v0.2.2
Added
-
Path-sensitive checked-pointer bounds propagation — a propagation
candidate that mixes checked-rooted and non-checked-rooted assignments
(int *q = malloc(...); if (c) q = p; q[i];) is no longer poisoned to
"never checked" for the whole function; it's classified "OPT" and its
snapshot temps are refreshed at every assignment, rooted or not (a
non-rooted store writes an explicit invalid sentinel instead of skipping
the refresh), plus seeded with the sentinel at function entry. A new
opcode,CHKRO, checks the snapshot but no-ops on the sentinel, soq[i]
is enforced exactly on the paths whereqactually holds a checked-rooted
value at runtime — decided per executed path with no CFG/join/fixpoint
analysis at all. Candidate registration also now covers an uninitialized
declaration (int *q;), which previously never became a candidate.
checked_prop_optionalpropagates transitively through a #941 chain, so a
candidate chained from an OPT source is itself OPT even when its own
single store is unconditionally rooted. A candidate whose every assignment
is checked-rooted ("FULL") is completely unaffected — sameCHKR, same
codegen as before. See
SAFETY.md § Checked Pointers (#942) -
Chained checked-pointer bounds propagation — a local that is itself
only propagated (never declared checked) can now act as a propagation
source for a further candidate:int *q = p + 2; int *r = q + 1; int *s = r + 1;now enforcess[i]too, not justq[i], chaining to arbitrary
depth. Decided by iterating #919's whole-function eligibility rule to a
fixpoint, seeded from declared-checked sources only and growing round over
round, so an unrooted cycle (q = r + 1; r = q + 1;) never self-validates.
A self-rooted reassignment (q = q + 1;) is now treated as neutral rather
than poisoningq, matching the existingq++/q += kbehavior. See
SAFETY.md § Checked Pointers (#941)
Fixed
CHKNTnow covers read-modify-write through an[[cccc::ntarray]]
terminator slot —s[n] += 1,s[n]++,s[n]--(and the_Atomic
compare-and-swap RMW form) previously bypassed #923's null-terminator
guard: the read-modify-write desugar's synthesized store never carried the
checked-pointer boundsCHKNTkeys off, so a non-null RMW into the
terminator slot silently corrupted the invariant even though the
equivalent direct assignment already trapped. See
SAFETY.md § Checked Pointers (#937)
Changed
- Struct/union member checked-pointer bounds evaluate their object
expression once per access, not once per bound —arr[k].p[i]used to
re-evaluatek's indexing arithmetic 2-4 times per checked access (once
forlo, once or twice forhidepending on the bounds form), since
building each bound re-cloned the member access's object expression
(arr[k]) from scratch. A non-trivial object expression (a runtime
index; not a bare local or plain member chain, which already cost
nothing to re-clone) is now hoisted into a single compiler-generated
temp shared by every bound of that access. Pure performance cleanup —
same checks, same traps, no user-visible behavior change. See
SAFETY.md § Checked Pointers (#945)