Repository navigation
-mm=own: a local lent to a call cannot be assigned before the call takes it - #660
Merged
Merged
Conversation
…s it `g(n, (n = mk(2), 0))`: the arguments are read in order, so the first read `n` and the second gave `n` a new value before the call took the first - and under rc that assignment released the block the callee then read (exit 139, or garbage). The same with a field or an element of a local (`g(h.v, (h.v = mk(), 0))`, also of a folded `const h = new H()`), a conditional argument (its own blocks), a call in a try body, an assigned parameter, and a closure called there that assigns a captured local. Follow-ups 7 and the rc half of 8 (fuzzer A1, local form). holdGlobalArguments now also holds such an argument, as it holds one read out of a global (#647): retained right after the read, released after the call (and in the handler of a try that takes what the call throws). It holds a read of a local when a store into that local, a place in it, or its release - or any call, for a captured local - lies on a path from the read to the call (own_facts::findBetween). The retain goes right after the read also when a conditional argument put the call in a later block of the same region, unless a loop leads back. own still accepts the local forms; that is the own half of follow-up 8. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…signs it `g(s, (s = new Shared(new V(2)), 0))` with `s` a local handle: the assignment gave back the count the old handle held, the last one, and `g` read the freed block. Handles are counted under own too, and the previous commit held such a read under rc only, while own's new check leaves handles to the counts - so own read freed memory. The hold now applies to a handle under own as well, as holdGlobalArguments already does for a handle read out of a global. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…kes it `g(n, (n = mk(2), 0))`: the first argument borrows `n`'s object, and the second gives `n` a new value first, which drops that object before `g` reads it. own accepted it and read freed memory - also through a conditional argument (`g(n, c ? (n = mk(), 0) : 1)`), in a try body, and with a closure called there that assigns a captured `n`. Follow-up 8, own half (fuzzer A1, local form); rc holds such an argument instead (the parent commit). checkArgumentsAssigned rejects an argument read out of an owning local when a store into that local's slot, or its release - or a call, when a closure built over the local assigns it - lies on a path from the read to the call (own_facts::findBetween). A read of a global is already checkGlobalRead's; a store into a field of the local, the place borrows'. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ASDAlexander77
force-pushed
the
own-argument-slot-assigned
branch
from
October 23, 2026 09:18
376b09c to
6e7f8ff
Compare
#653 added a same-block check for an argument whose slot or place a later argument overwrites (overwrittenBeforeCall); it runs before localAssignedBefore, which still covers a conditional argument, a closure assigning a captured local, a field of a folded const, and a handle under own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nt-slot-assigned Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up 8 from the own-raytrace rulings, own half (fuzzer A1, local form). Stacked on #657 (it uses that PR's
own_facts::findBetween/slotOf): merge #657 first; until then this PR's diff shows both commits.Bug
g(n, (n = mk(2), 0)): the first argument borrowsn's object and the second givesna new value first, which drops that object beforegreads it. own accepted it and read freed memory (garbage, or exit 139 on Linux), also through a conditional argument, in a try body, and with a closure called there that assigns a capturedn. On current main (with #655) own still accepted every local form; the global form (f2(G, (G = mk(2), G))) is already rejected by #639 / checkGlobalRead, and the field form by the place-borrow rule.Fix
checkArgumentsAssigned(OwnershipInferencePass) rejects an argument read out of an owning local when a store into that local's slot, or its release - or a call, when a closure built over the local assigns it (OWN_ASSIGNS_CAPTURES_ATTR_NAME) - lies on a path from the read to the call:'n' is lent to 'g', but is given a new value before the call takes it; -mm=own cannot prove it outlives the call, with a note at the assignment. A closure that only reads the captured local, or an assignment of another local, stays accepted.Tests
own_err_argument_assigned,..._conditional,..._closure.Verified (this branch, both commits)
MALLOC_PERTURB_=165 MALLOC_CHECK_=3: 6/6.🤖 Generated with Claude Code
Update
Merged #657's branch (now with main through #656). Windows 5315/5315; Linux 5297/5297, the new tests 20/20 under
MALLOC_PERTURB_=165 MALLOC_CHECK_=3.