code wiki / (root) / nx_json_adversarial_test.nx

nx_json_adversarial_test.nx source

↩ module page · 99 lines · 3325 B

1// nx_json_adversarial_test.nx -- Phase A5 of S-class hardening. 2// 3// Adversarial fuzzing of nx_json_next, the tokenizer the substrate 4// uses to parse Moonraker HTTP responses + any other JSON-bearing 5// input. Even though Moonraker is on the LAN, defense-in-depth: a 6// malformed JSON byte stream must not crash the tokenizer or read 7// past the buffer. 8// 9// expect_exit: 0 10// license_tier: ORIGINAL 11 12import "nx_syscalls.nx" 13import "nx_json.nx" 14 15// Drain a tokenizer: advance until EOF or ERROR. Returns: 16// 1 if tokenizer reached EOF cleanly 17// 2 if tokenizer hit ERROR 18// 3 if more than 1024 iterations (would indicate infinite loop) 19func drain_tok(t: *NxJsonTok) -> i64 { 20 var iters: i64 = 0 21 while iters < 1024 { 22 let k: i64 = nx_json_next(t) 23 if k == NX_JSON_EOF { return 1 } 24 if k == NX_JSON_ERROR { return 2 } 25 iters = iters + 1 26 } 27 return 3 // possible infinite loop 28} 29 30func main() -> i64 { 31 // ===== (a) Empty input -> reaches EOF immediately ===== 32 let empty: *u8 = sys_mmap(4) 33 let t_empty: *NxJsonTok = nx_json_new(empty, 0) 34 let r_empty: i64 = drain_tok(t_empty) 35 if r_empty != 1 { return 10 } 36 37 // ===== (b) All NUL bytes -> EOF or ERROR (NOT infinite loop) ===== 38 let nul_buf: *u8 = sys_mmap(64) 39 let t_nul: *NxJsonTok = nx_json_new(nul_buf, 64) 40 let r_nul: i64 = drain_tok(t_nul) 41 if r_nul == 3 { return 20 } // infinite-loop guard 42 43 // ===== (c) All 0xFF bytes -> EOF or ERROR (NOT infinite) ===== 44 let ff_buf: *u8 = sys_mmap(64) 45 var fi: i64 = 0 46 while fi < 64 { 47 ff_buf[fi] = 0xff 48 fi = fi + 1 49 } 50 let t_ff: *NxJsonTok = nx_json_new(ff_buf, 64) 51 let r_ff: i64 = drain_tok(t_ff) 52 if r_ff == 3 { return 30 } 53 54 // ===== (d) Valid JSON object -> drains without ERROR ===== 55 let good: *u8 = sys_mmap(64) 56 let s: *u8 = "{\"a\":1,\"b\":true,\"c\":null}" 57 var n: i64 = 0 58 while s[n] != 0 { n = n + 1 } 59 var k: i64 = 0 60 while k < n { good[k] = s[k]; k = k + 1 } 61 let t_good: *NxJsonTok = nx_json_new(good, n) 62 let r_good: i64 = drain_tok(t_good) 63 if r_good != 1 { return 40 } 64 65 // ===== (e) Unclosed string -> ERROR (NOT infinite) ===== 66 let unclosed: *u8 = sys_mmap(64) 67 let s_u: *u8 = "\"never closed" 68 var nu: i64 = 0 69 while s_u[nu] != 0 { nu = nu + 1 } 70 var ku: i64 = 0 71 while ku < nu { unclosed[ku] = s_u[ku]; ku = ku + 1 } 72 let t_unclosed: *NxJsonTok = nx_json_new(unclosed, nu) 73 let r_unclosed: i64 = drain_tok(t_unclosed) 74 if r_unclosed == 3 { return 50 } // not infinite 75 76 // ===== (f) Lone garbage chars -> EOF or ERROR ===== 77 let junk: *u8 = sys_mmap(64) 78 junk[0] = 0x40 // '@' 79 junk[1] = 0x23 // '#' 80 junk[2] = 0x25 // '%' 81 junk[3] = 0x5E // '^' 82 let t_junk: *NxJsonTok = nx_json_new(junk, 4) 83 let r_junk: i64 = drain_tok(t_junk) 84 if r_junk == 3 { return 60 } 85 86 // ===== (g) Deeply nested array -- shouldn't blow up tokenizer ===== 87 // (Tokenizer is stateless; parser/validator handles depth.) 88 let deep: *u8 = sys_mmap(256) 89 var di: i64 = 0 90 while di < 100 { 91 deep[di] = 0x5B // '[' 92 di = di + 1 93 } 94 let t_deep: *NxJsonTok = nx_json_new(deep, 100) 95 let r_deep: i64 = drain_tok(t_deep) 96 if r_deep == 3 { return 70 } 97 98 return 0 99}