Mercurial > hg > dmlib
comparison src/dmzlib.c @ 958:985225a93aeb
Add error code parameter to dmError() and dmErrorVA().
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 27 Feb 2015 03:58:25 +0200 |
parents | 6b2f41844580 |
children | 1832ac20edb2 |
comparison
equal
deleted
inserted
replaced
957:b66653c9acb3 | 958:985225a93aeb |
---|---|
6 */ | 6 */ |
7 #include "dmzlib.h" | 7 #include "dmzlib.h" |
8 | 8 |
9 | 9 |
10 #define DM_ZLIB_TMPBUF_SIZE (16 * 1024) | 10 #define DM_ZLIB_TMPBUF_SIZE (16 * 1024) |
11 #define STBI_ASSERT(x) // dummy | 11 #define DMSTBI_ASSERT(x) // dummy |
12 | |
13 | |
14 static int stbi__err(const char *s, const char *p) | |
15 { | |
16 (void) s; | |
17 (void) p; | |
18 return 0; | |
19 } | |
20 | 12 |
21 | 13 |
22 // @TODO: should statically initialize these for optimal thread safety | 14 // @TODO: should statically initialize these for optimal thread safety |
23 static Uint8 stbi__zdefault_length[288], stbi__zdefault_distance[32]; | 15 static Uint8 stbi__zdefault_length[288], stbi__zdefault_distance[32]; |
24 | 16 |
55 } | 47 } |
56 | 48 |
57 | 49 |
58 static inline int stbi__bit_reverse_n(int v, int bits) | 50 static inline int stbi__bit_reverse_n(int v, int bits) |
59 { | 51 { |
60 STBI_ASSERT(bits <= 16); | 52 DMSTBI_ASSERT(bits <= 16); |
61 // to bit reverse n bits, reverse 16 and shift | 53 // to bit reverse n bits, reverse 16 and shift |
62 // e.g. 11 bits, bit reverse and shift away 5 | 54 // e.g. 11 bits, bit reverse and shift away 5 |
63 return stbi__bit_reverse_16(v) >> (16 - bits); | 55 return stbi__bit_reverse_16(v) >> (16 - bits); |
64 } | 56 } |
65 | 57 |
66 | 58 |
67 static int stbi__zbuild_huffman(DMZHuffmanContext * z, const Uint8 * sizelist, const int num) | 59 static int stbi__zbuild_huffman(DMZHuffmanContext * ctx, const Uint8 * sizelist, const int num) |
68 { | 60 { |
69 int i, k = 0; | 61 int i, k = 0; |
70 int code, next_code[16], sizes[17]; | 62 int code, next_code[16], sizes[17]; |
71 | 63 |
72 // DEFLATE spec for generating codes | 64 // DEFLATE spec for generating codes |
73 memset(sizes, 0, sizeof(sizes)); | 65 memset(sizes, 0, sizeof(sizes)); |
74 memset(z->fast, 0, sizeof(z->fast)); | 66 memset(ctx->fast, 0, sizeof(ctx->fast)); |
75 | 67 |
76 for (i = 0; i < num; i++) | 68 for (i = 0; i < num; i++) |
77 sizes[sizelist[i]]++; | 69 sizes[sizelist[i]]++; |
78 | 70 |
79 sizes[0] = 0; | 71 sizes[0] = 0; |
80 for (i = 1; i < 16; i++) | 72 for (i = 1; i < 16; i++) |
81 { | 73 { |
82 if (sizes[i] > (1 << i)) | 74 if (sizes[i] > (1 << i)) |
83 return stbi__err("fail!", "omg!"); | 75 { |
76 return dmError(DMERR_INTERNAL, | |
77 "Sizes assert failed while building Huffman codes.\n"); | |
78 } | |
84 } | 79 } |
85 | 80 |
86 code = 0; | 81 code = 0; |
87 for (i = 1; i < 16; i++) | 82 for (i = 1; i < 16; i++) |
88 { | 83 { |
89 next_code[i] = code; | 84 next_code[i] = code; |
90 z->firstCode[i] = (Uint16) code; | 85 ctx->firstCode[i] = (Uint16) code; |
91 z->firstSymbol[i] = (Uint16) k; | 86 ctx->firstSymbol[i] = (Uint16) k; |
92 code = (code + sizes[i]); | 87 code = (code + sizes[i]); |
93 | 88 |
94 if (sizes[i] && code - 1 >= (1 << i)) | 89 if (sizes[i] && code - 1 >= (1 << i)) |
95 return stbi__err("bad codelengths", "Corrupt JPEG"); | 90 { |
96 | 91 return dmError(DMERR_INVALID_DATA, |
97 z->maxCode[i] = code << (16 - i); // preshift for inner loop | 92 "Bad Huffman code lengths.\n"); |
93 } | |
94 | |
95 ctx->maxCode[i] = code << (16 - i); // preshift for inner loop | |
98 code <<= 1; | 96 code <<= 1; |
99 k += sizes[i]; | 97 k += sizes[i]; |
100 } | 98 } |
101 | 99 |
102 z->maxCode[16] = 0x10000; // sentinel | 100 ctx->maxCode[16] = 0x10000; // sentinel |
103 for (i = 0; i < num; i++) | 101 for (i = 0; i < num; i++) |
104 { | 102 { |
105 int s = sizelist[i]; | 103 int s = sizelist[i]; |
106 if (s) | 104 if (s) |
107 { | 105 { |
108 int c = next_code[s] - z->firstCode[s] + z->firstSymbol[s]; | 106 int c = next_code[s] - ctx->firstCode[s] + ctx->firstSymbol[s]; |
109 Uint16 fastv = (Uint16) ((s << 9) | i); | 107 Uint16 fastv = (Uint16) ((s << 9) | i); |
110 z->size[c] = (Uint8) s; | 108 ctx->size[c] = (Uint8) s; |
111 z->value[c] = (Uint16) i; | 109 ctx->value[c] = (Uint16) i; |
112 if (s <= STBI__ZFAST_BITS) | 110 if (s <= STBI__ZFAST_BITS) |
113 { | 111 { |
114 int k = stbi__bit_reverse_n(next_code[s], s); | 112 int k = stbi__bit_reverse_n(next_code[s], s); |
115 while (k < STBI__ZFAST_SIZE) | 113 while (k < STBI__ZFAST_SIZE) |
116 { | 114 { |
117 z->fast[k] = fastv; | 115 ctx->fast[k] = fastv; |
118 k += (1 << s); | 116 k += (1 << s); |
119 } | 117 } |
120 } | 118 } |
121 ++next_code[s]; | 119 ++next_code[s]; |
122 } | 120 } |
123 } | 121 } |
124 return 1; | 122 return 1; |
125 } | 123 } |
126 | 124 |
127 | 125 |
128 static inline Uint8 stbi__zget8(DMZLibContext * z) | 126 static inline Uint8 stbi__zget8(DMZLibContext * ctx) |
129 { | 127 { |
130 if (z->zbuffer >= z->zbuffer_end) | 128 if (ctx->zbuffer >= ctx->zbufferEnd) |
131 return 0; | 129 return 0; |
132 | 130 |
133 return *z->zbuffer++; | 131 return *ctx->zbuffer++; |
134 } | 132 } |
135 | 133 |
136 | 134 |
137 static void stbi__fill_bits(DMZLibContext * z) | 135 static void stbi__fill_bits(DMZLibContext * ctx) |
138 { | 136 { |
139 do | 137 do |
140 { | 138 { |
141 STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); | 139 DMSTBI_ASSERT(ctx->codeBuffer < (1U << ctx->numBits)); |
142 z->code_buffer |= stbi__zget8(z) << z->num_bits; | 140 ctx->codeBuffer |= stbi__zget8(ctx) << ctx->numBits; |
143 z->num_bits += 8; | 141 ctx->numBits += 8; |
144 } | 142 } |
145 while (z->num_bits <= 24); | 143 while (ctx->numBits <= 24); |
146 } | 144 } |
147 | 145 |
148 | 146 |
149 static inline unsigned int stbi__zreceive(DMZLibContext * z, int n) | 147 static inline unsigned int stbi__zreceive(DMZLibContext * ctx, int n) |
150 { | 148 { |
151 unsigned int k; | 149 unsigned int val; |
152 if (z->num_bits < n) | 150 |
153 stbi__fill_bits(z); | 151 if (ctx->numBits < n) |
154 k = z->code_buffer & ((1 << n) - 1); | 152 stbi__fill_bits(ctx); |
155 z->code_buffer >>= n; | 153 |
156 z->num_bits -= n; | 154 val = ctx->codeBuffer & ((1 << n) - 1); |
157 return k; | 155 ctx->codeBuffer >>= n; |
158 } | 156 ctx->numBits -= n; |
159 | 157 |
160 | 158 return val; |
161 static int stbi__zhuffman_decode_slowpath(DMZLibContext * a, DMZHuffmanContext * z) | 159 } |
160 | |
161 | |
162 static int stbi__zhuffman_decode_slowpath(DMZLibContext * ctx, DMZHuffmanContext * huff, int *val) | |
162 { | 163 { |
163 int b, s, k; | 164 int b, s, k; |
164 | 165 |
165 // not resolved by fast table, so compute it the slow way | 166 // not resolved by fast table, so compute it the slow way |
166 // use jpeg approach, which requires MSbits at top | 167 // use jpeg approach, which requires MSbits at top |
167 k = stbi__bit_reverse_16(a->code_buffer); | 168 k = stbi__bit_reverse_16(ctx->codeBuffer); |
168 for (s = STBI__ZFAST_BITS + 1; ; s++) | 169 for (s = STBI__ZFAST_BITS + 1; ; s++) |
169 { | 170 { |
170 if (k < z->maxCode[s]) break; | 171 if (k < huff->maxCode[s]) |
172 break; | |
171 } | 173 } |
172 | 174 |
173 if (s == 16) | 175 if (s == 16) |
174 return -1; // invalid code! | 176 { |
177 return dmError(DMERR_DATA_ERROR, | |
178 "Bad Huffman code.\n"); | |
179 } | |
175 | 180 |
176 // code size is s, so: | 181 // code size is s, so: |
177 b = (k >> (16 - s)) - z->firstCode[s] + z->firstSymbol[s]; | 182 b = (k >> (16 - s)) - huff->firstCode[s] + huff->firstSymbol[s]; |
178 STBI_ASSERT(z->size[b] == s); | 183 DMSTBI_ASSERT(huff->size[b] == s); |
179 a->code_buffer >>= s; | 184 |
180 a->num_bits -= s; | 185 ctx->codeBuffer >>= s; |
181 return z->value[b]; | 186 ctx->numBits -= s; |
182 } | 187 *val = huff->value[b]; |
183 | 188 |
184 | 189 return DMERR_OK; |
185 static inline int stbi__zhuffman_decode(DMZLibContext * a, DMZHuffmanContext * z) | 190 } |
191 | |
192 | |
193 static inline int stbi__zhuffman_decode(DMZLibContext * ctx, DMZHuffmanContext * huff, int *val) | |
186 { | 194 { |
187 int b; | 195 int b; |
188 if (a->num_bits < 16) | 196 if (ctx->numBits < 16) |
189 stbi__fill_bits(a); | 197 stbi__fill_bits(ctx); |
190 | 198 |
191 b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; | 199 b = huff->fast[ctx->codeBuffer & STBI__ZFAST_MASK]; |
192 if (b) | 200 if (b) |
193 { | 201 { |
194 int s = b >> 9; | 202 int s = b >> 9; |
195 a->code_buffer >>= s; | 203 ctx->codeBuffer >>= s; |
196 a->num_bits -= s; | 204 ctx->numBits -= s; |
197 return b & 511; | 205 *val = b & 511; |
198 } | 206 return DMERR_OK; |
199 return stbi__zhuffman_decode_slowpath(a, z); | 207 } |
200 } | 208 |
201 | 209 return stbi__zhuffman_decode_slowpath(ctx, huff, val); |
202 | 210 } |
203 static int stbi__zexpand(DMZLibContext * z, char *zout, int n) // need to make room for n bytes | 211 |
204 { | 212 |
205 char *q; | 213 static int stbi__zexpand(DMZLibContext * ctx, Uint8 *zout, size_t n) |
206 int cur, limit; | 214 { |
207 z->zout = zout; | 215 Uint8 *newBuf; |
208 | 216 size_t cur, limit; |
209 if (!z->z_expandable) | 217 |
210 return stbi__err("output buffer limit", "Corrupt PNG"); | 218 ctx->zout = zout; |
211 | 219 |
212 cur = (int) (z->zout - z->zout_start); | 220 if (!ctx->expandable) |
213 limit = (int) (z->zout_end - z->zout_start); | 221 { |
222 return dmError(DMERR_BOUNDS, | |
223 "Output buffer limit hit, and is not expandable.\n"); | |
224 } | |
225 | |
226 cur = ctx->zout - ctx->zoutStart; | |
227 limit = ctx->zoutEnd - ctx->zoutStart; | |
214 | 228 |
215 while (cur + n > limit) | 229 while (cur + n > limit) |
216 limit *= 2; | 230 limit *= 2; |
217 | 231 |
218 if ((q = (char *) dmRealloc(z->zout_start, limit)) == NULL) | 232 if ((newBuf = (Uint8 *) dmRealloc(ctx->zoutStart, limit)) == NULL) |
219 return stbi__err("outofmem", "Out of memory"); | 233 { |
220 | 234 return dmError(DMERR_MALLOC, |
221 z->zout_start = q; | 235 "Could not reallocate buffer.\n"); |
222 z->zout = q + cur; | 236 } |
223 z->zout_end = q + limit; | 237 |
224 return 1; | 238 ctx->zoutStart = newBuf; |
239 ctx->zout = newBuf + cur; | |
240 ctx->zoutEnd = newBuf + limit; | |
241 | |
242 return DMERR_OK; | |
225 } | 243 } |
226 | 244 |
227 | 245 |
228 static const int stbi__zlength_base[31] = | 246 static const int stbi__zlength_base[31] = |
229 { | 247 { |
252 }; | 270 }; |
253 | 271 |
254 | 272 |
255 static int stbi__parse_huffman_block(DMZLibContext * a) | 273 static int stbi__parse_huffman_block(DMZLibContext * a) |
256 { | 274 { |
257 char *zout = a->zout; | 275 Uint8 *zout = a->zout; |
258 for (;;) | 276 for (;;) |
259 { | 277 { |
260 int z = stbi__zhuffman_decode(a, &a->z_length); | 278 int z, ret; |
279 if ((ret = stbi__zhuffman_decode(a, &a->zlength, &z)) != DMERR_OK) | |
280 return ret; | |
281 | |
261 if (z < 256) | 282 if (z < 256) |
262 { | 283 { |
263 if (z < 0) | 284 if (zout >= a->zoutEnd) |
264 return stbi__err("bad huffman code", "Corrupt PNG"); // error in huffman codes | |
265 | |
266 if (zout >= a->zout_end) | |
267 { | 285 { |
268 if (!stbi__zexpand(a, zout, 1)) | 286 if ((ret = stbi__zexpand(a, zout, 1)) != DMERR_OK) |
269 return 0; | 287 return ret; |
288 | |
270 zout = a->zout; | 289 zout = a->zout; |
271 } | 290 } |
272 *zout++ = (char) z; | 291 *zout++ = (Uint8) z; |
273 } | 292 } |
274 else | 293 else |
275 { | 294 { |
276 Uint8 *p; | 295 Uint8 *p; |
277 int len, dist; | 296 int len, dist; |
278 if (z == 256) | 297 if (z == 256) |
279 { | 298 { |
280 a->zout = zout; | 299 a->zout = zout; |
281 return 1; | 300 return DMERR_OK; |
282 } | 301 } |
283 z -= 257; | 302 z -= 257; |
284 | 303 |
285 len = stbi__zlength_base[z]; | 304 len = stbi__zlength_base[z]; |
286 if (stbi__zlength_extra[z]) | 305 if (stbi__zlength_extra[z]) |
287 len += stbi__zreceive(a, stbi__zlength_extra[z]); | 306 len += stbi__zreceive(a, stbi__zlength_extra[z]); |
288 | 307 |
289 z = stbi__zhuffman_decode(a, &a->z_distance); | 308 if ((ret = stbi__zhuffman_decode(a, &a->zdistance, &z)) != DMERR_OK) |
290 if (z < 0) | 309 return ret; |
291 return stbi__err("bad huffman code", "Corrupt PNG"); | |
292 | 310 |
293 dist = stbi__zdist_base[z]; | 311 dist = stbi__zdist_base[z]; |
294 if (stbi__zdist_extra[z]) | 312 if (stbi__zdist_extra[z]) |
295 dist += stbi__zreceive(a, stbi__zdist_extra[z]); | 313 dist += stbi__zreceive(a, stbi__zdist_extra[z]); |
296 | 314 |
297 if (zout - a->zout_start < dist) | 315 if (zout - a->zoutStart < dist) |
298 return stbi__err("bad dist", "Corrupt PNG"); | 316 { |
299 | 317 return dmError(DMERR_DATA_ERROR, |
300 if (zout + len > a->zout_end) | 318 "Bad Huffman block distance.\n"); |
319 } | |
320 | |
321 if (zout + len > a->zoutEnd) | |
301 { | 322 { |
302 if (!stbi__zexpand(a, zout, len)) | 323 if (!stbi__zexpand(a, zout, len)) |
303 return 0; | 324 return 0; |
304 zout = a->zout; | 325 zout = a->zout; |
305 } | 326 } |
329 static int stbi__compute_huffman_codes(DMZLibContext * a) | 350 static int stbi__compute_huffman_codes(DMZLibContext * a) |
330 { | 351 { |
331 DMZHuffmanContext z_codelength; | 352 DMZHuffmanContext z_codelength; |
332 Uint8 lencodes[286 + 32 + 137]; //padding for maximum single op | 353 Uint8 lencodes[286 + 32 + 137]; //padding for maximum single op |
333 Uint8 codelength_sizes[19]; | 354 Uint8 codelength_sizes[19]; |
334 int i, n; | 355 int i, n, ret; |
335 | 356 |
336 int hlit = stbi__zreceive(a, 5) + 257; | 357 int hlit = stbi__zreceive(a, 5) + 257; |
337 int hdist = stbi__zreceive(a, 5) + 1; | 358 int hdist = stbi__zreceive(a, 5) + 1; |
338 int hclen = stbi__zreceive(a, 4) + 4; | 359 int hclen = stbi__zreceive(a, 4) + 4; |
339 | 360 |
340 memset(codelength_sizes, 0, sizeof(codelength_sizes)); | 361 memset(codelength_sizes, 0, sizeof(codelength_sizes)); |
341 | 362 |
342 for (i = 0; i < hclen; i++) | 363 for (i = 0; i < hclen; i++) |
343 { | 364 { |
344 int s = stbi__zreceive(a, 3); | 365 int s = stbi__zreceive(a, 3); |
345 codelength_sizes[length_dezigzag[i]] = (Uint8) s; | 366 codelength_sizes[length_dezigzag[i]] = (Uint8) s; |
346 } | 367 } |
347 if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) | 368 |
348 return 0; | 369 if ((ret = stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) != DMERR_OK) |
349 | 370 return ret; |
350 | 371 |
351 n = 0; | 372 n = 0; |
352 while (n < hlit + hdist) | 373 while (n < hlit + hdist) |
353 { | 374 { |
354 int c = stbi__zhuffman_decode(a, &z_codelength); | 375 int c; |
355 STBI_ASSERT(c >= 0 && c < 19); | 376 if ((ret = stbi__zhuffman_decode(a, &z_codelength, &c)) != DMERR_OK) |
377 return ret; | |
378 | |
379 DMSTBI_ASSERT(c >= 0 && c < 19); | |
356 | 380 |
357 if (c < 16) | 381 if (c < 16) |
358 lencodes[n++] = (Uint8) c; | 382 lencodes[n++] = (Uint8) c; |
359 else | 383 else |
360 if (c == 16) | 384 if (c == 16) |
377 n += c; | 401 n += c; |
378 } | 402 } |
379 } | 403 } |
380 | 404 |
381 if (n != hlit + hdist) | 405 if (n != hlit + hdist) |
382 return stbi__err("bad codelengths", "Corrupt PNG"); | 406 { |
383 | 407 return dmError(DMERR_DATA_ERROR, |
384 if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) | 408 "Bad huffman codelengths.\n"); |
385 return 0; | 409 } |
386 | 410 |
387 if (!stbi__zbuild_huffman(&a->z_distance, lencodes + hlit, hdist)) | 411 if ((ret = stbi__zbuild_huffman(&a->zlength, lencodes, hlit)) != DMERR_OK) |
388 return 0; | 412 return ret; |
389 return 1; | 413 |
414 if ((ret = stbi__zbuild_huffman(&a->zdistance, lencodes + hlit, hdist)) != DMERR_OK) | |
415 return ret; | |
416 | |
417 return DMERR_OK; | |
390 } | 418 } |
391 | 419 |
392 | 420 |
393 static int stbi__parse_uncompressed_block(DMZLibContext * a) | 421 static int stbi__parse_uncompressed_block(DMZLibContext * a) |
394 { | 422 { |
395 Uint8 header[4]; | 423 Uint8 header[4]; |
396 int len, nlen, k; | 424 int len, nlen, k; |
397 | 425 |
398 if (a->num_bits & 7) | 426 if (a->numBits & 7) |
399 stbi__zreceive(a, a->num_bits & 7); // discard | 427 stbi__zreceive(a, a->numBits & 7); // discard |
400 | 428 |
401 // drain the bit-packed data into header | 429 // drain the bit-packed data into header |
402 k = 0; | 430 k = 0; |
403 while (a->num_bits > 0) | 431 while (a->numBits > 0) |
404 { | 432 { |
405 header[k++] = (Uint8) (a->code_buffer & 255); // suppress MSVC run-time check | 433 header[k++] = (Uint8) (a->codeBuffer & 255); // suppress MSVC run-time check |
406 a->code_buffer >>= 8; | 434 a->codeBuffer >>= 8; |
407 a->num_bits -= 8; | 435 a->numBits -= 8; |
408 } | 436 } |
409 STBI_ASSERT(a->num_bits == 0); | 437 DMSTBI_ASSERT(a->numBits == 0); |
410 | 438 |
411 // now fill header the normal way | 439 // now fill header the normal way |
412 while (k < 4) | 440 while (k < 4) |
413 header[k++] = stbi__zget8(a); | 441 header[k++] = stbi__zget8(a); |
414 | 442 |
415 len = header[1] * 256 + header[0]; | 443 len = (header[1] << 8) | header[0]; |
416 nlen = header[3] * 256 + header[2]; | 444 nlen = (header[3] << 8) | header[2]; |
417 | 445 |
418 if (nlen != (len ^ 0xffff)) | 446 if (nlen != (len ^ 0xffff)) |
419 return stbi__err("zlib corrupt", "Corrupt PNG"); | 447 { |
420 | 448 return dmError(DMERR_DATA_ERROR, |
421 if (a->zbuffer + len > a->zbuffer_end) | 449 "Compressed data corrupt.\n"); |
422 return stbi__err("read past buffer", "Corrupt PNG"); | 450 } |
423 | 451 |
424 if (a->zout + len > a->zout_end && !stbi__zexpand(a, a->zout, len)) | 452 if (a->zbuffer + len > a->zbufferEnd) |
425 return 0; | 453 { |
454 return dmError(DMERR_BOUNDS, | |
455 "Read past buffer, probably corrupt compressed data.\n"); | |
456 } | |
457 | |
458 if (a->zout + len > a->zoutEnd && !stbi__zexpand(a, a->zout, len)) | |
459 { | |
460 return dmError(DMERR_DATA_ERROR, | |
461 "XXXX TODO"); | |
462 } | |
426 | 463 |
427 memcpy(a->zout, a->zbuffer, len); | 464 memcpy(a->zout, a->zbuffer, len); |
428 a->zbuffer += len; | 465 a->zbuffer += len; |
429 a->zout += len; | 466 a->zout += len; |
430 return 1; | 467 |
431 } | 468 return DMERR_OK; |
432 | 469 } |
433 | 470 |
434 static int stbi__parse_zlib_header(DMZLibContext * a) | 471 |
435 { | 472 int dmZLibParseHeader(DMZLibContext * ctx, BOOL checkPNG) |
436 int cmf = stbi__zget8(a); | 473 { |
474 int cmf = stbi__zget8(ctx); | |
475 int flags = stbi__zget8(ctx); | |
437 int cm = cmf & 15; | 476 int cm = cmf & 15; |
438 int flg = stbi__zget8(a); | |
439 // int cinfo = cmf >> 4; | 477 // int cinfo = cmf >> 4; |
440 | 478 |
441 if ((cmf * 256 + flg) % 31 != 0) | 479 if ((cmf * 256 + flags) % 31 != 0) |
442 return stbi__err("bad zlib header", "Corrupt PNG"); // zlib spec | 480 { |
443 | 481 return dmError(DMERR_INVALID_DATA, |
444 if (flg & 32) | 482 "Bad zlib header."); |
445 return stbi__err("no preset dict", "Corrupt PNG"); // preset dictionary not allowed in png | 483 } |
446 | 484 |
447 if (cm != 8) | 485 if (checkPNG && (flags & 32)) |
448 return stbi__err("bad compression", "Corrupt PNG"); // DEFLATE required for png | 486 { |
487 // preset dictionary not allowed in png | |
488 return dmError(DMERR_NOT_SUPPORTED, | |
489 "Preset dictionary not allowed in PNG.\n"); | |
490 } | |
491 | |
492 if (checkPNG && cm != 8) | |
493 { | |
494 return dmError(DMERR_INVALID_DATA, | |
495 "Bad or unsupported compression type.\n"); | |
496 } | |
449 | 497 |
450 // window = 1 << (8 + cinfo)... but who cares, we fully buffer output | 498 // window = 1 << (8 + cinfo)... but who cares, we fully buffer output |
451 return 1; | 499 return DMERR_OK; |
452 } | 500 } |
453 | 501 |
454 | 502 |
455 static int stbi__parse_zlib(DMZLibContext * a, BOOL parse_header) | 503 int dmZLibDecode(DMZLibContext * ctx) |
456 { | 504 { |
457 int final, type; | 505 int final, type, ret; |
458 | 506 |
459 if (parse_header && !stbi__parse_zlib_header(a)) | 507 ctx->numBits = 0; |
460 return 0; | 508 ctx->codeBuffer = 0; |
461 | |
462 a->num_bits = 0; | |
463 a->code_buffer = 0; | |
464 do | 509 do |
465 { | 510 { |
466 final = stbi__zreceive(a, 1); | 511 final = stbi__zreceive(ctx, 1); |
467 type = stbi__zreceive(a, 2); | 512 type = stbi__zreceive(ctx, 2); |
468 if (type == 0) | 513 if (type == 0) |
469 { | 514 { |
470 if (!stbi__parse_uncompressed_block(a)) | 515 if ((ret = stbi__parse_uncompressed_block(ctx)) != DMERR_OK) |
471 return 0; | 516 return ret; |
472 } | 517 } |
473 else | 518 else |
474 if (type == 3) | 519 if (type == 3) |
475 return 0; | 520 return 0; |
476 else | 521 else |
477 { | 522 { |
478 if (type == 1) | 523 if (type == 1) |
479 { | 524 { |
480 // use fixed code lengths | 525 // use fixed code lengths |
481 if (!stbi__zbuild_huffman(&a->z_length, stbi__zdefault_length, 288)) | 526 if ((ret = stbi__zbuild_huffman(&ctx->zlength, stbi__zdefault_length, 288)) != DMERR_OK) |
482 return 0; | 527 return ret; |
483 | 528 |
484 if (!stbi__zbuild_huffman | 529 if ((ret = stbi__zbuild_huffman(&ctx->zdistance, stbi__zdefault_distance, 32)) != DMERR_OK) |
485 (&a->z_distance, stbi__zdefault_distance, 32)) | 530 return ret; |
486 return 0; | |
487 } | 531 } |
488 else | 532 else |
489 { | 533 if ((ret = stbi__compute_huffman_codes(ctx)) != DMERR_OK) |
490 if (!stbi__compute_huffman_codes(a)) | 534 return ret; |
491 return 0; | 535 |
492 } | 536 if ((ret = stbi__parse_huffman_block(ctx)) != DMERR_OK) |
493 if (!stbi__parse_huffman_block(a)) | 537 return ret; |
494 return 0; | |
495 } | 538 } |
496 } | 539 } |
497 while (!final); | 540 while (!final); |
498 return 1; | 541 |
499 } | 542 return DMERR_OK; |
500 | 543 } |
501 | 544 |
502 static int stbi__do_zlib(DMZLibContext * a, char *obuf, int olen, int exp, | 545 |
503 BOOL parse_header) | 546 Uint8 *stbi_zlib_decode_malloc_guesssize_headerflag( |
504 { | 547 const Uint8 *buffer, const size_t len, |
505 a->zout_start = obuf; | 548 const size_t initialSize, size_t *outLen, |
506 a->zout = obuf; | 549 BOOL parseHeader) |
507 a->zout_end = obuf + olen; | 550 { |
508 a->z_expandable = exp; | 551 DMZLibContext ctx; |
509 | 552 Uint8 *outBuf; |
510 return stbi__parse_zlib(a, parse_header); | 553 int ret; |
511 } | 554 |
512 | 555 if ((outBuf = dmMalloc(initialSize)) == NULL) |
513 | 556 return NULL; |
514 char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) | 557 |
515 { | 558 ctx.zbuffer = (Uint8 *) buffer; |
516 DMZLibContext a; | 559 ctx.zbufferEnd = (Uint8 *) buffer + len; |
517 char *p = (char *) dmMalloc(initial_size); | 560 ctx.zout = outBuf; |
561 ctx.zoutStart = outBuf; | |
562 ctx.zoutEnd = outBuf + initialSize; | |
563 ctx.expandable = TRUE; | |
564 | |
565 if (parseHeader && (ret = dmZLibParseHeader(&ctx, TRUE)) != DMERR_OK) | |
566 { | |
567 return dmError(ret, | |
568 "Failed to parse zlib header data.\n"); | |
569 } | |
570 | |
571 if ((ret = dmZLibDecode(&ctx)) != DMERR_OK) | |
572 { | |
573 if (outLen) | |
574 *outLen = ctx.zout - ctx.zoutStart; | |
575 | |
576 return ctx.zoutStart; | |
577 } | |
578 else | |
579 { | |
580 dmFree(ctx.zoutStart); | |
581 return NULL; | |
582 } | |
583 } | |
584 | |
585 | |
586 #if 0 | |
587 | |
588 Uint8 *stbi_zlib_decode_malloc(Uint8 const *buffer, int len, int *outlen) | |
589 { | |
590 return stbi_zlib_decode_malloc_guesssize(buffer, len, DM_ZLIB_TMPBUF_SIZE, outlen); | |
591 } | |
592 | |
593 | |
594 int stbi_zlib_decode_buffer(Uint8 *obuffer, size_t olen, Uint8 const *ibuffer, size_t ilen, size_t *res) | |
595 { | |
596 DMZLibContext ctx; | |
597 int ret; | |
598 | |
599 ctx.zbuffer = (Uint8 *) ibuffer; | |
600 ctx.zbufferEnd = (Uint8 *) ibuffer + ilen; | |
601 | |
602 if ((ret = stbi__do_zlib(&a, obuffer, olen, 0, 1)) != DMERR_OK) | |
603 { | |
604 *res = a.zout - a.zoutStart; | |
605 return DMERR_OK; | |
606 } | |
607 else | |
608 return ret; | |
609 } | |
610 | |
611 | |
612 Uint8 *stbi_zlib_decode_noheader_malloc(Uint8 const *buffer, int len, size_t *outlen) | |
613 { | |
614 DMZLibContext ctx; | |
615 Uint8 *p = (Uint8 *) dmMalloc(DM_ZLIB_TMPBUF_SIZE); | |
518 if (p == NULL) | 616 if (p == NULL) |
519 return NULL; | 617 return NULL; |
520 a.zbuffer = (Uint8 *) buffer; | 618 |
521 a.zbuffer_end = (Uint8 *) buffer + len; | 619 ctx.zbuffer = (Uint8 *) buffer; |
522 if (stbi__do_zlib(&a, p, initial_size, 1, 1)) | 620 ctx.zbufferEnd = (Uint8 *) buffer + len; |
523 { | 621 |
524 if (outlen) | 622 if (stbi__do_zlib(&ctx, p, DM_ZLIB_TMPBUF_SIZE, 1, 0)) |
525 *outlen = (int) (a.zout - a.zout_start); | 623 { |
526 return a.zout_start; | 624 if (outlen != NULL) |
625 *outlen = (int) (ctx.zout - a.zoutStart); | |
626 return a.zoutStart; | |
527 } | 627 } |
528 else | 628 else |
529 { | 629 { |
530 dmFree(a.zout_start); | 630 dmFree(a.zoutStart); |
531 return NULL; | 631 return NULL; |
532 } | 632 } |
533 } | 633 } |
534 | 634 |
535 | 635 |
536 char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) | 636 int stbi_zlib_decode_noheader_buffer(Uint8 *obuffer, int olen, const Uint8 *ibuffer, int ilen) |
537 { | |
538 return stbi_zlib_decode_malloc_guesssize(buffer, len, DM_ZLIB_TMPBUF_SIZE, outlen); | |
539 } | |
540 | |
541 | |
542 char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, | |
543 int len, int initial_size, int *outlen, BOOL parse_header) | |
544 { | 637 { |
545 DMZLibContext a; | 638 DMZLibContext a; |
546 char *p = (char *) dmMalloc(initial_size); | 639 |
547 if (p == NULL) | |
548 return NULL; | |
549 | |
550 a.zbuffer = (Uint8 *) buffer; | |
551 a.zbuffer_end = (Uint8 *) buffer + len; | |
552 if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) | |
553 { | |
554 if (outlen) | |
555 *outlen = (int) (a.zout - a.zout_start); | |
556 return a.zout_start; | |
557 } | |
558 else | |
559 { | |
560 dmFree(a.zout_start); | |
561 return NULL; | |
562 } | |
563 } | |
564 | |
565 | |
566 int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) | |
567 { | |
568 DMZLibContext a; | |
569 a.zbuffer = (Uint8 *) ibuffer; | 640 a.zbuffer = (Uint8 *) ibuffer; |
570 a.zbuffer_end = (Uint8 *) ibuffer + ilen; | 641 a.zbufferEnd = (Uint8 *) ibuffer + ilen; |
571 if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) | 642 |
572 return (int) (a.zout - a.zout_start); | 643 if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) |
644 return (int) (a.zout - a.zoutStart); | |
573 else | 645 else |
574 return -1; | 646 return -1; |
575 } | 647 } |
576 | 648 |
577 | 649 #endif |
578 char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) | |
579 { | |
580 DMZLibContext a; | |
581 char *p = (char *) dmMalloc(DM_ZLIB_TMPBUF_SIZE); | |
582 if (p == NULL) | |
583 return NULL; | |
584 | |
585 a.zbuffer = (Uint8 *) buffer; | |
586 a.zbuffer_end = (Uint8 *) buffer + len; | |
587 | |
588 if (stbi__do_zlib(&a, p, DM_ZLIB_TMPBUF_SIZE, 1, 0)) | |
589 { | |
590 if (outlen != NULL) | |
591 *outlen = (int) (a.zout - a.zout_start); | |
592 return a.zout_start; | |
593 } | |
594 else | |
595 { | |
596 dmFree(a.zout_start); | |
597 return NULL; | |
598 } | |
599 } | |
600 | |
601 | |
602 int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) | |
603 { | |
604 DMZLibContext a; | |
605 | |
606 a.zbuffer = (Uint8 *) ibuffer; | |
607 a.zbuffer_end = (Uint8 *) ibuffer + ilen; | |
608 | |
609 if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) | |
610 return (int) (a.zout - a.zout_start); | |
611 else | |
612 return -1; | |
613 } |