diff --git a/CHANGES.md b/CHANGES.md index dd1b8f9b8..c7c5c2551 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,7 +10,12 @@ Features Bug Fixes --------- +* [#1740](https://github.com/java-native-access/jna/issues/1740): Fix `c.s.j.p.unix.solaris.LibKstat.KstatCtl` mapping `kc_chain` as an inline `Kstat` instead of a pointer, which made every call taking a `KstatCtl` write past the end of the structure `kstat_open()` allocated, and map the `Kstat` function pointers `ks_update` and `ks_snapshot` as `Pointer` instead of `int` - [@dbwiddis](https://github.com/dbwiddis). +Breaking Changes +---------------- +* `c.s.j.p.unix.solaris.LibKstat.KstatCtl#kc_chain` is now a `Pointer` instead of a `Kstat`. Use `KstatCtl#chain()` to get the head of the kstat chain as a `Kstat`. The previous mapping never returned usable data: the inline `Kstat` decoded the native chain pointer as its `ks_crtime` timestamp, and every following field from bytes past the end of the native structure, so code that read this field could not have relied on it. +* `c.s.j.p.unix.solaris.LibKstat.Kstat#ks_update` and `Kstat#ks_snapshot` are now `Pointer` instead of `int`, matching the native function pointers. The structure layout is unchanged, but the previous mapping held only half of a kernel-only address, which has no meaning in user space. Release 5.19.1 ============== diff --git a/contrib/platform/src/com/sun/jna/platform/unix/solaris/LibKstat.java b/contrib/platform/src/com/sun/jna/platform/unix/solaris/LibKstat.java index 06db040f5..7e9b2043f 100644 --- a/contrib/platform/src/com/sun/jna/platform/unix/solaris/LibKstat.java +++ b/contrib/platform/src/com/sun/jna/platform/unix/solaris/LibKstat.java @@ -132,22 +132,28 @@ class Kstat extends Structure { public long ks_snaptime; // time of last data snapshot // Fields relevant to kernel only - public int ks_update; // dynamic update function + public Pointer ks_update; // dynamic update function public Pointer ks_private; // provider-private data - public int ks_snapshot; // snapshot function + public Pointer ks_snapshot; // snapshot function public Pointer ks_lock; // protects this kstat's data + public Kstat() { + super(); + } + + public Kstat(Pointer p) { + super(p); + read(); + } + public Kstat next() { if (ks_next == null) { return null; } - Kstat n = new Kstat(); - n.useMemory(ks_next); - n.read(); - return n; + return new Kstat(ks_next); } } @@ -350,16 +356,28 @@ public KstatIO(Pointer p) { /** * A kstat control structure. Only one thread may actively use a KstatCtl * value at any time. Synchronization is left to the application. + *

+ * Oracle Solaris 11.4 appends a fourth field, {@code void **kc_private}, + * which is private to libkstat. It is deliberately not mapped: this + * structure only ever wraps the pointer returned by {@code kstat_open()}, + * so mapping the three public fields reads and writes a prefix of the + * native structure on every release, and leaves the private field alone. */ @FieldOrder({"kc_chain_id", "kc_chain", "kc_kd"}) class KstatCtl extends Structure { public int kc_chain_id; // current kstat chain ID - public Kstat kc_chain; // pointer to kstat chain + public Pointer kc_chain; // pointer to kstat chain public int kc_kd; // /dev/kstat descriptor - not public interface + public Kstat chain() { + if (kc_chain == null) { + return null; + } + return new Kstat(kc_chain); + } } /**