code wiki / (root) / nx_zlib_wrap.nx

nx_zlib_wrap.nx source

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