code wiki / (root) / nx_av1_obu_gate.nx

nx_av1_obu_gate.nx source

↩ module page · 198 lines · 8565 B

1// nx_av1_obu_gate.nx -- proves the AV1/AV2 OBU layer by ROUND-TRIP. 2// 3// T2 pins LEB128 to its canonical encodings absolutely (128 -> 0x80 0x01), 4// because a writer that emits a longer-than-necessary form still round-trips 5// against its own reader while producing streams other decoders reject. 6// 7// T6/T7 are the security-shaped ones: obu_forbidden_bit and obu_reserved_1bit 8// must both be REFUSED. A parser that ignores them consumes arbitrary bytes 9// as headers and resynchronises onto garbage -- the standard way a malformed 10// file becomes a long walk through memory. T8 also bounds LEB128 at 8 bytes, 11// so a continuation run cannot march off the buffer. 12// 13// T4 separates UVLC from LEB128. They are both 'variable length' and they are 14// not the same code; confusing them misreads every frame-header field after 15// the first, silently. 16// 17// license_tier: ORIGINAL 18import "nx_syscalls.nx" 19import "nx_bitstream.nx" 20import "nx_av1_obu.nx" 21 22func g_puts(s: *u8) -> i64 { 23 var i: i64 = 0 24 while s[i] != (0 as u8) { i = i + 1 } 25 sys_write(1, s, i) 26 return i 27} 28 29func g_putn(v: i64) -> i64 { 30 let buf: *u8 = sys_mmap(32) 31 var x: i64 = v 32 if x < 0 { g_puts("-" as *u8); x = 0 - x } 33 if x == 0 { buf[0] = 0x30 as u8; sys_write(1, buf, 1); return 1 } 34 let tmp: *u8 = sys_mmap(32) 35 var d: i64 = 0 36 while x > 0 { tmp[d] = ((x % 10) + 0x30) as u8; x = x / 10; d = d + 1 } 37 var i: i64 = 0 38 while i < d { buf[i] = tmp[d - 1 - i]; i = i + 1 } 39 sys_write(1, buf, d) 40 return d 41} 42 43func main() -> i64 { 44 var fails: i64 = 0 45 var mark: i64 = 0 46 47 // ---- T1: LEB128 round-trip across the group boundaries ---- 48 let lb: *u8 = sys_mmap(256) 49 let ll: *i64 = sys_mmap(64) as *i64 50 let vals: *i64 = sys_mmap(128) as *i64 51 vals[0] = 0; vals[1] = 1; vals[2] = 127; vals[3] = 128 52 vals[4] = 16383; vals[5] = 16384; vals[6] = 2097151; vals[7] = 268435455 53 var k: i64 = 0 54 while k < 8 { 55 let w: i64 = nx_obu_leb128_write(lb, 256, 0, vals[k]) 56 if w <= 0 { fails = fails + 1 } else { 57 if nx_obu_leb128_read(lb, 256, 0, ll) != vals[k] { fails = fails + 1 } 58 if ll[0] != w { fails = fails + 1 } 59 } 60 k = k + 1 61 } 62 if fails > 0 { if mark == 0 { mark = 1 } } 63 64 // ---- T2: the CANONICAL encodings, pinned absolutely ---- 65 nx_obu_leb128_write(lb, 256, 0, 0) 66 if (lb[0] as i64 & 255) != 0x00 { fails = fails + 1 } 67 nx_obu_leb128_write(lb, 256, 0, 127) 68 if (lb[0] as i64 & 255) != 0x7f { fails = fails + 1 } 69 // 128 must be exactly two bytes: 0x80 0x01 70 if nx_obu_leb128_write(lb, 256, 0, 128) != 2 { fails = fails + 1 } 71 if (lb[0] as i64 & 255) != 0x80 { fails = fails + 1 } 72 if (lb[1] as i64 & 255) != 0x01 { fails = fails + 1 } 73 // 16384 must be exactly three: 0x80 0x80 0x01 74 if nx_obu_leb128_write(lb, 256, 0, 16384) != 3 { fails = fails + 1 } 75 if (lb[0] as i64 & 255) != 0x80 { fails = fails + 1 } 76 if (lb[2] as i64 & 255) != 0x01 { fails = fails + 1 } 77 if fails > 0 { if mark == 0 { mark = 2 } } 78 79 // ---- T4: UVLC is NOT LEB128 -- Exp-Golomb style, MSB-first ---- 80 let ub: *u8 = sys_mmap(64) 81 ub[0] = 0x80 as u8 // '1' -> 0 82 let b1: *NxBitStream = nx_bitstream_alloc(ub, 1) 83 if nx_obu_uvlc(b1) != 0 { fails = fails + 1 } 84 ub[0] = 0x40 as u8 // '0','1','0' -> 1 85 let b2: *NxBitStream = nx_bitstream_alloc(ub, 1) 86 if nx_obu_uvlc(b2) != 1 { fails = fails + 1 } 87 ub[0] = 0x60 as u8 // '0','1','1' -> 2 88 let b3: *NxBitStream = nx_bitstream_alloc(ub, 1) 89 if nx_obu_uvlc(b3) != 2 { fails = fails + 1 } 90 ub[0] = 0x20 as u8 // '0','0','1','0','0' -> 3 91 let b4: *NxBitStream = nx_bitstream_alloc(ub, 1) 92 if nx_obu_uvlc(b4) != 3 { fails = fails + 1 } 93 if fails > 0 { if mark == 0 { mark = 4 } } 94 95 // ---- T5: write three OBUs and walk the temporal unit back ---- 96 let tu: *u8 = sys_mmap(4096) 97 let pay1: *u8 = sys_mmap(256) 98 var i: i64 = 0 99 while i < 40 { pay1[i] = ((i * 3) & 255) as u8; i = i + 1 } 100 let pay2: *u8 = sys_mmap(512) 101 i = 0 102 while i < 200 { pay2[i] = ((i * 7 + 1) & 255) as u8; i = i + 1 } 103 104 var off: i64 = 0 105 // a temporal delimiter carries no payload 106 off = nx_obu_write(tu, 4096, off, NX_OBU_TEMPORAL_DELIM, 0, 0, 0, pay1, 0) 107 if off <= 0 { fails = fails + 1 } 108 off = nx_obu_write(tu, 4096, off, NX_OBU_SEQ_HEADER, 0, 0, 0, pay1, 40) 109 if off <= 0 { fails = fails + 1 } 110 // a frame OBU carrying the extension header, temporal 5 spatial 2 111 off = nx_obu_write(tu, 4096, off, NX_OBU_FRAME, 5, 2, 1, pay2, 200) 112 if off <= 0 { fails = fails + 1 } 113 114 if nx_obu_count(tu, off) != 3 { fails = fails + 1 } 115 116 let fld: *i64 = sys_mmap(128) as *i64 117 var p: i64 = 0 118 var seen: i64 = 0 119 var bad: i64 = 0 120 while seen < 3 { 121 if nx_obu_parse(tu, off, p, fld) != 1 { fails = fails + 1; seen = 3 } else { 122 if seen == 0 { 123 if fld[NX_OBU_FLD_TYPE] != NX_OBU_TEMPORAL_DELIM { bad = bad + 1 } 124 if fld[NX_OBU_FLD_PAYLEN] != 0 { bad = bad + 1 } 125 } 126 if seen == 1 { 127 if fld[NX_OBU_FLD_TYPE] != NX_OBU_SEQ_HEADER { bad = bad + 1 } 128 if fld[NX_OBU_FLD_PAYLEN] != 40 { bad = bad + 1 } 129 let po: i64 = fld[NX_OBU_FLD_PAYOFF] 130 var j: i64 = 0 131 while j < 40 { 132 if (tu[po+j] as i64 & 255) != (pay1[j] as i64 & 255) { bad = bad + 1 } 133 j = j + 1 134 } 135 } 136 if seen == 2 { 137 if fld[NX_OBU_FLD_TYPE] != NX_OBU_FRAME { bad = bad + 1 } 138 if fld[NX_OBU_FLD_EXTFLAG] != 1 { bad = bad + 1 } 139 if fld[NX_OBU_FLD_TEMPORAL] != 5 { bad = bad + 1 } 140 if fld[NX_OBU_FLD_SPATIAL] != 2 { bad = bad + 1 } 141 if fld[NX_OBU_FLD_PAYLEN] != 200 { bad = bad + 1 } 142 let po2: i64 = fld[NX_OBU_FLD_PAYOFF] 143 var j2: i64 = 0 144 while j2 < 200 { 145 if (tu[po2+j2] as i64 & 255) != (pay2[j2] as i64 & 255) { bad = bad + 1 } 146 j2 = j2 + 1 147 } 148 } 149 p = fld[NX_OBU_FLD_NEXT] 150 seen = seen + 1 151 } 152 } 153 if bad != 0 { fails = fails + 1 } 154 if p != off { fails = fails + 1 } 155 if fails > 0 { if mark == 0 { mark = 5 } } 156 157 // ---- T6 NEG: obu_forbidden_bit must be REFUSED ---- 158 tu[0] = ((tu[0] as i64) | 0x80) as u8 159 if nx_obu_parse(tu, off, 0, fld) != 0 { fails = fails + 1 } 160 if nx_obu_count(tu, off) != (0 - 1) { fails = fails + 1 } 161 tu[0] = ((tu[0] as i64) & 0x7f) as u8 162 if nx_obu_parse(tu, off, 0, fld) != 1 { fails = fails + 1 } 163 if fails > 0 { if mark == 0 { mark = 6 } } 164 165 // ---- T7 NEG: obu_reserved_1bit must be REFUSED ---- 166 tu[0] = ((tu[0] as i64) | 0x01) as u8 167 if nx_obu_parse(tu, off, 0, fld) != 0 { fails = fails + 1 } 168 tu[0] = ((tu[0] as i64) & 0xfe) as u8 169 if nx_obu_parse(tu, off, 0, fld) != 1 { fails = fails + 1 } 170 if fails > 0 { if mark == 0 { mark = 7 } } 171 172 // ---- T8 NEG: LEB128 is BOUNDED -- a runaway continuation is refused ---- 173 let run: *u8 = sys_mmap(64) 174 i = 0 175 while i < 16 { run[i] = 0xff as u8; i = i + 1 } 176 if nx_obu_leb128_read(run, 16, 0, ll) != (0 - 1) { fails = fails + 1 } 177 // and a continuation that runs past the buffer end 178 run[0] = 0x80 as u8 179 if nx_obu_leb128_read(run, 1, 0, ll) != (0 - 1) { fails = fails + 1 } 180 // out-of-range write arguments 181 if nx_obu_write(tu, 4096, 0, 16, 0, 0, 0, pay1, 0) != 0 { fails = fails + 1 } 182 if nx_obu_write(tu, 4096, 0, 1, 8, 0, 1, pay1, 0) != 0 { fails = fails + 1 } 183 if nx_obu_write(tu, 4, 0, 1, 0, 0, 0, pay1, 40) != 0 { fails = fails + 1 } 184 if fails > 0 { if mark == 0 { mark = 8 } } 185 186 if fails == 0 { 187 g_puts("GATE nx_av1_obu verdict=GREEN pass=8/8 (LEB128 round-trip across group boundaries; CANONICAL encodings pinned 128=0x80,0x01 and 16384=3 bytes; UVLC Exp-Golomb 0/1/2/3 distinct from LEB128; 3-OBU temporal unit written and walked back with extension ids temporal=5 spatial=2 and 240 payload bytes EXACT; NEG forbidden-bit and reserved-bit both refused then restored-and-accepted; LEB128 bounded at 8 bytes and at the buffer end; bad type/temporal-id/capacity refused)\n" as *u8) 188 sys_exit(0) 189 return 0 190 } 191 g_puts("GATE nx_av1_obu verdict=RED fails=" as *u8) 192 g_putn(fails) 193 g_puts(" first_stage=" as *u8) 194 g_putn(mark) 195 g_puts("\n" as *u8) 196 sys_exit(1) 197 return 1 198}