Skip to content

v0.2.3

Choose a tag to compare

@github-actions github-actions released this 08 Aug 19:08
· 11 commits to trunk since this release

Added

  • CHKNT's null-terminator guard now covers float/double, struct/
    union, and wide _BitInt/_Decimal ntarray pointees
    — previously
    only integer and pointer pointees were guarded (a deliberate v1
    exclusion, #923). Investigating the exclusion for a decision pass turned
    up an actual hole: _BitInt(128) passed the old is_integer() gate and
    set the guard flag, but its store lowers through codegen's memcpy branch,
    which returned before the old CHKNT-only emission site — so the flag
    was set and nothing was ever checked. float/double now reuse CHKNT
    itself (their value's raw bits are transferred into an integer register
    first). A new opcode, CHKNTZ, guards the memcpy-lowered pointees
    (struct/union, wide _BitInt, _Decimal) that never pass through a
    single value register: it scans the source bytes for any non-zero byte
    before the underlying memcpy runs, so the terminator slot is never
    actually clobbered when it traps. long double stays unguarded on
    purpose — its widened terminator slot is 16 bytes but the actual store is
    an 8-byte flat-double FSTR, so no opcode inspects its full stored
    representation. CHKNTZ only guards a whole-object store through the
    pointer itself; a member-wise write into the same slot (tbl[n].a = 1;)
    is a known, separately-tracked gap (#950). See
    SAFETY.md § Checked Pointers and
    VM.md § Safety Opcodes (#939)

Fixed

  • node_has_side_effects() now sees through a ternary's branches
    ND_COND (the cond ? then : els ternary) stores its two branches in
    ->then/->els, separately from ->lhs/->rhs, and the side-effect
    check that gates checked-pointer bounds declarations
    (resolve_bounds_tokens()) and member object-expression instrumentation
    (compute_checked_bounds(), #921/#945/#947) never recursed into them —
    so count(c ? i++ : 3) was wrongly accepted, and i++ would have run on
    every checked access instead of never. Now rejected at the declaration,
    same as count(i++). See
    SAFETY.md § Checked Pointers (#949)
  • GNU elvis (a ?: b) no longer forces a compiler temp when the
    condition is a plain, cheaply re-readable operand
    a ?: b always
    desugared to tmp = a, tmp ? tmp : b, whose ND_ASSIGN made a pure
    elvis bounds expression like count(n ?: 8) fail the check above even
    though it has no side effects. When a is an ND_VAR/ND_NUM and not
    volatile/_Atomic, the desugar now builds a ? clone(a) : b directly
    instead, which reads as side-effect-free; every other condition shape
    keeps the original temp-based desugar. See
    SAFETY.md § Checked Pointers (#949)

Changed

  • Checked-pointer bounds propagation and assignment-time bounds
    implication also evaluate a member object expression once per
    assignment
    q = arr[k].p; (bounds propagation) and arr[k].p = src;
    (assignment-time bounds implication) used to re-evaluate k's indexing
    arithmetic 2-3 times while building that one assignment's bounds, the
    same duplication #945 already fixed for a direct per-access check. Both
    passes now share #945's hoist-into-a-temp treatment via a second temp
    allocator, needed because they run after their function's own local-list
    snapshot. Pure performance cleanup — same checks, same traps, no
    user-visible behavior change. See
    SAFETY.md § Checked Pointers (#947)

Documented

  • Why a side-effecting member object expression stays uninstrumented
    f()->p[i] is declined by checked-pointer bounds checking (no check
    emitted) because the hoist introduced by #945/#947 rewrites the bounds
    expressions
    , not the access itself: f()->p[i]'s own access still calls
    f() once regardless, so emitting a check would call it again just to
    build the hoisted object-expression temp — an extra evaluation of a
    side-effecting expression that a --checked-pointers build must never
    introduce over a default build. See
    SAFETY.md § Checked Pointers (#948)