code wiki / (root) / nx_ctrlbyte_gate.nx

nx_ctrlbyte_gate.nx source

↩ module page · 259 lines · 10041 B

1// nx_ctrlbyte_gate.nx -- CONTROL-BYTE CORRUPTION TOOTH (debt 1785520719 / 1785521381, 2026-07-31). 2// THE WOUND: 210 .nx sources had ONE LINE INSIDE putn overwritten by a run of 0x0E (Shift-Out) bytes. 3// Every organ so hit printed EMPTY status=, bytes= and counts -- a fleet of blind instruments. 4// It survived because BOTH existing rulers called it healthy: nx_srcguard rules on SYMBOLS (a line 5// replaced inside a function changes no top-level symbol, so it can never fire) and nx_fs read 6// RENDERS A 0x0E RUN AS AN INNOCENT BLANK LINE. A symbol ruler and a byte ruler answer DIFFERENT 7// questions; the corpus had only the first. 8// This is the byte ruler: any byte outside {tab, LF, CR, printable, UTF-8 >=0x80} in a .nx file is RED. 9// A rule nothing must remember beats a list nobody maintains. 10// verbs: scan [dir] | selftest <writable-scratch-dir> 11// expect_exit: 0 license_tier: ORIGINAL 12import "nx_syscalls.nx" 13 14const CB_DIRBUF: i64 = 131072 15const CB_FCAP: i64 = 4194304 16const CB_PATH: i64 = 1024 17const CB_DT_DIR: i64 = 4 18const CB_MODE_644: i64 = 420 19const CB_MAX_REPORT: i64 = 40 20const CB_SIG_RUN: i64 = 119 21 22func cb_vlen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 23func cb_puts(s: *u8) -> i64 { sys_write(1, s, cb_vlen(s)); return 0 } 24func cb_putn(v: i64) -> i64 { 25 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 } 26 var m: i64 = v 27 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 28 let d: *u8 = sys_mmap(24) 29 var k: i64 = 0 30 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 31 var j: i64 = k - 1 32 while j >= 0 { sys_write(1, ((d as i64)+j) as *u8, 1); j = j - 1 } 33 return 0 34} 35func cb_hex2(v: i64) -> i64 { 36 let tbl: *u8 = "0123456789abcdef" as *u8 37 let hi: i64 = v / 16 38 let lo: i64 = v % 16 39 sys_write(1, ((tbl as i64)+hi) as *u8, 1) 40 sys_write(1, ((tbl as i64)+lo) as *u8, 1) 41 return 0 42} 43 44// Is this byte illegal inside a .nx source file? tab/LF/CR are legal whitespace; >=0x80 is UTF-8 in 45// comments and must NOT be flagged, or the gate cries wolf and gets ignored. 46func cb_is_bad(c: i64) -> i64 { 47 if c == 9 { return 0 } 48 if c == 10 { return 0 } 49 if c == 13 { return 0 } 50 if c == 127 { return 1 } 51 if c < 32 { return 1 } 52 return 0 53} 54 55func cb_ends_nx(nm: *u8) -> i64 { 56 let n: i64 = cb_vlen(nm) 57 if n < 4 { return 0 } 58 if nm[n-3] != (46 as u8) { return 0 } 59 if nm[n-2] != (110 as u8) { return 0 } 60 if nm[n-1] != (120 as u8) { return 0 } 61 return 1 62} 63 64func cb_join(dst: *u8, dir: *u8, nm: *u8) -> i64 { 65 var k: i64 = 0 66 var i: i64 = 0 67 let dl: i64 = cb_vlen(dir) 68 while i < dl { dst[k] = dir[i]; k = k + 1; i = i + 1 } 69 if k > 0 { if dst[k-1] != (47 as u8) { dst[k] = 47 as u8; k = k + 1 } } 70 i = 0 71 while nm[i] != (0 as u8) { dst[k] = nm[i]; k = k + 1; i = i + 1 } 72 dst[k] = 0 as u8 73 return k 74} 75 76func cb_scan_file(path: *u8, buf: *u8, reported: *i64) -> i64 { 77 let fd: i64 = sys_openat_rd(path) 78 if fd < 0 { return 0 } 79 var n: i64 = 0 80 var go: i64 = 1 81 while go == 1 { let r: i64 = sys_read(fd, ((buf as i64)+n) as *u8, CB_FCAP-n); if r <= 0 { go = 0 } else { n = n + r } if n >= CB_FCAP { go = 0 } } 82 sys_close(fd) 83 var bad: i64 = 0 84 var line: i64 = 1 85 var firstline: i64 = 0 86 var firstbyte: i64 = 0 87 var i: i64 = 0 88 while i < n { 89 let c: i64 = buf[i] as i64 90 if c == 10 { line = line + 1 } 91 if cb_is_bad(c) == 1 { 92 bad = bad + 1 93 if firstline == 0 { firstline = line; firstbyte = c } 94 } 95 i = i + 1 96 } 97 if bad > 0 { if reported[0] < CB_MAX_REPORT { 98 cb_puts(" RED " as *u8) 99 cb_puts(path) 100 cb_puts(" line=" as *u8) 101 cb_putn(firstline) 102 cb_puts(" byte=0x" as *u8) 103 cb_hex2(firstbyte) 104 cb_puts(" count=" as *u8) 105 cb_putn(bad) 106 cb_puts("\n" as *u8) 107 reported[0] = reported[0] + 1 108 } } 109 return bad 110} 111 112func cb_scan_dir(dir: *u8, recurse: i64, buf: *u8, stats: *i64, reported: *i64) -> i64 { 113 let fd: i64 = sys_openat_rd(dir) 114 if fd < 0 { return 0 } 115 let dbuf: *u8 = sys_mmap(CB_DIRBUF) 116 var go: i64 = 1 117 while go == 1 { 118 let nb: i64 = sys_getdents64(fd, dbuf, CB_DIRBUF) 119 if nb <= 0 { go = 0 } else { 120 var off: i64 = 0 121 while off < nb { 122 let rec: *u8 = (dbuf as i64 + off) as *u8 123 let rl: i64 = dirent_reclen(rec) 124 if rl <= 0 { off = nb } else { 125 let nm: *u8 = dirent_name(rec) 126 let ty: i64 = dirent_type(rec) 127 var skip: i64 = 0 128 if nm[0] == (46 as u8) { skip = 1 } 129 if skip == 0 { if ty == CB_DT_DIR { 130 if recurse == 1 { 131 let sub: *u8 = sys_mmap(CB_PATH) 132 cb_join(sub, dir, nm) 133 cb_scan_dir(sub, 0, buf, stats, reported) 134 } 135 } else { 136 if cb_ends_nx(nm) == 1 { 137 let p: *u8 = sys_mmap(CB_PATH) 138 cb_join(p, dir, nm) 139 stats[0] = stats[0] + 1 140 let bad: i64 = cb_scan_file(p, buf, reported) 141 if bad > 0 { stats[1] = stats[1] + 1; stats[2] = stats[2] + bad } 142 } 143 } } 144 off = off + rl 145 } 146 } 147 } 148 } 149 sys_close(fd) 150 return 0 151} 152 153func cb_write_file(path: *u8, data: *u8, n: i64) -> i64 { 154 let fd: i64 = sys_openat_wr(path, CB_MODE_644) 155 if fd < 0 { return 0 - 1 } 156 sys_write(fd, data, n) 157 sys_close(fd) 158 return n 159} 160 161func main(argc: i64, argv: *i64) -> i64 { 162 if argc < 2 { 163 cb_puts("usage: nx_ctrlbyte_gate {scan [dir] | selftest <writable-scratch-dir>}\n" as *u8) 164 sys_exit(2) 165 return 2 166 } 167 let verb: *u8 = argv[1] as *u8 168 let buf: *u8 = sys_mmap(CB_FCAP) 169 let stats: *i64 = sys_mmap(64) as *i64 170 let reported: *i64 = sys_mmap(16) as *i64 171 172 if verb[1] == (99 as u8) { 173 var dir: *u8 = "buildroot/runtime" as *u8 174 if argc >= 3 { dir = argv[2] as *u8 } 175 cb_puts("NX-CTRLBYTE-GATE scan dir=" as *u8) 176 cb_puts(dir) 177 cb_puts("\n" as *u8) 178 cb_scan_dir(dir, 1, buf, stats, reported) 179 cb_puts("scanned=" as *u8) 180 cb_putn(stats[0]) 181 cb_puts(" corrupt_files=" as *u8) 182 cb_putn(stats[1]) 183 cb_puts(" bad_bytes=" as *u8) 184 cb_putn(stats[2]) 185 // FAIL-CLOSED ON AN EMPTY SCAN: a missing or empty directory used to report GREEN, which is 186 // a vacuous pass -- a scan that examined NOTHING proves nothing, and would silently bless a 187 // typo in the path forever. Caught by this gate scoring buildroot/nxasm as scanned=0 GREEN. 188 if stats[0] == 0 { cb_puts(" VERDICT=RED scanned 0 files -- vacuous scan, check the path" as *u8); cb_puts("\n" as *u8); sys_exit(1); return 1 } 189 if stats[1] == 0 { cb_puts(" VERDICT=GREEN\n" as *u8); sys_exit(0); return 0 } 190 cb_puts(" VERDICT=RED\n" as *u8) 191 sys_exit(1) 192 return 1 193 } 194 195 if verb[1] == (101 as u8) { 196 if argc < 3 { cb_puts("selftest needs <writable-scratch-dir>\n" as *u8); sys_exit(2); return 2 } 197 let scratch: *u8 = argv[2] as *u8 198 var pass: i64 = 0 199 var tot: i64 = 0 200 201 let clean: *u8 = sys_mmap(CB_PATH) 202 cb_join(clean, scratch, "cbg_clean.nx" as *u8) 203 let cdata: *u8 = "func f() -> i64 { return 0 }\n" as *u8 204 cb_write_file(clean, cdata, cb_vlen(cdata)) 205 reported[0] = 0 206 let cbad: i64 = cb_scan_file(clean, buf, reported) 207 tot = tot + 1 208 if cbad == 0 { pass = pass + 1; cb_puts("T1 PASS clean file scores 0 bad bytes\n" as *u8) } 209 if cbad != 0 { cb_puts("T1 FAIL clean file flagged -- gate over-fires\n" as *u8) } 210 211 // NON-VACUITY: reproduce the EXACT 119-byte 0x0E signature and require the gate to catch it. 212 // A gate that cannot fail on the defect it names is not evidence. 213 let dirty: *u8 = sys_mmap(CB_PATH) 214 cb_join(dirty, scratch, "cbg_dirty.nx" as *u8) 215 let dd: *u8 = sys_mmap(512) 216 var w: i64 = 0 217 let pre: *u8 = "func f() -> i64 {\n" as *u8 218 var q: i64 = 0 219 while pre[q] != (0 as u8) { dd[w] = pre[q]; w = w + 1; q = q + 1 } 220 var z: i64 = 0 221 while z < CB_SIG_RUN { dd[w] = 14 as u8; w = w + 1; z = z + 1 } 222 dd[w] = 10 as u8 223 w = w + 1 224 let post: *u8 = " return 0\n}\n" as *u8 225 q = 0 226 while post[q] != (0 as u8) { dd[w] = post[q]; w = w + 1; q = q + 1 } 227 cb_write_file(dirty, dd, w) 228 reported[0] = 0 229 let dbad: i64 = cb_scan_file(dirty, buf, reported) 230 tot = tot + 1 231 if dbad == CB_SIG_RUN { pass = pass + 1; cb_puts("T2 PASS non-vacuous: caught all 119 0x0E bytes\n" as *u8) } 232 if dbad != CB_SIG_RUN { cb_puts("T2 FAIL expected 119 bad bytes, got " as *u8); cb_putn(dbad); cb_puts(" -- GATE IS VACUOUS\n" as *u8) } 233 234 tot = tot + 1 235 var cls: i64 = 1 236 if cb_is_bad(9) != 0 { cls = 0 } 237 if cb_is_bad(10) != 0 { cls = 0 } 238 if cb_is_bad(13) != 0 { cls = 0 } 239 if cb_is_bad(65) != 0 { cls = 0 } 240 if cb_is_bad(14) != 1 { cls = 0 } 241 if cb_is_bad(0) != 1 { cls = 0 } 242 if cb_is_bad(127) != 1 { cls = 0 } 243 if cls == 1 { pass = pass + 1; cb_puts("T3 PASS classifier accepts tab LF CR alpha, rejects 0x0E NUL DEL\n" as *u8) } 244 if cls == 0 { cb_puts("T3 FAIL classifier wrong\n" as *u8) } 245 246 cb_puts("NX-CTRLBYTE-GATE SELFTEST " as *u8) 247 cb_putn(pass) 248 cb_puts("/" as *u8) 249 cb_putn(tot) 250 if pass == tot { cb_puts(" GREEN\n" as *u8); sys_exit(0); return 0 } 251 cb_puts(" RED\n" as *u8) 252 sys_exit(1) 253 return 1 254 } 255 256 cb_puts("unknown verb\n" as *u8) 257 sys_exit(2) 258 return 2 259}