Skip to content

fix(gc): re-read imported-ctor args, root the key-add receiver, refuse ConstFn finalize on a keys-identity miss - #11783

Merged
proggeramlug merged 2 commits into
mainfrom
fix/11680-audit-gc-fixes
Oct 3, 2026
Merged

proggeramlug merged 2 commits into
mainfrom
fix/11680-audit-gc-fixes

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

GC-safety and crash fixes from the audit of #11680.

H1: imported-constructor arguments. Positional arguments and the values pushed into rest/arguments arrays were read before js_array_alloc and js_class_value, both of which can move objects. The whole-function root_reload pass happened to re-read them in the emitted IR, which is why nothing broke so far and why the old test couldn't fail. Each positional argument is now named by its index in the root group and re-read at dispatch, and each pushed value is re-read before its push. The test checks every use against every collecting call, compiling with root_reload disabled (a #[cfg(test)] switch) so it exercises the lowering itself.

M2: publish_key_add_edge. The gc_call_effects graph shows the key-add mint can collect: for example set_object_keys_with_live_rep → js_array_length → js_number_coerce. The receiver was still written through a raw pointer after the mint. It is now rooted and re-read after each publish. The false "cannot collect" comment in the finalizer is corrected. The test uses a #[cfg(test)] hook that collects after each publish, runs under forced evacuation with the verifier, and checks the moved receiver.

M1: ConstFn finalizer abort. A receiver with the same key names as the seeded record but a different keys array aborted the process, despite the doc saying refusals leave the receiver untouched. The finalizer now compares the whole record, including keys-array identity, before minting under the requested id, and otherwise refuses. Covered by a child-process test.

Sabotage: reverting each fix turns its own test red.

Verification

Check Result
perry-runtime (RUST_TEST_THREADS=1, perry-dev) 4814/0
perry-codegen green except manifest_consistency, which fails on main since #11757
gc-root-dominance corpus 0 violations, 40/40 seeded caught, unrooted-allocas 0
two-module imported-ctor fixture matches node under forced evacuation + verifier
gap new / ctor / class green apart from known entries
fmt, file size pass

M3, unifying the ConstFn admission rules, is left for a follow-up: it needs a design decision about the closure-value exclusions.

Summary by CodeRabbit

  • Bug Fixes
    • Improved reliability of imported constructor arguments when garbage collection occurs during argument processing, including arguments packed into rest or arguments arrays.
    • Fixed key additions involving constant functions so receivers and function values remain valid if garbage collection occurs during publication.
    • Static constant-function finalization now checks that the full shape matches before stamping it. Mismatches leave the receiver unchanged instead of aborting.

Ralph Küpper added 2 commits October 3, 2026 08:04
…e ConstFn finalize on a keys-identity miss

Three findings from the #11680 audit.

H1: an imported constructor's positional arguments and the values pushed
into its rest/arguments arrays were register snapshots taken before
js_array_alloc, the pushes and the class-value lookup. ImportedCtorArg
now names a group operand, every push re-reads its element from its
root, and the dispatch re-reads every positional argument. The
root_reload pass was masking this in the emitted IR, so the test now
also runs with that pass off (test-only seam) and checks every pushed
value and the positional operand against each collecting call.

M2: publish_key_add_edge wrote the ConstFn prewrite, the SPECIAL stamp
and the convergence through the pre-mint receiver. The GC call-effects
graph cannot prove a mint non-collecting, so the receiver is rooted and
re-read after each publication. The finalizer comment that called the
mint non-collecting is corrected. The test arms a cfg(test) collection
after each publication under forced evacuation and the evacuation
verifier.

M1: the static ConstFn finalizer aborted the process when a receiver
had the same key names as the record seeded under the requested id but
a different keys array. It now compares the complete record, keys
identity included, before minting: a match is stamped and anything else
is a refusal that leaves the receiver untouched.
@proggeramlug proggeramlug added the run-extended-tests Opt PR into compile-smoke/parity/doc-tests/drizzle-mysql-smoke label Oct 3, 2026
@coderabbitai

coderabbitai Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 60e2b55e-36ee-4840-9d38-529dbbf42f83
📥 Commits

Reviewing files that changed from the base of the PR and between f6c873d and 984151b.

📒 Files selected for processing (9)
  • changelog.d/11783-audit-gc-fixes.md
  • crates/perry-codegen/src/expr/collecting_root_tests.rs
  • crates/perry-codegen/src/lower_call/new.rs
  • crates/perry-codegen/src/lower_call/new_ctor_args.rs
  • crates/perry-codegen/src/root_reload.rs
  • crates/perry-runtime/src/object/constfn_key_add_tests.rs
  • crates/perry-runtime/src/object/field_rep_store.rs
  • crates/perry-runtime/src/object/static_shapes.rs
  • crates/perry-runtime/src/object/static_shapes_tests.rs
 __________________
< X marks the bug. >
 ------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@proggeramlug
proggeramlug merged commit b1bc839 into main Oct 3, 2026
41 of 45 checks passed
@proggeramlug
proggeramlug deleted the fix/11680-audit-gc-fixes branch October 3, 2026 08:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-extended-tests Opt PR into compile-smoke/parity/doc-tests/drizzle-mysql-smoke

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant