code wiki / _hdl_build / nx_html_to_text_oom_gate.nx
nx_html_to_text_oom_gate.nx source
↩ module page · 64 lines · 3443 B
1import "nx_gate_gn.nx"
2// nx_html_to_text_oom_gate.nx -- proves the S-class OOM fix in nx_html_to_text. Before the fix, h2t_is_block_tag /
3// h2t_is_suppress_tag mmap'd ~10 constant tag-name buffers PER TAG (never freed) -> a single 436KB doc leaked
4// ~400MB, so a multi-doc fold (or a tight loop) OOM-137'd. This gate runs nx_html_to_text on a real 436KB Wikipedia
5// raw 1000 times: before the fix it OOM-dies by ~iter 10 (run-exit=137 -> the GREEN line never prints = RED);
6// after the fix it completes deterministically (zero per-tag alloc + per-doc scratch freed). LIAR-KILLABLE: revert
7// the fix -> this gate OOMs. expect_exit: 0 license_tier: ORIGINAL
8import "nx_syscalls.nx"
9import "nx_html_to_text.nx"
10import "nx_gate_verdict.nx"
11
12func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
13func contains(buf: *u8, n: i64, pat: *u8, plen: i64) -> i64 {
14 if plen <= 0 { return 0 }
15 var i: i64 = 0
16 while i + plen <= n {
17 var j: i64 = 0
18 while j < plen { if buf[i+j] != pat[j] { j = plen + 1 } else { j = j + 1 } }
19 if j == plen { return 1 }
20 i = i + 1
21 }
22 return 0
23}
24
25func main() -> i64 {
26 var pass: i64=0; var fail: i64=0
27 let lenbox: *i64 = sys_mmap(16) as *i64
28 let src: *u8 = sys_read_file("knowledge/fetched/supply_b1_tariff.raw" as *u8, lenbox)
29 if src == 0 as *u8 { gp("HTML2TEXT-OOM FAIL: no corpus (knowledge/fetched/supply_b1_tariff.raw missing)\n" as *u8); sys_exit(1); return 1 }
30 let srclen: i64 = lenbox[0]
31 let cap: i64 = 2097152
32 let out: *u8 = sys_mmap(cap) // allocated ONCE, reused every iter -> the test itself leaks nothing
33 gp("=== nx_html_to_text_oom_gate: 1000x extraction of a 436KB doc (would OOM ~iter 10 before the fix) ===\n" as *u8)
34 gp(" doc bytes=" as *u8); gn(srclen); gp("\n" as *u8)
35
36 let len0: i64 = nx_html_to_text(src, srclen, out, cap)
37 gp(" extracted text bytes=" as *u8); gn(len0); gp("\n" as *u8)
38 if len0 > 1000 { pass=pass+1 } else { fail=fail+1; gp(" FAIL too-little-text (extraction broken)\n" as *u8) }
39 if contains(out, len0, "ariff" as *u8, 5) == 1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL text-missing-'ariff' (extraction wrong)\n" as *u8) }
40
41 let N: i64 = 1000
42 var i: i64 = 0
43 var consistent: i64 = 1
44 while i < N {
45 let leni: i64 = nx_html_to_text(src, srclen, out, cap)
46 if leni != len0 { consistent = 0; i = N }
47 i = i + 1
48 }
49 if consistent == 1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL non-deterministic across iterations\n" as *u8) }
50 // Reaching here = the process SURVIVED 1000 large-doc extractions = the leak is gone (the proof).
51 gp(" completed " as *u8); gn(N); gp(" extractions, NO OOM, deterministic\n" as *u8)
52 pass=pass+1
53
54 gp("HTML2TEXT-OOM pass=" as *u8); gn(pass); gp(" fail=" as *u8); gn(fail)
55 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
56 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
57 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
58 let ctr__dry: *i64 = gv_ctr()
59 ctr__dry[0] = pass
60 ctr__dry[1] = pass + fail
61 let rc__dry: i64 = gv_verdict("HTML-TO-TEXT-OOM-GATE" as *u8, ctr__dry, "per-tag mmap leak eliminated; text correct + deterministic; 1000x fold no OOM)" as *u8)
62 sys_exit(rc__dry)
63 return rc__dry
64}