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
{{ message }}
Repository navigation
js_class_method_bind: perry-stdlib's handle-property dispatch has the same interior-pointer bug in eight sub-dispatchers #8178
#8133 named four js_class_method_bind sites binding a movable heap string's interior. Fixing it (#8177) surfaced six in perry-runtime — and the same defect systemically in perry-stdlib's handle-property dispatch, where eight sub-dispatchers capture the forwarded name pointer directly.
The contract being violated
js_class_method_bind(instance, name_ptr, name_len) stores the name pointer in the bound closure's capture, and dispatch_bound_method (closure/dispatch/bound.rs:12) re-reads it at call time. So the pointer must outlive the bind — it cannot point into a movable GC heap string, whose contents are unreachable once a collection moves it.
Where it still happens
Eight sub-dispatchers in perry-stdlib forward the caller's pointer straight into the bind:
sqlite — four sites
tls — two sites
emitter_als — two sites
Reachable from ordinary code that stores a method rather than calling it:
Also found on perry-runtime's primitive-receiver arm ((5).toString), which #8177 did not cover.
Why this will not show up by accident
#8177 established the reproduction conditions, and they are narrow:
A literaldec.decode lowers to rodata and never reaches these arms at all. Only a computed key does — const k = "dec" + "ode"; obj[k].
Pre-fix, the symptom was a silent wrong answer: decode=undefined followed by a throw, where node prints decode=hi. No instrument fired.
Under PERRY_GC_ZEAL=1 PERRY_GC_PROTECT_FROMSPACE=1 it became a SIGBUS reported as RETIRED FROM-SPACE … retired_by_minor=#0.
So a test that binds a literal name and calls it immediately will pass on broken code. Any fixture here needs a computed key and enough allocation to actually move the string; #8177's used ~400k allocations.
Suggested shape
#8177's fix is worth copying rather than re-deriving: it replaced the is_timer_handle_method_keypredicate with a 'static-returning lookup and removed key_ptr/key_len from text_handle_property entirely. With no predicate and no pointer parameter, the bug is unwritable rather than merely fixed. The stdlib dispatchers can take the same treatment.
Related
#8133 (closed by #8177), #7747 (the first two sites), docs/src/internals/gc-rooting-invariant.md.
Activity