code wiki / (root) / nx_wasm_vm_bounds_gate_20260912.nx

nx_wasm_vm_bounds_gate_20260912.nx source

↩ module page · 98 lines · 6107 B

1import "nx_wasm_vm_bounds_20260912.nx" 2import "nx_gate_verdict.nx" 3// Regression sizes deliberately cross all three old fixed metadata allocations. 4const WG_TYPES: i64 = 1024 + 1 5const WG_FUNCS: i64 = 2048 + 1 6const WG_EXPORTS: i64 = 1092 7func wg_u32(b: *u8, p: i64, value: i64) -> i64 { 8 var v: i64 = value; var o: i64 = p; var go: i64 = 1 9 while go == 1 { var x: i64 = v & 127; v = v >> 7; if v != 0 { x = x | 128 }; b[o] = x as u8; o = o + 1; if v == 0 { go = 0 } } 10 return o 11} 12func wg_name(b: *u8, p: i64, value: i64) -> i64 { 13 var o: i64 = p; b[o] = 102 as u8; o = o + 1 14 var divisor: i64 = 1 15 while value / divisor >= 10 { divisor = divisor * 10 } 16 while divisor > 0 { b[o] = (48 + ((value / divisor) % 10)) as u8; o = o + 1; divisor = divisor / 10 } 17 b[o] = 0 as u8; return o - p 18} 19func wg_section(b: *u8, p: i64, sid: i64, payload: *u8, size: i64, start: *i64) -> i64 { 20 b[p] = sid as u8; var o: i64 = wg_u32(b, p + 1, size); start[0] = o 21 var i: i64 = 0; while i < size { b[o] = payload[i]; o = o + 1; i = i + 1 }; return o 22} 23func wg_image(b: *u8, marks: *i64) -> i64 { 24 b[0] = 0 as u8; b[1] = 97 as u8; b[2] = 115 as u8; b[3] = 109 as u8 25 b[4] = 1 as u8; b[5] = 0 as u8; b[6] = 0 as u8; b[7] = 0 as u8 26 let payload: *u8 = sys_mmap((WG_TYPES + WG_FUNCS + WG_EXPORTS) * 16) 27 let start: *i64 = sys_mmap(8) as *i64; var o: i64 = 8 28 var p: i64 = wg_u32(payload, 0, WG_TYPES); var i: i64 = 0 29 while i < WG_TYPES { payload[p] = 96 as u8; payload[p+1] = 0 as u8; payload[p+2] = 1 as u8; payload[p+3] = 126 as u8; p = p + 4; i = i + 1 } 30 o = wg_section(b, o, 1, payload, p, start) 31 p = wg_u32(payload, 0, WG_FUNCS); marks[0] = p; i = 0 32 while i < WG_FUNCS { p = wg_u32(payload, p, WG_TYPES - 1); i = i + 1 } 33 o = wg_section(b, o, 3, payload, p, start); marks[0] = marks[0] + start[0] 34 p = wg_u32(payload, 0, WG_EXPORTS); let name: *u8 = sys_mmap(32); i = 0 35 while i < WG_EXPORTS { 36 let nl: i64 = wg_name(name, 0, i); p = wg_u32(payload, p, nl) 37 var j: i64 = 0; while j < nl { payload[p] = name[j]; p = p + 1; j = j + 1 } 38 payload[p] = 0 as u8; p = p + 1 39 p = wg_u32(payload, p, WG_FUNCS - 1); i = i + 1 40 } 41 o = wg_section(b, o, 7, payload, p, start); marks[1] = start[0] 42 p = wg_u32(payload, 0, WG_FUNCS); i = 0 43 while i < WG_FUNCS { payload[p] = 4 as u8; payload[p+1] = 0 as u8; payload[p+2] = 66 as u8; payload[p+3] = 7 as u8; payload[p+4] = 11 as u8; p = p + 5; i = i + 1 } 44 o = wg_section(b, o, 10, payload, p, start); marks[2] = start[0] 45 return o 46} 47func wg_refuse(b: *u8, n: i64, label: *u8, ctr: *i64) -> i64 { 48 let m: *WasmMod = wm_new(b, n) 49 let rc: i64 = wm_parse(m) 50 gv_check(label, rc < 0 && (m.exp_name_off as i64) == 0 && (m.type_nparam as i64) == 0 && (m.func_type as i64) == 0 && m.n_exports == 0 && m.n_funcs == 0 && m.n_types == 0, ctr) 51 return rc 52} 53func main() -> i64 { 54 let ctr: *i64 = gv_ctr(); gv_head("WASM-METADATA-BOUNDS") 55 let b: *u8 = sys_mmap((WG_TYPES + WG_FUNCS + WG_EXPORTS) * 32) 56 let marks: *i64 = sys_mmap(24) as *i64 57 let n: i64 = wg_image(b, marks) 58 let m: *WasmMod = wm_new(b, n); let rc: i64 = wm_parse(m) 59 gv_check("valid counts exceed all old metadata caps", rc == 0 && m.n_types == WG_TYPES && m.n_funcs == WG_FUNCS && m.n_exports == WG_EXPORTS, ctr) 60 if rc == 0 { 61 gv_check("last function retains high type index", m.func_type[WG_FUNCS-1] == WG_TYPES-1 && m.type_nres[WG_TYPES-1] == 1, ctr) 62 gv_check("late export resolves beyond old1024 bound", wm_find_export(m, "f1091") == WG_FUNCS-1, ctr) 63 gv_check("late export executes last function", wm_run(m, "f1091", 0, 0, 0, 0, 0, 0) == 7, ctr) 64 } 65 wg_refuse(b, 7, "short header refuses before metadata writes", ctr) 66 let version: u8 = b[4]; b[4] = 2 as u8 67 wg_refuse(b, n, "unsupported version refuses before metadata writes", ctr); b[4] = version 68 wg_refuse(b, n - 1, "truncated section refuses before metadata writes", ctr) 69 let ft: i64 = marks[0]; let old_type: u8 = b[ft+1]; b[ft+1] = 127 as u8 70 wg_refuse(b, n, "invalid function type index refuses before metadata writes", ctr); b[ft+1] = old_type 71 let ex: i64 = marks[1]; let ex0: u8 = b[ex]; let ex1: u8 = b[ex+1] 72 wg_u32(b, ex, WG_EXPORTS + WG_FUNCS * 16) 73 wg_refuse(b, n, "export count larger than section refuses before writes", ctr); b[ex] = ex0; b[ex+1] = ex1 74 // Rebuild because the inflated LEB intentionally extends into the first name byte. 75 wg_image(b, marks) 76 let cd: i64 = marks[2]; let old_code: u8 = b[cd]; b[cd] = (old_code - (1 as u8)) as u8 77 wg_refuse(b, n, "code/function count mismatch refuses before metadata writes", ctr); b[cd] = old_code 78 // A name length that crosses its export-section boundary must never reach table writes. 79 let name_at: i64 = marks[1] + 2 80 let saved_name0: u8 = b[name_at]; let saved_name1: u8 = b[name_at+1]; let saved_name2: u8 = b[name_at+2] 81 wg_u32(b, name_at, n) 82 wg_refuse(b, n, "export name exceeding section refuses before metadata writes", ctr) 83 b[name_at] = saved_name0; b[name_at+1] = saved_name1; b[name_at+2] = saved_name2 84 let body_at: i64 = marks[2] + 2; let body_size: u8 = b[body_at] 85 b[body_at] = 1 as u8 86 wg_refuse(b, n, "body too short for locals and end refuses before writes", ctr) 87 b[body_at] = body_size 88 wg_refuse(0 as *u8, 8, "null image refuses before header reads", ctr) 89 let z: *u8 = sys_mmap(16); var zi: i64 = 0 90 while zi < 8 { z[zi] = b[zi]; zi = zi + 1 } 91 z[8] = 1 as u8; z[9] = 128 as u8 92 wg_refuse(z, 10, "truncated unsigned LEB refuses before metadata writes", ctr) 93 z[9] = 255 as u8; z[10] = 255 as u8; z[11] = 255 as u8; z[12] = 255 as u8; z[13] = 31 as u8 94 wg_refuse(z, 14, "u32 LEB overflow refuses before metadata writes", ctr) 95 let empty: *WasmMod = wm_new(z, 8) 96 gv_check("empty valid module remains accepted", wm_parse(empty) == 0 && empty.n_exports == 0, ctr) 97 return gv_verdict("WASM-METADATA-BOUNDS", ctr, "Metadata bounds only; bytecode instruction validation and live Beach interaction separate.") 98}