code wiki / (root) / nx_wasm_memory_lib.nx

nx_wasm_memory_lib.nx source

↩ module page · 100 lines · 3333 B

1// Allocation-free inspection of Nishi's single-memory Wasm artifacts. 2// This reads the memory contract only; it is not a full Wasm validator. 3const WM_U32_BITS: i64=32 4const WM_LEB_BITS: i64=7 5const WM_U32_MAX: i64=4294967295 6const WM_PAGE_MAX: i64=65536 7const WM_HEADER: i64=8 8const WM_FIELDS: i64=4 // minimum pages, maximum (-1 absent), shared, imported. 9struct WMemReader { b: *u8, end: i64, at: i64, error: i64 } 10func wmem_byte(r: *WMemReader) -> i64 { 11 if r.error<0 { return 0 } 12 if r.at>=r.end { r.error=0-1; return 0 } 13 let v: i64=r.b[r.at] as i64 14 r.at=r.at+1 15 return v 16} 17func wmem_u32(r: *WMemReader) -> i64 { 18 var value: i64=0 19 var shift: i64=0 20 while shift<WM_U32_BITS { 21 let b: i64=wmem_byte(r) 22 if r.error<0 { return 0 } 23 let payload: i64=b&127 24 if payload>(WM_U32_MAX>>shift) { r.error=0-2;return 0 } 25 value=value|(payload<<shift) 26 if (b&128)==0 { return value } 27 shift=shift+WM_LEB_BITS 28 } 29 r.error=0-2 30 return 0 31} 32func wmem_name(r: *WMemReader) -> i64 { 33 let n: i64=wmem_u32(r) 34 if n>r.end-r.at { r.error=0-1;return 0 } 35 r.at=r.at+n 36 return 0 37} 38func wmem_limits(r: *WMemReader,out: *i64,imported: i64) -> i64 { 39 let flags: i64=wmem_u32(r) 40 if flags!=0 { if flags!=1 { if flags!=3 { r.error=0-3;return 0 } } } 41 let low: i64=wmem_u32(r) 42 var high: i64=0-1 43 if (flags&1)!=0 { high=wmem_u32(r) } 44 if r.error<0 { return 0 } 45 if low>WM_PAGE_MAX { r.error=0-4;return 0 } 46 if high>WM_PAGE_MAX { r.error=0-4;return 0 } 47 if high>=0 { if high<low { r.error=0-4;return 0 } } 48 out[0]=low;out[1]=high;out[2]=(flags>>1)&1;out[3]=imported 49 return 0 50} 51func wmem_read(b: *u8,n: i64,out: *i64) -> i64 { 52 if n<WM_HEADER { return 0-1 } 53 if b[0]!=(0 as u8) { return 0-5 } 54 if b[1]!=(97 as u8) { return 0-5 } 55 if b[2]!=(115 as u8) { return 0-5 } 56 if b[3]!=(109 as u8) { return 0-5 } 57 if b[4]!=(1 as u8) { return 0-5 } 58 if b[5]!=(0 as u8) { return 0-5 } 59 if b[6]!=(0 as u8) { return 0-5 } 60 if b[7]!=(0 as u8) { return 0-5 } 61 var r: WMemReader 62 r.b=b;r.at=WM_HEADER;r.end=n;r.error=0 63 var found: i64=0 64 while r.at<n { 65 let section: i64=wmem_byte(&r) 66 let size: i64=wmem_u32(&r) 67 if r.error<0 { return r.error } 68 if size>n-r.at { return 0-1 } 69 let end: i64=r.at+size 70 r.end=end 71 if section==2 { 72 let count: i64=wmem_u32(&r) 73 var i: i64=0 74 while i<count { 75 wmem_name(&r);wmem_name(&r) 76 let kind: i64=wmem_byte(&r) 77 if r.error<0 { return r.error } 78 if kind==0 { wmem_u32(&r) } else { 79 if kind!=2 { return 0-6 } 80 if found!=0 { return 0-7 } 81 wmem_limits(&r,out,1);found=1 82 } 83 if r.error<0 { return r.error } 84 i=i+1 85 } 86 if r.at!=end { return 0-8 } 87 } 88 if section==5 { 89 let count: i64=wmem_u32(&r) 90 if count!=1 { return 0-7 } 91 if found!=0 { return 0-7 } 92 wmem_limits(&r,out,0);found=1 93 if r.error<0 { return r.error } 94 if r.at!=end { return 0-8 } 95 } 96 r.at=end;r.end=n 97 } 98 if found==0 { return 0-9 } 99 return 0 100}