Skip to content

-mm=own: a read of a global ends at a call that may assign the global - #661

Merged
ASDAlexander77 merged 4 commits into
mainfrom
own-global-read-callee-assigns
Oct 23, 2026
Merged

ASDAlexander77 merged 4 commits into
mainfrom
own-global-read-callee-assigns

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Follow-up 11 from the own-raytrace rulings ("own accepts a callee that assigns a global after the caller took a const read of it").

Bug

const c = G; reset(); print(c.x) with reset() { G = new V(1); }: the read borrows what G holds and the call frees it while c still reads it. own accepted it and read freed memory (exit 139 on current main), also through a further call (step() calling reset()). checkGlobalRead (#655) ended such a read only at a store to the global in the same function.

Fix

  • OwnershipSignaturePass::pinAssignedGlobals (after computeDrops): the globals each function may give a new value - a store to the global or its release in its body, or in a call it makes, to a fixpoint - pinned on each call as __own_assigns_globals (names). A call that may drop and whose callees are not known gets __own_assigns_any_global; one that drops nothing (callMayDrop false: imported, .instanceOf, no-drop callees) gets nothing.
  • checkGlobalRead counts such a call among the read's ends, beside same-function stores, so the existing "'c' borrows 'G' but is used here after 'G' is released or overwritten" fires, with the note at the call. A read handed to that call as an argument stays A global lent to a call that assigns it: rc holds a count, own rejects #639's.

Tests

  • own negatives: own_err_global_read_callee_assigns, ..._transitive.
  • own/own_global_read_callee_other.ts under own, rc, none, gc: calls that assign only another global, or none, stay accepted and correct.
  • Tooth: on main own accepts the probe and exits 139.

Verified

  • Windows Release: 5288/5288 (no new rejection anywhere in the corpus, the ray tracer included).
  • Linux (WSL): 5270/5270; the new tests again under MALLOC_PERTURB_=165 MALLOC_CHECK_=3: 8/8.

🤖 Generated with Claude Code

ASDAlexander77 and others added 4 commits October 23, 2026 10:04
`const c = G; reset(); print(c.x)`, where `reset` does `G = new V(1)`:
the read borrows what `G` holds, and the call frees it while `c` still
reads it. own accepted it and read freed memory (exit 139), also when
the assignment is a call further down (`step()` calling `reset()`).
checkGlobalRead (#655) ended such a read only at a store to the global
in the same function; follow-up 11.

OwnershipSignaturePass pins on each call the globals it may give a new
value (pinAssignedGlobals): a store to the global, or its release, in a
callee or in a call it makes, to a fixpoint; a call that may drop and
whose callees are not known may assign any, one that drops nothing
assigns none. checkGlobalRead counts such a call among the read's ends.
A read handed to that call as an argument stays #639's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit 9e0e387 into main Oct 23, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the own-global-read-callee-assigns branch October 23, 2026 10:21
ASDAlexander77 added a commit that referenced this pull request Oct 23, 2026
…n that global (#678)

#639 refused any call that might drop anything once a value read out of an
assigned global was lent to it, though only a store to the global releases its
block: `G = new N(2); other(G)`, where other assigns H, was rejected. The check
now reads what pinAssignedGlobals (#661) put on the call, which runs before it:
it refuses a call that may assign that global, or one it cannot name (an
indirect call, a callee calling one), and lends to any other. A callee that
assigns the global itself, through another function, a method or a function
value is still refused.

own_err_global_kept_field is now refused by checkGlobalRead, which it was
written for: `keep` stores the lent value into a field that outlives the next
assignment of `g`; its pinned message follows. Tests: own_global_argument_other_global
under every model, own_err_global_argument_indirect. Own corpus unchanged (533).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant