Skip to content

v0.2.2

Choose a tag to compare

@github-actions github-actions released this 08 Aug 15:26
· 15 commits to trunk since this release

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, so q[i]
    is enforced exactly on the paths where q actually 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_optional propagates 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 — same CHKR, 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 enforces s[i] too, not just q[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 poisoning q, matching the existing q++/q += k behavior. See
    SAFETY.md § Checked Pointers (#941)

Fixed

  • CHKNT now 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 bounds CHKNT keys 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-evaluate k's indexing arithmetic 2-4 times per checked access (once
    for lo, once or twice for hi depending 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)