nx_checked_arith.nx
buildroot/runtime/nx_checked_arith.nx
about
nx_checked_arith.nx -- LN1 CHECKED INTEGER ARITHMETIC fixture organ (lang.plan rung LN1, watch
symbol chk_add_overflow on /compare/lang row "Integer overflow checked (CWE-190 class)").
WHAT THIS IS. The runnable witness for the compiler's --chkarith declared mode: every i64
`+ - *` is followed by an overflow check that traps exit 72 (NX_TRAP_OVERFLOW) instead of
wrapping (nx_parse.nx, the LN1 block). Each phase is selected by argv so a single trap ends
exactly one phase and the gate (nx_chkarith_gate) can assert every outcome independently:
nx_checked_arith ok in-range add/sub/mul incl. the a==0 and a==-1 multiply paths
-> exit 0 under BOTH modes (the positive control: a deny mode that
refuses everything fails here)
nx_checked_arith add MAX + 1. Default build: WRAPS to MIN and keeps running (exit 0 only
if the wrapped value is observed -- anti-vacuity: the add executed).
--chkarith build: traps exit 72.
nx_checked_arith sub MIN - 1 -> wraps to MAX (default) / traps 72 (--chkarith).
nx_checked_arith mul 2^32 * 2^32 -> wraps to 0 (default) / traps 72 (--chkarith).
nx_checked_arith mulmin MIN * -1 -> wraps to MIN (default) / traps 72 (--chkarith) -- and
MUST NOT die of SIGFPE: the check's own division is branched around
for a == -1. Exit 72 is the only accepted outcome under the mode.
The wrap-by-intent intrinsics (__wrap_add/__wrap_sub/__wrap_mul) are witnessed by the sibling
nx_checked_arith_wrap.nx so that THIS file compiles on a pre-LN1 compiler too -- which is what
makes the gate's bite ATTRIBUTABLE: against the old compiler only the mode teeth go RED.
Operands are produced by FUNCTION CALLS, never literals or let-bound constants, so the runtime
legs exercise the RUNTIME check and not the compile-time refusal (that leg has its own sibling
witness, nx_checked_arith_const.nx).
license_tier: ORIGINAL No hw writes (Rule 26).
dependencies 1 imports · 0 importers
imports: nx_syscalls.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| none |
functions
| 33 | func ca_pow62() -> i64 called by 1: ca_max |
| 39 | func ca_max() -> i64 |
| 44 | func ca_min() -> i64 |
| 49 | func ca_pow32() -> i64 called by 1: ca_mul_overflow |
| 54 | func ca_pow31() -> i64 called by 1: ca_inrange_control |
| 59 | func ca_zero() -> i64 { return 0 } called by 1: ca_inrange_control |
| 60 | func ca_one() -> i64 { return 1 } |
| 61 | func ca_neg1() -> i64 { return 0 - 1 } |
| 65 | func chk_add_overflow() -> i64 |
| 70 | func ca_sub_overflow() -> i64 |
| 75 | func ca_mul_overflow() -> i64 |
| 80 | func ca_mulmin_overflow() -> i64 |
| 88 | func ca_inrange_control() -> i64 |
| 107 | func main(argc: i64, argv: *i64) -> i64 |