code wiki / (root) / nx_jpeg_marker_test.nx

nx_jpeg_marker_test.nx source

↩ module page · 188 lines · 9500 B

1// nx_jpeg_marker_test.nx -- KAT for JPEG marker scanner. 2// 3// Exercises: 4// - minimal SOI/EOI document 5// - SOI, APP0 (with payload), DQT (with payload), SOF0, SOS, EOI sequence 6// - marker classification (SOF0 vs SOF2 vs SOF_OTHER) 7// - length-less markers (SOI/EOI/RSTn) 8// - 0xFF fill-byte tolerance between segments 9// - 0xFF 0x00 stuffing-byte rejection as marker (should be skipped) 10// - truncation detection (length runs past buffer) 11// 12// expect_exit: 0 13// license_tier: ORIGINAL 14 15import "nx_syscalls.nx" 16import "nx_jpeg_marker.nx" 17 18func _fail(n: i64) -> i64 { 19 let b: *u8 = sys_mmap(16) 20 b[0]=0x46; b[1]=0x41; b[2]=0x49; b[3]=0x4C; b[4]=0x3D 21 sys_write(2, b, 5) 22 var x: i64 = n 23 if x < 0 { let m: *u8 = sys_mmap(4); m[0]=0x2D; sys_write(2, m, 1); x = 0 - x } 24 if x == 0 { let z: *u8 = sys_mmap(4); z[0]=0x30; sys_write(2, z, 1) } 25 else { 26 let buf: *u8 = sys_mmap(16) 27 var pos: i64 = 0 28 while x > 0 { buf[pos] = (0x30 + (x % 10)) as u8; x = x / 10; pos = pos + 1 } 29 let out: *u8 = sys_mmap(16) 30 var i: i64 = 0 31 while i < pos { out[i] = buf[pos - 1 - i]; i = i + 1 } 32 sys_write(2, out, pos) 33 } 34 let nl: *u8 = sys_mmap(4); nl[0]=0x0A; sys_write(2, nl, 1) 35 return 0 36} 37 38func main() -> i64 { 39 // ============================================================ 40 // Section A: classification + length-less predicates 41 // ============================================================ 42 if nx_jpeg_classify_marker(0xD8) != NX_JPEG_M_SOI { _fail(1); return 1 } 43 if nx_jpeg_classify_marker(0xD9) != NX_JPEG_M_EOI { _fail(2); return 2 } 44 if nx_jpeg_classify_marker(0xC0) != NX_JPEG_M_SOF0 { _fail(3); return 3 } 45 if nx_jpeg_classify_marker(0xC2) != NX_JPEG_M_SOF2 { _fail(4); return 4 } 46 if nx_jpeg_classify_marker(0xC1) != NX_JPEG_M_SOF_OTHER { _fail(5); return 5 } // extended-sequential 47 if nx_jpeg_classify_marker(0xC4) != NX_JPEG_M_DHT { _fail(6); return 6 } 48 if nx_jpeg_classify_marker(0xDB) != NX_JPEG_M_DQT { _fail(7); return 7 } 49 if nx_jpeg_classify_marker(0xDA) != NX_JPEG_M_SOS { _fail(8); return 8 } 50 if nx_jpeg_classify_marker(0xDD) != NX_JPEG_M_DRI { _fail(9); return 9 } 51 if nx_jpeg_classify_marker(0xE0) != NX_JPEG_M_APP { _fail(10); return 10 } 52 if nx_jpeg_classify_marker(0xEF) != NX_JPEG_M_APP { _fail(11); return 11 } 53 if nx_jpeg_classify_marker(0xFE) != NX_JPEG_M_COM { _fail(12); return 12 } 54 if nx_jpeg_classify_marker(0xD0) != NX_JPEG_M_RST { _fail(13); return 13 } 55 if nx_jpeg_classify_marker(0xD7) != NX_JPEG_M_RST { _fail(14); return 14 } 56 57 if nx_jpeg_marker_is_lengthless(0xD8) != 1 { _fail(20); return 20 } 58 if nx_jpeg_marker_is_lengthless(0xD9) != 1 { _fail(21); return 21 } 59 if nx_jpeg_marker_is_lengthless(0xD0) != 1 { _fail(22); return 22 } 60 if nx_jpeg_marker_is_lengthless(0xD7) != 1 { _fail(23); return 23 } 61 if nx_jpeg_marker_is_lengthless(0xC0) != 0 { _fail(24); return 24 } 62 if nx_jpeg_marker_is_lengthless(0xDB) != 0 { _fail(25); return 25 } 63 64 // ============================================================ 65 // Section B: minimal SOI / EOI document (4 bytes) 66 // ============================================================ 67 let s_min: *u8 = sys_mmap(8) 68 s_min[0]=0xFF; s_min[1]=0xD8; s_min[2]=0xFF; s_min[3]=0xD9 69 70 let c: *NxJpegCursor = sys_mmap(NX_JPEG_CURSOR_BYTES) as *NxJpegCursor 71 let seg: *NxJpegSegment = sys_mmap(NX_JPEG_SEG_BYTES) as *NxJpegSegment 72 73 nx_jpeg_seg_init(c, s_min, 4) 74 if nx_jpeg_seg_next(c, seg) != NX_JPEG_SEG_OK { _fail(30); return 30 } 75 if seg.marker != 0xD8 { _fail(31); return 31 } 76 if seg.kind != NX_JPEG_M_SOI { _fail(32); return 32 } 77 if seg.seg_off != 0 { _fail(33); return 33 } 78 if seg.seg_len != 2 { _fail(34); return 34 } 79 if seg.payload_len != 0 { _fail(35); return 35 } 80 81 if nx_jpeg_seg_next(c, seg) != NX_JPEG_SEG_OK { _fail(40); return 40 } 82 if seg.marker != 0xD9 { _fail(41); return 41 } 83 if seg.kind != NX_JPEG_M_EOI { _fail(42); return 42 } 84 if seg.seg_off != 2 { _fail(43); return 43 } 85 if seg.seg_len != 2 { _fail(44); return 44 } 86 87 if nx_jpeg_seg_next(c, seg) != NX_JPEG_SEG_EOF { _fail(50); return 50 } 88 89 // ============================================================ 90 // Section C: full canonical structure 91 // SOI(0) APP0(2..) DQT(..) SOF0(..) SOS(..) EOI(..) 92 // APP0 payload = JFIF magic (16 bytes typical, here we use 4 for test). 93 // ============================================================ 94 let s: *u8 = sys_mmap(128) 95 var k: i64 = 0 96 s[k]=0xFF; k=k+1; s[k]=0xD8; k=k+1 // SOI 97 // APP0: 0xFF E0 LL LL payload(4) 98 s[k]=0xFF; k=k+1; s[k]=0xE0; k=k+1 99 s[k]=0x00; k=k+1; s[k]=0x06; k=k+1 // length=6 (incl LL) 100 s[k]=0x4A; k=k+1; s[k]=0x46; k=k+1; s[k]=0x49; k=k+1; s[k]=0x46; k=k+1 // "JFIF" 101 // DQT: 0xFF DB LL LL payload(2) 102 s[k]=0xFF; k=k+1; s[k]=0xDB; k=k+1 103 s[k]=0x00; k=k+1; s[k]=0x04; k=k+1 // length=4 104 s[k]=0x00; k=k+1; s[k]=0x10; k=k+1 // tiny payload 105 // SOF0: 0xFF C0 LL LL payload(3) 106 s[k]=0xFF; k=k+1; s[k]=0xC0; k=k+1 107 s[k]=0x00; k=k+1; s[k]=0x05; k=k+1 // length=5 108 s[k]=0x08; k=k+1; s[k]=0x00; k=k+1; s[k]=0x01; k=k+1 109 // SOS: 0xFF DA LL LL payload(2) 110 s[k]=0xFF; k=k+1; s[k]=0xDA; k=k+1 111 s[k]=0x00; k=k+1; s[k]=0x04; k=k+1 112 s[k]=0x01; k=k+1; s[k]=0x00; k=k+1 113 // EOI 114 s[k]=0xFF; k=k+1; s[k]=0xD9; k=k+1 115 let total_len: i64 = k 116 117 nx_jpeg_seg_init(c, s, total_len) 118 119 // 1: SOI 120 if nx_jpeg_seg_next(c, seg) != NX_JPEG_SEG_OK { _fail(60); return 60 } 121 if seg.kind != NX_JPEG_M_SOI { _fail(61); return 61 } 122 123 // 2: APP0 124 if nx_jpeg_seg_next(c, seg) != NX_JPEG_SEG_OK { _fail(70); return 70 } 125 if seg.kind != NX_JPEG_M_APP { _fail(71); return 71 } 126 if seg.marker != 0xE0 { _fail(72); return 72 } 127 if seg.payload_len != 4 { _fail(73); return 73 } 128 if s[seg.payload_off] != 0x4A { _fail(74); return 74 } // 'J' 129 if s[seg.payload_off + 3] != 0x46 { _fail(75); return 75 } // 'F' 130 131 // 3: DQT 132 if nx_jpeg_seg_next(c, seg) != NX_JPEG_SEG_OK { _fail(80); return 80 } 133 if seg.kind != NX_JPEG_M_DQT { _fail(81); return 81 } 134 if seg.payload_len != 2 { _fail(82); return 82 } 135 if s[seg.payload_off] != 0x00 { _fail(83); return 83 } 136 if s[seg.payload_off + 1] != 0x10 { _fail(84); return 84 } 137 138 // 4: SOF0 139 if nx_jpeg_seg_next(c, seg) != NX_JPEG_SEG_OK { _fail(90); return 90 } 140 if seg.kind != NX_JPEG_M_SOF0 { _fail(91); return 91 } 141 if seg.payload_len != 3 { _fail(92); return 92 } 142 if s[seg.payload_off] != 0x08 { _fail(93); return 93 } 143 if s[seg.payload_off + 2] != 0x01 { _fail(94); return 94 } 144 145 // 5: SOS 146 if nx_jpeg_seg_next(c, seg) != NX_JPEG_SEG_OK { _fail(100); return 100 } 147 if seg.kind != NX_JPEG_M_SOS { _fail(101); return 101 } 148 if seg.payload_len != 2 { _fail(102); return 102 } 149 150 // 6: EOI 151 if nx_jpeg_seg_next(c, seg) != NX_JPEG_SEG_OK { _fail(110); return 110 } 152 if seg.kind != NX_JPEG_M_EOI { _fail(111); return 111 } 153 154 // 7: EOF 155 if nx_jpeg_seg_next(c, seg) != NX_JPEG_SEG_EOF { _fail(120); return 120 } 156 157 // ============================================================ 158 // Section D: 0xFF fill-byte tolerance + 0xFF 0x00 stuffing-byte 159 // stream = SOI 0xFF 0xFF 0xFF EOI (multiple fill bytes) 160 // ============================================================ 161 let s2: *u8 = sys_mmap(16) 162 s2[0]=0xFF; s2[1]=0xD8 // SOI 163 s2[2]=0xFF; s2[3]=0xFF; s2[4]=0xFF; s2[5]=0xD9 // fill + EOI 164 nx_jpeg_seg_init(c, s2, 6) 165 if nx_jpeg_seg_next(c, seg) != NX_JPEG_SEG_OK { _fail(130); return 130 } 166 if seg.kind != NX_JPEG_M_SOI { _fail(131); return 131 } 167 if nx_jpeg_seg_next(c, seg) != NX_JPEG_SEG_OK { _fail(132); return 132 } 168 if seg.kind != NX_JPEG_M_EOI { _fail(133); return 133 } 169 if nx_jpeg_seg_next(c, seg) != NX_JPEG_SEG_EOF { _fail(134); return 134 } 170 171 // ============================================================ 172 // Section E: malformed -- bogus length runs past buffer 173 // SOI then 0xFF DB with claimed length 0x00FF but only 4 bytes after 174 // ============================================================ 175 let s3: *u8 = sys_mmap(16) 176 s3[0]=0xFF; s3[1]=0xD8 // SOI 177 s3[2]=0xFF; s3[3]=0xDB // DQT marker 178 s3[4]=0x00; s3[5]=0xFF // claimed length 255 179 s3[6]=0x00; s3[7]=0x00 // only 2 bytes follow 180 nx_jpeg_seg_init(c, s3, 8) 181 if nx_jpeg_seg_next(c, seg) != NX_JPEG_SEG_OK { _fail(140); return 140 } // SOI 182 if nx_jpeg_seg_next(c, seg) != NX_JPEG_SEG_TRUNC { _fail(141); return 141 } 183 184 let pass: *u8 = sys_mmap(16) 185 pass[0]=0x50; pass[1]=0x41; pass[2]=0x53; pass[3]=0x53; pass[4]=0x0A 186 sys_write(1, pass, 5) 187 return 0 188}