code wiki / _hdl_build / nx_doc_ubscan_gate.nx
nx_doc_ubscan_gate.nx source
↩ module page · 51 lines · 3309 B
1import "nx_gate_gn.nx"
2// nx_doc_ubscan_gate.nx -- liar-kill gate for the UB cast-then-index detector (the recycler's CONVERT of the
3// undefined-behavior critique). MUST-FLAG: the dangerous inline `(EXPR as *T)[i]` (incl. inside a call). MUST-NOT-
4// FLAG: the SAFE bind-then-index (`let p = ... as *T; p[i]`), a plain cast with no index, and a paren-index with no
5// cast. Grounding: the motivating critique artifact recyc_crit_ub.raw really exists. expect_exit: 0
6import "nx_syscalls.nx"
7import "nx_doc_ubscan.nx"
8import "nx_gate_verdict.nx"
9
10func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
11func slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
12func have_file(p: *u8) -> i64 { let fd: i64=sys_openat_rd(p); if fd<0 { return 0 } sys_close(fd); return 1 }
13
14func main() -> i64 {
15 gp("=== nx_doc_ubscan_gate: detect the LM-031 inline cast-then-index UB (recycled from the UB critique) ===\n" as *u8)
16 var pass: i64=0; var fail: i64=0
17
18 // KAT1 MUST-FLAG: the exact LM-031 dangerous form
19 let s1: *u8 = "func f() -> i64 { return (c[5] as *i64)[idx] }" as *u8
20 if ub_scan(s1, slen(s1)) >= 0 { pass=pass+1 } else { fail=fail+1; gp(" FAIL kat1-missed-castindex\n" as *u8) }
21
22 // KAT2 MUST-NOT-FLAG: the SAFE bind-then-index (the LM-031 fix)
23 let s2: *u8 = "func g() -> i64 { let p: *i64 = c[5] as *i64; return p[idx] }" as *u8
24 if ub_scan(s2, slen(s2)) < 0 { pass=pass+1 } else { fail=fail+1; gp(" FAIL kat2-flagged-safe-bind\n" as *u8) }
25
26 // KAT3 MUST-NOT-FLAG: a plain cast with NO index
27 let s3: *u8 = "func h() -> i64 { let x: *u8 = p as *u8; return 0 }" as *u8
28 if ub_scan(s3, slen(s3)) < 0 { pass=pass+1 } else { fail=fail+1; gp(" FAIL kat3-flagged-plain-cast\n" as *u8) }
29
30 // KAT4 MUST-NOT-FLAG: a parenthesized index with NO cast
31 let s4: *u8 = "func k() -> i64 { let v: i64 = (a + b)[i]; return v }" as *u8
32 if ub_scan(s4, slen(s4)) < 0 { pass=pass+1 } else { fail=fail+1; gp(" FAIL kat4-flagged-noncast-index\n" as *u8) }
33
34 // KAT5 MUST-FLAG: cast-then-index nested inside a call argument
35 let s5: *u8 = "func m() -> i64 { return foo((x as *i64)[0]) }" as *u8
36 if ub_scan(s5, slen(s5)) >= 0 { pass=pass+1 } else { fail=fail+1; gp(" FAIL kat5-missed-nested\n" as *u8) }
37
38 // KAT6 grounding: the motivating critique artifact exists (this hardening was recycled from a real fetched page)
39 if have_file("knowledge/fetched/recyc_crit_ub.raw" as *u8)==1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL kat6-ungrounded (recyc_crit_ub.raw missing)\n" as *u8) }
40
41 gp("DOC-UBSCAN-GATE pass=" as *u8); gn(pass); gp(" fail=" as *u8); gn(fail)
42 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
43 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
44 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
45 let ctr__dry: *i64 = gv_ctr()
46 ctr__dry[0] = pass
47 ctr__dry[1] = pass + fail
48 let rc__dry: i64 = gv_verdict("DOC-UBSCAN-GATE" as *u8, ctr__dry, "inline cast-then-index UB flagged incl. nested; safe bind-then-index/plain-cast/noncast-index NOT flagged; recycled from the UB critique)" as *u8)
49 sys_exit(rc__dry)
50 return rc__dry
51}