You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up to #4898 / PR #4902 (deferred there by design).
Summary
PR #4902 added a runtime gate (is_registered_box_ptr) so js_box_set/js_box_get silently skip pointers that were never minted by js_box_alloc. That makes the react-reconciler SIGBUS correctness-safe, but the source bug is still present: codegen can emit a js_box_set call whose box-pointer operand is undef/poison — a mutable-capture box whose allocation was elided on the taken path while the store survived.
Faulting site (pre-fix(runtime): reject unregistered box pointers in js_box_set/get (#4898) #4902): str d0,[x0] inside js_box_set with x0 = &"object_get_by_name_guard" — a read-only __TEXT.__cstring typed-feedback guard-name constant (chore: triage dead-code warnings (fields, variants, constants, dead assignments) #854register_site arg). The module IR never stores into any guard global (verified across all --trace llvm modules; all 8292 guard uses in the react-reconciler production module are register_site args). The stray pointer is a pure optimizer/regalloc artifact of an undef operand: regalloc fills the register with whatever happens to be live, and react-reconciler's single giant minified module.exports = function($$$config){…} emits ~2500 register_site calls in one function, so a guard cstring pointer is what's live.
An undef operand reaching a call means LLVM proved the box-pointer SSA value undefined on some path — i.e. a path exists where the capture box was never allocated/stored but js_box_set for that capture is still reachable.
(test-files/ink-sandbox/rr_min.tsx). Pre-#4902 this SIGBUSed at module init. Post-#4902 the bad call is silently skipped — so the localization handle is the rejection itself: an env-gated diagnostic in the is_registered_box_ptr failure arm (print/abort) should fire on this repro and identify the first offending site.
Suggested attack
Add a temporary PERRY_BOX_DIAG=1 (or reuse PERRY_GC_DIAG) print/trap in the js_box_set/js_box_get unregistered-pointer arm to confirm the stray call still occurs on main and capture a backtrace.
Audit closure-conversion / codegen paths where a capture's box alloc is conditional (lazy alloc, dominance assumption) while the corresponding js_box_set is emitted unconditionally — likely a dominance bug: alloc emitted in a block that doesn't dominate the store.
Fix so every emitted js_box_set/js_box_get operand is dominated by its js_box_alloc (or the alloc is hoisted), then verify the diagnostic no longer fires on the react-reconciler repro.
Likely same root family as #2564 (captured Object.assign alias → HostRoot hang).
Follow-up to #4898 / PR #4902 (deferred there by design).
Summary
PR #4902 added a runtime gate (
is_registered_box_ptr) sojs_box_set/js_box_getsilently skip pointers that were never minted byjs_box_alloc. That makes the react-reconciler SIGBUS correctness-safe, but the source bug is still present: codegen can emit ajs_box_setcall whose box-pointer operand is undef/poison — a mutable-capture box whose allocation was elided on the taken path while the store survived.Evidence (from the #4898 deep-triage)
str d0,[x0]insidejs_box_setwithx0 = &"object_get_by_name_guard"— a read-only__TEXT.__cstringtyped-feedback guard-name constant (chore: triage dead-code warnings (fields, variants, constants, dead assignments) #854register_sitearg). The module IR never stores into any guard global (verified across all--trace llvmmodules; all 8292 guard uses in the react-reconciler production module areregister_siteargs). The stray pointer is a pure optimizer/regalloc artifact of an undef operand: regalloc fills the register with whatever happens to be live, and react-reconciler's single giant minifiedmodule.exports = function($$$config){…}emits ~2500 register_site calls in one function, so a guard cstring pointer is what's live.js_box_setfor that capture is still reachable.Repro
(
test-files/ink-sandbox/rr_min.tsx). Pre-#4902 this SIGBUSed at module init. Post-#4902 the bad call is silently skipped — so the localization handle is the rejection itself: an env-gated diagnostic in theis_registered_box_ptrfailure arm (print/abort) should fire on this repro and identify the first offending site.Suggested attack
PERRY_BOX_DIAG=1(or reusePERRY_GC_DIAG) print/trap in thejs_box_set/js_box_getunregistered-pointer arm to confirm the stray call still occurs on main and capture a backtrace.js_box_setis emitted unconditionally — likely a dominance bug: alloc emitted in a block that doesn't dominate the store.js_box_set/js_box_getoperand is dominated by itsjs_box_alloc(or the alloc is hoisted), then verify the diagnostic no longer fires on the react-reconciler repro.Likely same root family as #2564 (captured
Object.assignalias → HostRoot hang).