Summary
Follow-up to #5976. That issue's SIGSEGV came from get_valid_func_ptr (closure/dispatch/validate.rs) dereferencing a NaN-boxed small-handle id as a ClosureHeader — it floored the candidate address at 0x1000, which is well below HANDLE_BAND_MAX (0x100000), so a revocable-proxy id (POINTER_TAG | 0xF0000+id) reached the *(addr + 12) CLOSURE_MAGIC probe and faulted.
Three ad-hoc CLOSURE_MAGIC probes still carry the same 0x1000 floor and crash the same way when a Proxy value is stored where a closure is expected:
crates/perry-runtime/src/symbol/iterator.rs:444 — the Symbol.toPrimitive method probe
crates/perry-runtime/src/symbol/properties.rs:570 and :614 — js_object_set_symbol_method
crates/perry-runtime/src/jsx.rs:307 — is_valid_closure (JSX function component)
(json/stringify.rs, builtins/arithmetic.rs (typeof) and object/object_ops/accessors.rs already reject the band — see #1843 / #4004 / #4800 / #4904.)
Repro
const fn1 = (): string => "prim";
const obj: any = {};
obj[Symbol.toPrimitive] = new Proxy(fn1, {});
console.log("toPrimitive:", `${obj}`);
console.log("END");
Perry: SIGSEGV, rc 139 — EXC_BAD_ACCESS at 0x000f000d (proxy id 1 at PROXY_ID_BAND_START + 1, plus the 12-byte CLOSURE_TYPE_TAG_OFFSET).
Node: toPrimitive: prim / END.
Notes
Unlike #5976 (whose dynamic-construct path already had a correct Proxy branch three checks below the faulting probe, so a band guard alone restores full spec behavior), these sites have no proxy-aware fallback: a band guard here stops the crash but yields "not a closure", not a trap dispatch. The proper fix routes a proxy-valued method through js_native_call_value / the Proxy [[Call]] path instead of the raw closure call — hence a separate issue rather than folding it into #5976.
Summary
Follow-up to #5976. That issue's SIGSEGV came from
get_valid_func_ptr(closure/dispatch/validate.rs) dereferencing a NaN-boxed small-handle id as aClosureHeader— it floored the candidate address at0x1000, which is well belowHANDLE_BAND_MAX(0x100000), so a revocable-proxy id (POINTER_TAG | 0xF0000+id) reached the*(addr + 12)CLOSURE_MAGIC probe and faulted.Three ad-hoc CLOSURE_MAGIC probes still carry the same
0x1000floor and crash the same way when a Proxy value is stored where a closure is expected:crates/perry-runtime/src/symbol/iterator.rs:444— theSymbol.toPrimitivemethod probecrates/perry-runtime/src/symbol/properties.rs:570and:614—js_object_set_symbol_methodcrates/perry-runtime/src/jsx.rs:307—is_valid_closure(JSX function component)(
json/stringify.rs,builtins/arithmetic.rs(typeof) andobject/object_ops/accessors.rsalready reject the band — see #1843 / #4004 / #4800 / #4904.)Repro
Perry: SIGSEGV, rc 139 —
EXC_BAD_ACCESS at 0x000f000d(proxy id 1 atPROXY_ID_BAND_START + 1, plus the 12-byteCLOSURE_TYPE_TAG_OFFSET).Node:
toPrimitive: prim/END.Notes
Unlike #5976 (whose dynamic-construct path already had a correct Proxy branch three checks below the faulting probe, so a band guard alone restores full spec behavior), these sites have no proxy-aware fallback: a band guard here stops the crash but yields "not a closure", not a trap dispatch. The proper fix routes a proxy-valued method through
js_native_call_value/ the Proxy[[Call]]path instead of the raw closure call — hence a separate issue rather than folding it into #5976.