code wiki / _hdl_build / nx_janitor_caps_gate.nx
nx_janitor_caps_gate.nx source
↩ module page · 48 lines · 4131 B
1// nx_janitor_caps_gate.nx -- proves the silent-truncation CAP detector (nx_cap_detect_lib) has TEETH and NO
2// false positives on its discriminators. In-memory fixtures (no /tmp): one POSITIVE that MUST flag, and four
3// NEG-CONTROLS that MUST NOT -- data-driven size, no-source, byte-buffer(no '*'), and shift-not-bound. The
4// fixtures are code-representing strings passed straight to the CORE scan (the gate does NOT strip -- the
5// sweep strips real files; here the string IS the simulated code). GREEN iff all six checks pass.
6// MIGRATED ONTO THE BASE CLASS 2026-09-05: the hand-rolled "--- 6/6 GREEN" line was unreadable to every rollup,
7// and the compare evidence census read this gate as GREEN at pass=0/0 -- a vacuous row, a green with no visible
8// teeth. gv_check_eq asserts AND emits actual/expected in one call so the published number and the tested number
9// cannot drift; the neg-controls are NAMED so the census can count them; the exit code carries the verdict.
10// license_tier: ORIGINAL | genealogy_id: nishi_janitor_caps_gate_2026_07_15
11import "nx_syscalls.nx"
12import "nx_gate_verdict.nx"
13import "nx_cap_detect_lib.nx"
14
15func gg_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
16
17// would the SWEEP flag this buffer? (a literal cap AND an unbounded-source read)
18func gg_would_flag(buf: *u8) -> i64 {
19 let n: i64=gg_slen(buf)
20 if jc_mmap_scan(buf, n)>0 { if jc_has_src(buf, n)==1 { return 1 } }
21 return 0
22}
23
24func main(argc: i64, argv: *i64) -> i64 {
25 let ctr: *i64 = gv_ctr()
26 gv_head("nx_janitor_caps_gate -- does the silent-truncation cap detector have teeth and no false positives?" as *u8)
27 // POSITIVE: fixed-count array + '< 128' bound + sys_read -> MUST flag, cap literal = 128
28 let f1: *u8 = "func f(fd: i64, b: *u8) { let a: *i64 = sys_mmap(8 * 128) as *i64; var i: i64 = 0; while i < 128 { let n: i64 = sys_read(fd, b, 64); a[i] = n; i = i + 1 } }" as *u8
29 // NEG data-driven: a VARIABLE after '*' -> no literal -> invisible
30 let f2: *u8 = "func f(fd: i64, b: *u8, ns: i64) { let a: *i64 = sys_mmap(8 * ns + 64) as *i64; var i: i64 = 0; while i < ns { let n: i64 = sys_read(fd, b, 64); a[i] = n; i = i + 1 } }" as *u8
31 // NEG no-source: cap present but no unbounded read (argc-bounded, provably safe)
32 let f3: *u8 = "func f(argc: i64) { let a: *i64 = sys_mmap(8 * 128) as *i64; var i: i64 = 0; while i < 128 { a[i] = i; i = i + 1 } }" as *u8
33 // NEG byte-buffer: sys_mmap(256) has no '*' -> not a fixed-count array
34 let f4: *u8 = "func f(fd: i64) { let a: *u8 = sys_mmap(256); var i: i64 = 0; while i < 256 { let n: i64 = sys_read(fd, a, 1); i = i + 1 } }" as *u8
35 // NEG shift-not-bound: '<< 128' is a shift, not a loop bound
36 let f5: *u8 = "func f(fd: i64, b: *u8) { let a: *i64 = sys_mmap(8 * 128) as *i64; var x: i64 = 1 << 128; let n: i64 = sys_read(fd, b, 64); a[0] = x }" as *u8
37
38 gv_check_eq("F1 positive: a fixed-count array, a bound on the same literal and an unbounded read FLAGS" as *u8, gg_would_flag(f1), 1, ctr)
39 gv_check_eq("F1 the exact cap literal is read back from the fixture" as *u8, jc_mmap_scan(f1, gg_slen(f1)), 128, ctr)
40 gv_check_eq("neg-control-F2 data-driven size (a variable after the star) is NOT flagged" as *u8, gg_would_flag(f2), 0, ctr)
41 gv_check_eq("neg-control-F3 a cap with no unbounded source is NOT flagged" as *u8, gg_would_flag(f3), 0, ctr)
42 gv_check_eq("neg-control-F4 a byte buffer without a star is NOT flagged" as *u8, gg_would_flag(f4), 0, ctr)
43 gv_check_eq("neg-control-F5 a shift is not a bound and is NOT flagged" as *u8, gg_would_flag(f5), 0, ctr)
44 let small: *u8 = "func f(fd:i64,b:*u8){let a:*i64=sys_mmap(8 * 8) as *i64;var i:i64=0;while i < 8 {a[i]=sys_read(fd,b,1);i=i+1}}" as *u8
45 gv_check_eq("small literal count is a candidate, not presumed safe",gg_would_flag(small),1,ctr)
46 gv_check_eq("small candidate retains exact count",jc_mmap_scan(small,gg_slen(small)),8,ctr)
47 return gv_verdict("nx_janitor_caps_gate" as *u8, ctr, "Narrow lexical candidate detection; named capacities, byte buffers and data-flow safety remain unqualified" as *u8)
48}