Found in a loaded mass run of the perry-runtime lib suite (7 workers x 30 full-suite runs, release, RUST_TEST_THREADS=1, on main a15b224 plus the test-only #11363). It crashed 1 time in 210 runs.
Crash. SIGSEGV mid-test in async_hooks::test_support::tests::native_async_resource_accepts_string_and_symbol_expandos, in this stack:
get_accessor_descriptor <- exotic_set_property (crates/perry-runtime/src/object/exotic_expando.rs) <- js_put_value_set
The faulting address is 0x4010000000000010, which is the double 4.0 plus 16, dereferenced as a pointer. So a NaN-boxed number, or an unboxed f64, reached a descriptor probe as the owner address.
Likely class. This looks like the set-path sibling of the #11338 fix. That fix made the handle_expando get path use handle-owner probes, which never read the owner's memory, because a native AsyncResource Box address passed to get_accessor_descriptor let descriptor_summary_meta read owner - 8 as a GcHeader. exotic_set_property calls get_accessor_descriptor(addr, ..) directly at several sites (lines ~324/376/408/424). If addr, or a prototype address it walks to, is ever a native handle, a Box, or a non-pointer, the probe reads arbitrary memory. Whether that crashes depends on layout, hence 1 in 210.
To do.
- Find how a value like 4.0 becomes
addr or proto_addr. It could be a prototype-chain read that returns a non-object, or an expando value being mistaken for a prototype.
- Route non-GC owners through the handle-owner probes (
get_handle_accessor_descriptor etc.), or validate the owner before probing.
- Add a deterministic regression test.
Found in a loaded mass run of the perry-runtime lib suite (7 workers x 30 full-suite runs, release,
RUST_TEST_THREADS=1, on main a15b224 plus the test-only #11363). It crashed 1 time in 210 runs.Crash. SIGSEGV mid-test in
async_hooks::test_support::tests::native_async_resource_accepts_string_and_symbol_expandos, in this stack:The faulting address is
0x4010000000000010, which is the double4.0plus 16, dereferenced as a pointer. So a NaN-boxed number, or an unboxed f64, reached a descriptor probe as the owner address.Likely class. This looks like the set-path sibling of the #11338 fix. That fix made the
handle_expandoget path use handle-owner probes, which never read the owner's memory, because a nativeAsyncResourceBox address passed toget_accessor_descriptorletdescriptor_summary_metareadowner - 8as aGcHeader.exotic_set_propertycallsget_accessor_descriptor(addr, ..)directly at several sites (lines ~324/376/408/424). Ifaddr, or a prototype address it walks to, is ever a native handle, a Box, or a non-pointer, the probe reads arbitrary memory. Whether that crashes depends on layout, hence 1 in 210.To do.
addrorproto_addr. It could be a prototype-chain read that returns a non-object, or an expando value being mistaken for a prototype.get_handle_accessor_descriptoretc.), or validate the owner before probing.