code wiki / (root) / nx_zlib_wrap.nx

nx_zlib_wrap.nx source

↩ module page · 286 lines · 10096 B

1// nx_zlib_wrap.nx -- RFC 1950 zlib container (DEFLATE + headers + Adler-32). 2// 3// CAPABILITY_COMPLETENESS: FULL 4// 5// zlib stream layout per RFC 1950: 6// 7// +---+---+ 2-byte header 8// |CMF|FLG| 9// +---+---+ 10// | ... | DEFLATE-compressed data (RFC 1951) 11// +-------+ 12// |Adler32| 4-byte big-endian Adler-32 of uncompressed data 13// +-------+ 14// 15// CMF (compression method + flags): 16// bits 0-3 CM (4 = deflate is reserved; 8 = deflate stream) 17// bits 4-7 CINFO (log2(window-size) - 8); for 32 KB window = 7 18// 19// FLG: 20// bits 0-4 FCHECK -- chosen so (CMF*256 + FLG) mod 31 == 0 21// bit 5 FDICT -- 1 if preset dictionary in use (rare; refused 22// in v1; queued as `feedback-preset-dict` work) 23// bits 6-7 FLEVEL -- compression-level hint (advisory; ignored) 24// 25// genealogy_id: rfc1950_zlib_1996 26// lineage_id: nx_zlib_wrap_v1 27// 28// Composes: nx_deflate (INFLATE) + nx_adler32 (already shipped). 29 30// nx_safety_envelope: 31// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 32// sil_target: SIL1 33// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 34// verdict: NOT_YET_EVALUATED 35 36import "nx_syscalls.nx" 37import "nx_runtime.nx" 38import "nx_tier.nx" 39import "nx_deflate.nx" 40import "nx_adler32.nx" 41const NX_MAGIC_16449714: i64 = 16449714 42const NX_MAGIC_30720: i64 = 30720 43 44// ===== error codes ================================================ 45 46const NX_ZLIB_OK: nx_int = 0 47const NX_ZLIB_ERR_TOO_SHORT: nx_int = 1 48const NX_ZLIB_ERR_BAD_METHOD: nx_int = 2 49const NX_ZLIB_ERR_BAD_CHECK: nx_int = 3 50const NX_ZLIB_ERR_PRESET_DICT: nx_int = 4 51const NX_ZLIB_ERR_DEFLATE: nx_int = 5 52const NX_ZLIB_ERR_ADLER_MISMATCH: nx_int = 6 53const NX_ZLIB_ERR_OUTPUT_CAPACITY: nx_int = 7 54 55// ===== result struct ============================================== 56 57struct NxZlibResult { 58 output_data: *u8, 59 output_size: nx_int, 60 bytes_consumed: nx_int, 61 error_code: nx_int, 62 cm: nx_int, 63 cinfo: nx_int, 64 fdict: nx_int, 65 flevel: nx_int, 66 adler_expected: nx_int, 67 adler_computed: nx_int, 68} 69 70const NX_ZLIB_RESULT_BYTES: nx_size = 80 71 72// ===== inflate full zlib stream =================================== 73 74func nx_zlib_inflate(input: *u8, input_size: nx_int, 75 max_output: nx_int) -> *NxZlibResult { 76 let r_ptr: *u8 = sys_mmap(NX_ZLIB_RESULT_BYTES) 77 let r: *NxZlibResult = r_ptr as *NxZlibResult 78 r.output_data = 0 as *u8 79 r.output_size = 0 80 r.bytes_consumed = 0 81 r.error_code = NX_ZLIB_OK 82 83 if input_size < 6 { // 2-byte header + min 0-byte DEFLATE + 4-byte trailer 84 r.error_code = NX_ZLIB_ERR_TOO_SHORT 85 return r 86 } 87 88 let cmf: nx_int = (input[0] as nx_int) & 255 89 let flg: nx_int = (input[1] as nx_int) & 255 90 let cm: nx_int = cmf & 15 91 let cinfo: nx_int = (cmf >> 4) & 15 92 let fdict: nx_int = (flg >> 5) & 1 93 let flevel: nx_int = (flg >> 6) & 3 94 r.cm = cm 95 r.cinfo = cinfo 96 r.fdict = fdict 97 r.flevel = flevel 98 99 if cm != 8 { 100 r.error_code = NX_ZLIB_ERR_BAD_METHOD 101 return r 102 } 103 // FCHECK: (cmf*256 + flg) mod 31 must equal 0. 104 let check_val: nx_int = (cmf * 256 + flg) % 31 105 if check_val != 0 { 106 r.error_code = NX_ZLIB_ERR_BAD_CHECK 107 return r 108 } 109 if fdict == 1 { 110 // Preset dictionary requires the caller to supply the 111 // dictionary out-of-band -- queued capability. 112 r.error_code = NX_ZLIB_ERR_PRESET_DICT 113 return r 114 } 115 116 // DEFLATE-compressed payload starts at offset 2 and ends 4 117 // bytes before EOF (Adler-32 trailer). 118 let payload_size: nx_int = input_size - 2 - 4 119 let payload: *u8 = (input as nx_int + 2) as *u8 120 121 let def_r: *NxDeflateResult = nx_deflate_inflate( 122 payload, payload_size, max_output) 123 if def_r == (0 as *NxDeflateResult) { 124 r.error_code = NX_ZLIB_ERR_DEFLATE 125 return r 126 } 127 if def_r.error_code != NX_DEF_OK { 128 r.error_code = NX_ZLIB_ERR_DEFLATE 129 if def_r.error_code == NX_DEF_ERR_OUTPUT_CAPACITY { r.error_code = NX_ZLIB_ERR_OUTPUT_CAPACITY } 130 r.output_data = def_r.output_data 131 r.output_size = def_r.output_size 132 r.bytes_consumed = 2 + def_r.bytes_consumed 133 return r 134 } 135 136 // Read 4-byte big-endian Adler-32 trailer. 137 let trailer_off: nx_int = 2 + def_r.bytes_consumed 138 if (trailer_off + 4) > input_size { 139 r.error_code = NX_ZLIB_ERR_TOO_SHORT 140 return r 141 } 142 let a0: nx_int = (input[trailer_off] as nx_int) & 255 143 let a1: nx_int = (input[trailer_off + 1] as nx_int) & 255 144 let a2: nx_int = (input[trailer_off + 2] as nx_int) & 255 145 let a3: nx_int = (input[trailer_off + 3] as nx_int) & 255 146 let adler_expected: nx_int = (a0 << 24) | (a1 << 16) | (a2 << 8) | a3 147 148 // Verify Adler-32 over the inflated output. 149 let adler_computed: nx_int = adler32(def_r.output_data, def_r.output_size) 150 r.adler_expected = adler_expected 151 r.adler_computed = adler_computed 152 153 if adler_expected != adler_computed { 154 r.error_code = NX_ZLIB_ERR_ADLER_MISMATCH 155 } 156 157 r.output_data = def_r.output_data 158 r.output_size = def_r.output_size 159 r.bytes_consumed = trailer_off + 4 160 return r 161} 162 163// ===== self-test ================================================== 164// 165// Construct a minimal zlib stream by hand: 166// CMF = 0x78 (CM=8 deflate, CINFO=7 32KB window) 167// FLG chosen so (0x78*256 + FLG) % 31 == 0 168// 0x78 * 256 = 30720; 30720 % 31 = 30720 - 31*991 = 30720 - 30721 = -1 = 30 169// FLG must satisfy (30 + FLG) % 31 == 0 -> FLG = 1. 170// With FDICT=0 FLEVEL=0 FCHECK=1 -> FLG = 1. 171// Payload: BFINAL=1 BTYPE=00 stored + LEN=2 + NLEN=0xFFFD + "Hi" 172// byte 0: 0x01 (BFINAL=1, BTYPE=00 + padding) 173// byte 1: 0x02 (LEN lo) 174// byte 2: 0x00 (LEN hi) 175// byte 3: 0xFD (NLEN lo) 176// byte 4: 0xFF (NLEN hi) 177// byte 5: 'H' = 0x48 178// byte 6: 'i' = 0x69 179// Adler-32 of "Hi": 180// a = 1 + 'H' = 73; a = 73 + 'i' = 73 + 105 = 178 181// b = 0 + 1 + 73 + 178 = ... compute via library 182// s1 = 178, s2 = 0 + 73 + 178 = 251 183// adler = (251 << 16) | 178 = 0x00FB00B2 184 185func main() -> nx_int { 186 // First verify Adler-32 helper produces 0x00FB00B2 for "Hi". 187 let hi: *u8 = (sys_mmap(2)) as *u8 188 hi[0] = 0x48 as u8 189 hi[1] = 0x69 as u8 190 let a_hi: nx_int = adler32(hi, 2) 191 if a_hi != NX_MAGIC_16449714 { return 1 } // 0x00FB00B2 192 193 // Build the zlib stream. 194 let stream: *u8 = (sys_mmap(11)) as *u8 195 stream[0] = 0x78 as u8 // CMF 196 stream[1] = 0x01 as u8 // FLG 197 stream[2] = 0x01 as u8 // BFINAL=1 BTYPE=00 198 stream[3] = 0x02 as u8 // LEN lo 199 stream[4] = 0x00 as u8 // LEN hi 200 stream[5] = 0xFD as u8 // NLEN lo 201 stream[6] = 0xFF as u8 // NLEN hi 202 stream[7] = 0x48 as u8 // 'H' 203 stream[8] = 0x69 as u8 // 'i' 204 // big-endian Adler-32 = 0x00 0xFB 0x00 0xB2 205 stream[9] = 0x00 as u8 // unused high byte 206 stream[10] = 0xFB as u8 // unused high byte 2 207 // need full 4 bytes -- expand: 208 let stream2: *u8 = (sys_mmap(13)) as *u8 209 var i: nx_int = 0 210 while i < 9 { 211 stream2[i] = stream[i] 212 i = i + 1 213 } 214 stream2[9] = 0x00 as u8 215 stream2[10] = 0xFB as u8 216 stream2[11] = 0x00 as u8 217 stream2[12] = 0xB2 as u8 218 219 let r: *NxZlibResult = nx_zlib_inflate(stream2, 13, 64) 220 if r == (0 as *NxZlibResult) { return 2 } 221 if r.error_code != NX_ZLIB_OK { return 3 } 222 if r.cm != 8 { return 4 } 223 if r.cinfo != 7 { return 5 } 224 if r.output_size != 2 { return 6 } 225 if r.output_data[0] != (0x48 as u8) { return 7 } 226 if r.output_data[1] != (0x69 as u8) { return 8 } 227 if r.adler_expected != r.adler_computed { return 9 } 228 229 // ---- Bad method (CM != 8) ---- 230 let bad_method: *u8 = (sys_mmap(13)) as *u8 231 var j: nx_int = 0 232 while j < 13 { 233 bad_method[j] = stream2[j] 234 j = j + 1 235 } 236 bad_method[0] = 0x79 as u8 // CM=9, bad 237 // recompute FCHECK so header passes 31-mod check? Doesn't 238 // matter -- bad-method check fires first. 239 let rbm: *NxZlibResult = nx_zlib_inflate(bad_method, 13, 64) 240 if rbm.error_code != NX_ZLIB_ERR_BAD_METHOD { return 20 } 241 242 // ---- Bad FCHECK (FLG that breaks % 31 check) ---- 243 let bad_fcheck: *u8 = (sys_mmap(13)) as *u8 244 var k: nx_int = 0 245 while k < 13 { 246 bad_fcheck[k] = stream2[k] 247 k = k + 1 248 } 249 bad_fcheck[1] = 0x02 as u8 // FLG=2 -> (NX_MAGIC_30720+2) % 31 = 1 != 0 250 let rbc: *NxZlibResult = nx_zlib_inflate(bad_fcheck, 13, 64) 251 if rbc.error_code != NX_ZLIB_ERR_BAD_CHECK { return 30 } 252 253 // ---- Preset dictionary (FDICT bit set) refused ---- 254 let preset: *u8 = (sys_mmap(13)) as *u8 255 var p: nx_int = 0 256 while p < 13 { 257 preset[p] = stream2[p] 258 p = p + 1 259 } 260 // FDICT = 1, FLEVEL = 0; need to recompute FCHECK so 31-mod passes. 261 // CMF*256 + FLG; with FDICT bit set, FLG = 32 + FCHECK. 262 // (30720 + 32 + FCHECK) % 31 == 0 -> (30752 + FCHECK) % 31 == 0 263 // 30752 % 31 = ? 30752 / 31 = 991.9.. -> 991*31 = 30721; remainder 31; mod 31 = 0. 264 // So FCHECK = 0 gives (30752) % 31 = 0. FLG = 32. 265 preset[1] = 0x20 as u8 266 let rpd: *NxZlibResult = nx_zlib_inflate(preset, 13, 64) 267 if rpd.error_code != NX_ZLIB_ERR_PRESET_DICT { return 40 } 268 269 // ---- Adler mismatch ---- 270 let bad_adler: *u8 = (sys_mmap(13)) as *u8 271 var m: nx_int = 0 272 while m < 13 { 273 bad_adler[m] = stream2[m] 274 m = m + 1 275 } 276 bad_adler[12] = 0x00 as u8 // corrupt trailer 277 let rba: *NxZlibResult = nx_zlib_inflate(bad_adler, 13, 64) 278 if rba.error_code != NX_ZLIB_ERR_ADLER_MISMATCH { return 50 } 279 280 // ---- Too-short input ---- 281 let too_short: *u8 = (sys_mmap(4)) as *u8 282 let rts: *NxZlibResult = nx_zlib_inflate(too_short, 4, 64) 283 if rts.error_code != NX_ZLIB_ERR_TOO_SHORT { return 60 } 284 285 return 0 286}