nx_fnres_offset_probe.nx source
↩ module page · 76 lines · 3543 B
1// nx_fnres_offset_probe.nx -- proves the FNRES offset desync is fixed (debt 1785521219).
2//
3// THE DEFECT: nx_autofix_auto's fn_failing clamped the parsed name to 23 bytes, then located the
4// `passed` and `total` fields at `r + 6 + nl + 1` -- i.e. from the CLAMPED length. For any function
5// name longer than 23 characters that offset lands INSIDE the name, the digit scan hits letters and
6// bails, and `passed` stays 0. The tool then reports ZERO TESTS PASSED for a function that passed all
7// of them -- a wrong NUMBER, not a crash, in a tool that judges fixes by that number.
8//
9// THIS PROBE USES A 30-CHAR NAME (over the 23 clamp) so it exercises exactly the broken path.
10// With the old code T2 reads passed=0; with the fix it reads passed=7.
11// expect_exit: 0 license_tier: ORIGINAL
12
13import "nx_syscalls.nx"
14
15func fo_w(s: *u8) -> i64 {
16 var n: i64 = 0
17 while s[n] != (0 as u8) { n = n + 1 }
18 sys_write(1, s, n)
19 return 0
20}
21
22func fo_len(s: *u8) -> i64 {
23 var n: i64 = 0
24 while s[n] != (0 as u8) { n = n + 1 }
25 return n
26}
27
28// Mirror of the FIXED parser: clamp the NAME, but locate fields from the name's TRUE end.
29func fo_parse_passed(row: *u8, namebuf: *u8) -> i64 {
30 let n: i64 = fo_len(row)
31 var i: i64 = 6
32 var nl: i64 = 0
33 var nend: i64 = n
34 while i < n { if row[i] == (32 as u8) { nend = i; i = n + 1 } else { if nl < 23 { namebuf[nl] = row[i]; nl = nl + 1 } i = i + 1 } }
35 namebuf[nl] = 0 as u8
36 var q: i64 = nend + 1
37 var passed: i64 = 0
38 while q < n { let c: i64 = row[q] as i64; if c >= 48 { if c <= 57 { passed = passed * 10 + (c - 48); q = q + 1 } else { q = n + 1 } } else { q = n + 1 } }
39 return passed
40}
41
42// What the OLD code did: locate from the CLAMPED length.
43func fo_parse_passed_old(row: *u8, namebuf: *u8) -> i64 {
44 let n: i64 = fo_len(row)
45 var i: i64 = 6
46 var nl: i64 = 0
47 while i < n { if row[i] == (32 as u8) { i = n + 1 } else { if nl < 23 { namebuf[nl] = row[i]; nl = nl + 1 } i = i + 1 } }
48 namebuf[nl] = 0 as u8
49 var q: i64 = 6 + nl + 1
50 var passed: i64 = 0
51 while q < n { let c: i64 = row[q] as i64; if c >= 48 { if c <= 57 { passed = passed * 10 + (c - 48); q = q + 1 } else { q = n + 1 } } else { q = n + 1 } }
52 return passed
53}
54
55func main() -> i64 {
56 let nb: *u8 = sys_mmap(64)
57
58 // 12-char name: BOTH parsers agree (under the clamp).
59 let shortrow: *u8 = "FNRES fn_short_ok 7 7" as *u8
60 if fo_parse_passed(shortrow, nb) != 7 { fo_w("T1 FAIL short name new-parser\n" as *u8); return 1 }
61 if fo_parse_passed_old(shortrow, nb) != 7 { fo_w("T1 FAIL short name old-parser\n" as *u8); return 1 }
62 fo_w("T1 short_name PASS both parsers read passed=7 (name under the clamp)\n" as *u8)
63
64 // 30-char name: over the 23 clamp. The OLD parser desyncs to 0; the FIXED one still reads 7.
65 let longrow: *u8 = "FNRES fn_name_of_thirty_chars_x 7 7" as *u8
66 let newv: i64 = fo_parse_passed(longrow, nb)
67 let oldv: i64 = fo_parse_passed_old(longrow, nb)
68 if newv != 7 { fo_w("T2 FAIL fixed parser did not read 7\n" as *u8); return 2 }
69 if oldv == 7 { fo_w("T2 INCONCLUSIVE: old parser also read 7 -- probe is vacuous\n" as *u8); return 3 }
70 fo_w("T2 long_name PASS fixed parser reads passed=7 where the OLD parser desyncs\n" as *u8)
71
72 fo_w("\nNON-VACUITY: T2 asserts the OLD parser gets it WRONG on the same input,\n" as *u8)
73 fo_w("so this probe cannot pass unless the defect was real and the fix changed it.\n" as *u8)
74 fo_w("FNRES-OFFSET-PROBE OK\n" as *u8)
75 return 0
76}