nx_registry_bounds_gate.nx source
↩ module page · 93 lines · 5033 B
1// nx_registry_bounds_gate.nx -- the regression tooth for the reg_index OUT-OF-BOUNDS
2// WRITE root-fixed 2026-07-31 (debt 1785506176).
3//
4// WHAT WENT WRONG: reg_index copied ss_get's length into the caller's buffer and
5// took NO capacity argument, so its signature could not express safety. MEASURED
6// LIVE: the mvault mv:ids index reached ~10.7 MiB (160269 ids x 70B) against a
7// 4 MiB buffer in nx_mvault do_stats -- the vault's own ruler segfaulted and
8// printed NOTHING -- and against an 8 MiB buffer in the /vault browse page.
9//
10// WHY THIS GATE EXISTS: the old defect was invisible to every test that only
11// checked the HAPPY path, because a copy that overruns still returns the right
12// number. So the load-bearing test here is T3/T6: a cap one byte too small must
13// REFUSE and must leave the byte just past the cap UNTOUCHED. That byte is
14// exactly what the pre-fix code clobbered, so this gate is PROVEN ABLE TO FAIL
15// rather than decorative -- revert nx_registry.nx and T3/T6 go red.
16// license_tier: ORIGINAL
17import "nx_registry.nx"
18import "nx_gate.nx"
19import "nx_gate_verdict.nx" // D001: canonical verdict emission + actlog frame
20
21const RB_PFX: *u8 = "knowledge/regbounds-test-\x00"
22const RB_KP: *u8 = "rb:\x00"
23const RB_IDX: *u8 = "rb:__idx__\x00"
24const RB_CANARY: i64 = 171
25
26func main() -> i64 {
27 gw("=== nx_registry_bounds_gate: reg_index refuses rather than overruns ===\n" as *u8)
28 var pass: i64=0; var tot: i64=0
29
30 // Seed a KNOWN index. reg_put is content-idempotent, so re-running this gate
31 // yields the same 12 bytes -- the expected length is derived, not guessed.
32 reg_put(RB_PFX, RB_KP, RB_IDX, "aaa" as *u8, "r1" as *u8, 2)
33 reg_put(RB_PFX, RB_KP, RB_IDX, "bbb" as *u8, "r2" as *u8, 2)
34 reg_put(RB_PFX, RB_KP, RB_IDX, "ccc" as *u8, "r3" as *u8, 2)
35 let want: i64 = 12
36
37 let n_len: i64 = reg_index_len(RB_PFX, RB_IDX)
38 tot=tot+1; if n_len==want { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
39 gw("T1 reg_index_len reports the true length without copying (" as *u8); gn(n_len); gw(")\n" as *u8)
40
41 let big: *u8 = sys_mmap(4096)
42 let n_ok: i64 = reg_index(RB_PFX, RB_IDX, big, 4096)
43 tot=tot+1; if n_ok==want { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
44 gw("T2 an ample cap copies the whole index (" as *u8); gn(n_ok); gw(" bytes)\n" as *u8)
45
46 // ---- THE TOOTH ----------------------------------------------------------
47 // cap is ONE BYTE short. The pre-fix code wrote all 12 bytes regardless, so
48 // buf[11] -- the canary -- was corrupted. Post-fix: refuse, write nothing.
49 let tight: *u8 = sys_mmap(4096)
50 var z: i64=0; while z<64 { tight[z]=RB_CANARY as u8; z=z+1 }
51 let n_ref: i64 = reg_index(RB_PFX, RB_IDX, tight, want - 1)
52 tot=tot+1; if n_ref==(0-1) { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
53 gw("T3 TOOTH a cap one byte short REFUSES with -1 (got " as *u8); gn(n_ref); gw(")\n" as *u8)
54
55 var clean: i64 = 1
56 var c: i64=0; while c<want { if tight[c]!=(RB_CANARY as u8) { clean=0 } c=c+1 }
57 tot=tot+1; if clean==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
58 gw("T4 TOOTH the refused call copied NOTHING -- no partial, no truncation\n" as *u8)
59
60 // Off-by-one guard in the OTHER direction: an exactly-fitting cap must NOT
61 // be refused, or the fix would trade an overflow for a false refusal.
62 let exact: *u8 = sys_mmap(4096)
63 let n_exact: i64 = reg_index(RB_PFX, RB_IDX, exact, want)
64 tot=tot+1; if n_exact==want { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
65 gw("T5 an EXACTLY-fitting cap succeeds (no false refusal)\n" as *u8)
66
67 // Two independent read paths must agree: the bounded copy and the zero-copy
68 // borrow. If they ever diverge, one of them is lying about the store.
69 let po: *i64 = sys_mmap(16) as *i64
70 let lo: *i64 = sys_mmap(16) as *i64
71 let found: i64 = reg_index_open(RB_PFX, RB_IDX, po, lo)
72 var same: i64 = 0
73 if found==1 { if lo[0]==n_ok {
74 same = 1
75 let src: *u8 = po[0] as *u8
76 var i: i64=0; while i<lo[0] { if src[i]!=big[i] { same=0 } i=i+1 }
77 } }
78 tot=tot+1; if same==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
79 gw("T6 zero-copy borrow returns BYTE-IDENTICAL content to the bounded copy\n" as *u8)
80
81 // An absent index is 0, not -1: "empty" and "does not fit" are different
82 // answers and a caller must be able to tell them apart.
83 let miss: i64 = reg_index(RB_PFX, "rb:__nosuchindex__" as *u8, big, 4096)
84 tot=tot+1; if miss==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
85 gw("T7 an ABSENT index returns 0, distinct from the -1 refusal\n" as *u8)
86
87 let ctr: *i64 = gv_ctr()
88 ctr[0] = pass
89 ctr[1] = tot
90 let rc: i64 = gv_verdict("REGINDEX-BOUNDS" as *u8, ctr, "reg_index is bounded, refuses rather than truncating, and both read paths agree" as *u8)
91 sys_exit(rc)
92 return rc
93}