Skip to content

fix(hy-emit,hy-check): fix O8 slot-loan rebind/branch races and A3/T24 soundness gaps (#603) - #604

Open
sonson0910 wants to merge 1 commit into
limitlessprojects:mainfrom
sonson0910:fix/o8-slot-loan-rebind-branch-and-t24-soundness
Open

sonson0910 wants to merge 1 commit into
limitlessprojects:mainfrom
sonson0910:fix/o8-slot-loan-rebind-branch-and-t24-soundness

Conversation

@sonson0910

Copy link
Copy Markdown
Contributor

Summary

Closes three related P0 soundness holes in O8 slot-loan lowering (hy-emit) and A3/T24 slot-loan checking (hy-check):

  1. hy-emit (compiler/crates/hy-emit/src/stmt.rs, expr.rs, lib.rs):

    • Stop remaining_stmts_use_loan when an unshadowed Stmt::Assign (AssignOp::Assign) overwrites PlaceKind::Ident(name) (after checking RHS values and non-ident target sub-expressions), and delegate block_mentions_ident to remaining_stmts_use_loan so a plain-value or slot-loan rebind inside a block does not falsely keep the old loan alive past move m.
    • Hand off active slot loans into Stmt::If, Stmt::Block, and Stmt::Managed when the construct rebinds the loan variable or moves its base map, and update flush_loan_for_name to return the frame index so rebinding an outer slot loan to a new slot loan updates the loan in place after flushing the old slot.
    • Save and restore branch_inherit in emit_fn_lit (expr.rs) so closures evaluated inside an if condition do not consume the enclosing if statement's branch_inherit handoff.
    • Save and restore pointer_vars and shadowed_since_loan in save_scope / restore_scope (lib.rs) so inner-block shadowing does not leak into outer slot-loan flushes.
  2. hy-check (compiler/crates/hy-check/src/loans.rs):

    • Extend a3_path_is_prefix_or_eq so rebinding an enclosing struct container (h = holder{...}) while a slot loan on a nested field map (&h.m[k]) is live is rejected with HYB-E3102.
    • Invoke check_a3_method_or_inline_call from Resolved::Method and Resolved::None in process_call so user-defined methods (h.drop_a(), b.put(m)) and immediately-invoked closure literals ((fn(x) { delete(x, "a") })(m)) that mutate a map during a live slot loan are rejected with HYB-E3102.
  3. hy-check (compiler/crates/hy-check/src/addr_loan.rs):

    • Extend is_slot_loan_expr to recognize &s.field (Expr::Field) slot loans alongside &m[k] (Expr::Index), clear slot_loan on multi-return reassignments (n, ok = f()), and reject &n.arr[0] (Expr::Index projections rooted at a slot loan) with HYB-E3104 (T24).

Verification

  • cargo test --workspace --quiet
  • python3 tools/check_test_registration.py
  • python3 tools/check_conflict_markers.py
  • End-to-end hyb check, hyb generate, and CGO_ENABLED=1 CC=gcc go run -race . on reproducers

Fixes #603

@sonson0910
sonson0910 force-pushed the fix/o8-slot-loan-rebind-branch-and-t24-soundness branch from e231560 to 8b83602 Compare October 18, 2026 11:44
…4 soundness gaps

- hy-emit: stop remaining_stmts_use_loan at unshadowed Ident `=` rebinds so a plain-value rebind (`n = item{...}`) followed by reads of `n` does not keep the old slot loan alive past `move m` or emit a duplicate store-back of the rebound value into the map slot.
- hy-emit: hand off active slot loans into `if` / nested blocks that rebind the loan variable, and do not consume `branch_inherit` inside closures evaluated in an `if` condition.
- hy-emit: preserve `pointer_vars` and `shadowed_since_loan` across lexical block scopes so inner-block shadowing does not leak into outer slot-loan flushes.
- hy-check: reject container rebinds (`h = holder{...}`) during a live field-map slot loan (`&h.m[k]`) with HYB-E3102, and check user-defined methods and inline closure calls `(fn(x) { ... })(m)` for A3 map mutations during a live slot loan.
- hy-check: track `&s.field` slot loans and multi-return reassignments in `addr_loan.rs` (T24 HYB-E3104).
@sonson0910
sonson0910 force-pushed the fix/o8-slot-loan-rebind-branch-and-t24-soundness branch from 8b83602 to 6731250 Compare October 18, 2026 23:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

soundness(hy-emit,hy-check): O8 slot-loan rebind/branch store-back races and A3 container-rebind/method mutation bypasses

1 participant