Repository navigation
fix(codegen): keep scope groups out of a later switch case (#11771) - #11774
Conversation
The scope-context dominance test compared references against the home list's end inclusively, but list_end is one past the last statement -- the next statement's number. For a switch case that is the first statement of the following case, which shares the binding's scope but skips its let. The binding was grouped, case 2 read the never-allocated scope root (TAG_UNDEFINED) as a pointer, and the #4926 fixture SIGSEGVed. Make the bound exclusive so such bindings keep their entry-initialized per-binding cell.
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (3)
Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 6 remain after this review. 📝 WalkthroughWalkthroughScope analysis now uses an exclusive statement-list end when determining whether declarations and references belong to a binding’s dominance interval. Regression tests cover skipped switch-case bindings and an in-list control case. ChangesScope-context switch-case dominance
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix · Severity of issue fixed: Medium Merge Risk: ⚪ Minimal · up to No actionable merge-blocking issue is identified; the change is mergeable after normal checks. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to The change conservatively narrows an optimization and directs skipped-initialization cases through existing guarded storage access. No introduced security concern was identified in the inspected paths, but broader specialized execution paths were not fully verified. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Closes #11771
Root cause
scope_env::analysisnumbers statements in pre-order and admits a binding to a scope context object only when every reference sits in[home, end(home list)].list_endis recorded as the counter after the list, i.e. one past its last statement — the number of the next statement — butdominating_homecompared it inclusively (hi > endrejects, sohi == endpassed).For a switch case, the next statement is the first statement of the following case, which is in the binding's lexical scope but skips its
let. In the #4926 fixture (case 1: let x …; case 2: return typeof x)xwas grouped, its scope object is allocated only by case 1'sPreallocateBoxes, and entering at case 2 loaded the group root's entry value (TAG_UNDEFINED) and dereferenced it (vmovsd (%rax)withrax = 0x7ffc000000000001inreadSkipped$spec_i32).Fix
Make the bound exclusive (
>= end) for both declarations and references, and documentlist_endas exclusive. Such a binding falls back to its per-binding cell, whose frame slot is entry-initialized (#4926), so the skipped read isundefinedand the skipped write a no-op, as before #11710. No GC-visible change: no new raw pointer, the group/cell paths themselves are unchanged.Validation (perrymaster, dev profile)
cargo test -p perry --test issue_4926_boxed_slot_skipped_init: SIGSEGV (139) before, passes after.scope_envunit tests: the next-case read (pass shape and the loweredPreallocateBoxes-in-case shape) is refused, and a reference in the home list's last statement still groups. Both refusal tests fail with the old comparison.cargo test -p perry-codegen --lib: 1852 passed.loop_lexical_tdz, whosecommonjs-default-O0arm fails identically with the fix reverted (exception transport failed (reason=3)on this Linux dev build), so it is pre-existing and unrelated.test_gap_gc_scope_*,test_gap_gc_box_cells,test_gap_10464_box_cell_release,test_gap_*tdz*,test_gap_*switch*,test_gap_closures, …) underPERRY_GC_FORCE_EVACUATE=1 PERRY_GC_VERIFY_EVACUATION=1match Node byte-for-byte.cargo fmt --all -- --check,RUSTFLAGS="-D warnings" cargo check -p perry -p perry-codegen -p perry-runtime --tests.Summary by CodeRabbit
Bug Fixes
Tests