Bug Summary

File:Deflate.c
Warning:line 636, column 17
The right operand of '+' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple amd64-unknown-openbsd6.8 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name Deflate.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mthread-model posix -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/local/lib/clang/10.0.1 -I /usr/X11R6/include -I /usr/local/include -fdebug-compilation-dir /home/ben/Projects/ClassiCube/src -ferror-limit 19 -fmessage-length 0 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -fobjc-runtime=gnustep -fdiagnostics-show-option -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/ClassiCube/src/scan/2021-01-09-173753-31878-1 -x c Deflate.c
1#include "Deflate.h"
2#include "String.h"
3#include "Logger.h"
4#include "Funcs.h"
5#include "Platform.h"
6#include "Stream.h"
7#include "Errors.h"
8#include "Utils.h"
9
10#define Header_ReadU8(value)if ((res = s->ReadU8(s, &value))) return res; if ((res = s->ReadU8(s, &value))) return res;
11/*########################################################################################################################*
12*-------------------------------------------------------GZip header-------------------------------------------------------*
13*#########################################################################################################################*/
14enum GzipState {
15 GZIP_STATE_HEADER1, GZIP_STATE_HEADER2, GZIP_STATE_COMPRESSIONMETHOD, GZIP_STATE_FLAGS,
16 GZIP_STATE_LASTMODIFIED, GZIP_STATE_COMPRESSIONFLAGS, GZIP_STATE_OPERATINGSYSTEM,
17 GZIP_STATE_HEADERCHECKSUM, GZIP_STATE_FILENAME, GZIP_STATE_COMMENT, GZIP_STATE_DONE
18};
19
20void GZipHeader_Init(struct GZipHeader* header) {
21 header->state = GZIP_STATE_HEADER1;
22 header->done = false0;
23 header->flags = 0;
24 header->partsRead = 0;
25}
26
27cc_result GZipHeader_Read(struct Stream* s, struct GZipHeader* header) {
28 cc_uint8 tmp;
29 cc_result res;
30 switch (header->state) {
31
32 case GZIP_STATE_HEADER1:
33 Header_ReadU8(tmp)if ((res = s->ReadU8(s, &tmp))) return res;;
34 if (tmp != 0x1F) return GZIP_ERR_HEADER1;
35 header->state++;
36
37 case GZIP_STATE_HEADER2:
38 Header_ReadU8(tmp)if ((res = s->ReadU8(s, &tmp))) return res;;
39 if (tmp != 0x8B) return GZIP_ERR_HEADER2;
40 header->state++;
41
42 case GZIP_STATE_COMPRESSIONMETHOD:
43 Header_ReadU8(tmp)if ((res = s->ReadU8(s, &tmp))) return res;;
44 if (tmp != 0x08) return GZIP_ERR_METHOD;
45 header->state++;
46
47 case GZIP_STATE_FLAGS:
48 Header_ReadU8(tmp)if ((res = s->ReadU8(s, &tmp))) return res;;
49 header->flags = tmp;
50 if (header->flags & 0x04) return GZIP_ERR_FLAGS;
51 header->state++;
52
53 case GZIP_STATE_LASTMODIFIED:
54 for (; header->partsRead < 4; header->partsRead++) {
55 Header_ReadU8(tmp)if ((res = s->ReadU8(s, &tmp))) return res;;
56 }
57 header->state++;
58 header->partsRead = 0;
59
60 case GZIP_STATE_COMPRESSIONFLAGS:
61 Header_ReadU8(tmp)if ((res = s->ReadU8(s, &tmp))) return res;;
62 header->state++;
63
64 case GZIP_STATE_OPERATINGSYSTEM:
65 Header_ReadU8(tmp)if ((res = s->ReadU8(s, &tmp))) return res;;
66 header->state++;
67
68 case GZIP_STATE_FILENAME:
69 if (header->flags & 0x08) {
70 for (; ;) {
71 Header_ReadU8(tmp)if ((res = s->ReadU8(s, &tmp))) return res;;
72 if (tmp == '\0') break;
73 }
74 }
75 header->state++;
76
77 case GZIP_STATE_COMMENT:
78 if (header->flags & 0x10) {
79 for (; ;) {
80 Header_ReadU8(tmp)if ((res = s->ReadU8(s, &tmp))) return res;;
81 if (tmp == '\0') break;
82 }
83 }
84 header->state++;
85
86 case GZIP_STATE_HEADERCHECKSUM:
87 if (header->flags & 0x02) {
88 for (; header->partsRead < 2; header->partsRead++) {
89 Header_ReadU8(tmp)if ((res = s->ReadU8(s, &tmp))) return res;;
90 }
91 }
92 header->state++;
93 header->partsRead = 0;
94 header->done = true1;
95 }
96 return 0;
97}
98
99
100/*########################################################################################################################*
101*-------------------------------------------------------ZLib header-------------------------------------------------------*
102*#########################################################################################################################*/
103enum ZlibState { ZLIB_STATE_COMPRESSIONMETHOD, ZLIB_STATE_FLAGS, ZLIB_STATE_DONE };
104
105void ZLibHeader_Init(struct ZLibHeader* header) {
106 header->state = ZLIB_STATE_COMPRESSIONMETHOD;
107 header->done = false0;
108}
109
110cc_result ZLibHeader_Read(struct Stream* s, struct ZLibHeader* header) {
111 cc_uint8 tmp;
112 cc_result res;
113 switch (header->state) {
114
115 case ZLIB_STATE_COMPRESSIONMETHOD:
116 Header_ReadU8(tmp)if ((res = s->ReadU8(s, &tmp))) return res;;
117 if ((tmp & 0x0F) != 0x08) return ZLIB_ERR_METHOD;
118 /* Upper 4 bits are window size (ignored) */
119 header->state++;
120
121 case ZLIB_STATE_FLAGS:
122 Header_ReadU8(tmp)if ((res = s->ReadU8(s, &tmp))) return res;;
123 if (tmp & 0x20) return ZLIB_ERR_FLAGS;
124 header->state++;
125 header->done = true1;
126 }
127 return 0;
128}
129
130
131/*########################################################################################################################*
132*--------------------------------------------------Inflate (decompress)---------------------------------------------------*
133*#########################################################################################################################*/
134enum INFLATE_STATE_ {
135 INFLATE_STATE_HEADER, INFLATE_STATE_UNCOMPRESSED_HEADER,
136 INFLATE_STATE_UNCOMPRESSED_DATA, INFLATE_STATE_DYNAMIC_HEADER,
137 INFLATE_STATE_DYNAMIC_CODELENS, INFLATE_STATE_DYNAMIC_LITSDISTS,
138 INFLATE_STATE_DYNAMIC_LITSDISTSREPEAT, INFLATE_STATE_COMPRESSED_LIT,
139 INFLATE_STATE_COMPRESSED_LITEXTRA, INFLATE_STATE_COMPRESSED_DIST,
140 INFLATE_STATE_COMPRESSED_DISTEXTRA, INFLATE_STATE_COMPRESSED_DATA,
141 INFLATE_STATE_FASTCOMPRESSED, INFLATE_STATE_DONE
142};
143
144/* Insert next byte into the bit buffer */
145#define Inflate_GetByte(state)state->AvailIn--; state->Bits |= (cc_uint32)(*state->
NextIn++) << state->NumBits; state->NumBits += 8;
state->AvailIn--; state->Bits |= (cc_uint32)(*state->NextIn++) << state->NumBits; state->NumBits += 8;
146/* Retrieves bits from the bit buffer */
147#define Inflate_PeekBits(state, bits)(state->Bits & ((1UL << (bits)) - 1UL)) (state->Bits & ((1UL << (bits)) - 1UL))
148/* Consumes/eats up bits from the bit buffer */
149#define Inflate_ConsumeBits(state, bits)state->Bits >>= (bits); state->NumBits -= (bits); state->Bits >>= (bits); state->NumBits -= (bits);
150/* Aligns bit buffer to be on a byte boundary */
151#define Inflate_AlignBits(state)cc_uint32 alignSkip = state->NumBits & 7; state->Bits
>>= (alignSkip); state->NumBits -= (alignSkip);;
cc_uint32 alignSkip = state->NumBits & 7; Inflate_ConsumeBits(state, alignSkip)state->Bits >>= (alignSkip); state->NumBits -= (alignSkip
);
;
152/* Ensures there are 'bitsCount' bits, or returns if not */
153#define Inflate_EnsureBits(state, bitsCount)while (state->NumBits < bitsCount) { if (!state->AvailIn
) return; state->AvailIn--; state->Bits |= (cc_uint32)(
*state->NextIn++) << state->NumBits; state->NumBits
+= 8;; }
while (state->NumBits < bitsCount) { if (!state->AvailIn) return; Inflate_GetByte(state)state->AvailIn--; state->Bits |= (cc_uint32)(*state->
NextIn++) << state->NumBits; state->NumBits += 8;
; }
154/* Ensures there are 'bitsCount' bits */
155#define Inflate_UNSAFE_EnsureBits(state, bitsCount)while (state->NumBits < bitsCount) { state->AvailIn--
; state->Bits |= (cc_uint32)(*state->NextIn++) <<
state->NumBits; state->NumBits += 8;; }
while (state->NumBits < bitsCount) { Inflate_GetByte(state)state->AvailIn--; state->Bits |= (cc_uint32)(*state->
NextIn++) << state->NumBits; state->NumBits += 8;
; }
156/* Peeks then consumes given bits */
157#define Inflate_ReadBits(state, bitsCount)(state->Bits & ((1UL << (bitsCount)) - 1UL)); state
->Bits >>= (bitsCount); state->NumBits -= (bitsCount
);;
Inflate_PeekBits(state, bitsCount)(state->Bits & ((1UL << (bitsCount)) - 1UL)); Inflate_ConsumeBits(state, bitsCount)state->Bits >>= (bitsCount); state->NumBits -= (bitsCount
);
;
158/* Sets to given result and sets state to DONE */
159#define Inflate_Fail(state, res)state->result = res; state->State = INFLATE_STATE_DONE; state->result = res; state->State = INFLATE_STATE_DONE;
160
161/* Goes to the next state, after having read data of a block */
162#define Inflate_NextBlockState(state)(state->LastBlock ? INFLATE_STATE_DONE : INFLATE_STATE_HEADER
)
(state->LastBlock ? INFLATE_STATE_DONE : INFLATE_STATE_HEADER)
163/* Goes to the next state, after having finished reading a compressed entry */
164#define Inflate_NextCompressState(state)((state->AvailIn >= 10 && state->AvailOut >=
258) ? INFLATE_STATE_FASTCOMPRESSED : INFLATE_STATE_COMPRESSED_LIT
)
((state->AvailIn >= INFLATE_FASTINF_IN10 && state->AvailOut >= INFLATE_FASTINF_OUT258) ? INFLATE_STATE_FASTCOMPRESSED : INFLATE_STATE_COMPRESSED_LIT)
165/* The maximum amount of bytes that can be output is 258 */
166#define INFLATE_FASTINF_OUT258 258
167/* The most input bytes required for huffman codes and extra data is 16 + 5 + 16 + 13 bits. Add 3 extra bytes to account for putting data into the bit buffer. */
168#define INFLATE_FASTINF_IN10 10
169
170static cc_uint32 Huffman_ReverseBits(cc_uint32 n, cc_uint8 bits) {
171 n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1);
172 n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2);
173 n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4);
174 n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8);
175 return n >> (16 - bits);
176}
177
178/* Builds a huffman tree, based on input lengths of each codeword */
179static cc_result Huffman_Build(struct HuffmanTable* table, const cc_uint8* bitLens, int count) {
180 int bl_count[INFLATE_MAX_BITS16], bl_offsets[INFLATE_MAX_BITS16];
181 int code, offset, value;
182 int i, j;
183
184 /* Initialise 'zero bit length' codewords */
185 table->FirstCodewords[0] = 0;
186 table->FirstOffsets[0] = 0;
187 table->EndCodewords[0] = 0;
188
189 /* Count number of codewords assigned to each bit length */
190 for (i = 0; i < INFLATE_MAX_BITS16; i++) bl_count[i] = 0;
191 for (i = 0; i < count; i++) {
192 bl_count[bitLens[i]]++;
193 }
194
195 /* Ensure huffman tree actually makes sense */
196 bl_count[0] = 0;
197 for (i = 1; i < INFLATE_MAX_BITS16; i++) {
198 /* Check if too many huffman codes for bit length */
199 if (bl_count[i] > (1 << i)) return INF_ERR_NUM_CODES;
200 }
201
202 /* Compute the codewords for the huffman tree.
203 * Codewords are ordered, so consider this example tree:
204 * 2 of length 2, 3 of length 3, 1 of length 4
205 * Codewords produced would be: 00,01 100,101,110, 1110
206 */
207 code = 0; offset = 0;
208 for (i = 1; i < INFLATE_MAX_BITS16; i++) {
209 code = (code + bl_count[i - 1]) << 1;
210 bl_offsets[i] = offset;
211
212 table->FirstCodewords[i] = code;
213 table->FirstOffsets[i] = offset;
214 offset += bl_count[i];
215
216 /* Last codeword is actually: code + (bl_count[i] - 1)
217 * However, when decoding we peform < against this value though, so need to add 1 here.
218 * This way, don't need to special case bit lengths with 0 codewords when decoding.
219 */
220 if (bl_count[i]) {
221 table->EndCodewords[i] = code + bl_count[i];
222 } else {
223 table->EndCodewords[i] = 0;
224 }
225 }
226
227 /* Assigns values to each codeword.
228 * Note that although codewords are ordered, values may not be.
229 * Some values may also not be assigned to any codeword.
230 */
231 value = 0;
232 Mem_Set(table->Fast, UInt8_MaxValue((cc_uint8)255), sizeof(table->Fast));
233 for (i = 0; i < count; i++, value++) {
234 int len = bitLens[i];
235 if (!len) continue;
236 table->Values[bl_offsets[len]] = value;
237
238 /* Compute the accelerated lookup table values for this codeword.
239 * For example, assume len = 4 and codeword = 0100
240 * - Shift it left to be 0100_00000
241 * - Then, for all the indices from 0100_00000 to 0100_11111,
242 * - bit reverse index, as huffman codes are read backwards
243 * - set fast value to specify a 'value' value, and to skip 'len' bits
244 */
245 if (len <= INFLATE_FAST_BITS9) {
246 cc_int16 packed = (cc_int16)((len << INFLATE_FAST_BITS9) | value);
247 int codeword = table->FirstCodewords[len] + (bl_offsets[len] - table->FirstOffsets[len]);
248 codeword <<= (INFLATE_FAST_BITS9 - len);
249
250 for (j = 0; j < 1 << (INFLATE_FAST_BITS9 - len); j++, codeword++) {
251 int index = Huffman_ReverseBits(codeword, INFLATE_FAST_BITS9);
252 table->Fast[index] = packed;
253 }
254 }
255 bl_offsets[len]++;
256 }
257 return 0;
258}
259
260/* Attempts to read the next huffman encoded value from the bitstream, using given table */
261/* Returns -1 if there are insufficient bits to read the value */
262static int Huffman_Decode(struct InflateState* state, struct HuffmanTable* table) {
263 cc_uint32 i, j, codeword;
264 int packed, bits, offset;
265
266 /* Buffer as many bits as possible */
267 while (state->NumBits <= INFLATE_MAX_BITS16) {
268 if (!state->AvailIn) break;
269 Inflate_GetByte(state)state->AvailIn--; state->Bits |= (cc_uint32)(*state->
NextIn++) << state->NumBits; state->NumBits += 8;
;
270 }
271
272 /* Try fast accelerated table lookup */
273 if (state->NumBits >= INFLATE_FAST_BITS9) {
274 packed = table->Fast[Inflate_PeekBits(state, INFLATE_FAST_BITS)(state->Bits & ((1UL << (9)) - 1UL))];
275 if (packed >= 0) {
276 bits = packed >> INFLATE_FAST_BITS9;
277 Inflate_ConsumeBits(state, bits)state->Bits >>= (bits); state->NumBits -= (bits);;
278 return packed & 0x1FF;
279 }
280 }
281
282 /* Slow, bit by bit lookup */
283 codeword = 0;
284 for (i = 1, j = 0; i < INFLATE_MAX_BITS16; i++, j++) {
285 if (state->NumBits < i) return -1;
286 codeword = (codeword << 1) | ((state->Bits >> j) & 1);
287
288 if (codeword < table->EndCodewords[i]) {
289 offset = table->FirstOffsets[i] + (codeword - table->FirstCodewords[i]);
290 Inflate_ConsumeBits(state, i)state->Bits >>= (i); state->NumBits -= (i);;
291 return table->Values[offset];
292 }
293 }
294
295 Inflate_Fail(state, INF_ERR_INVALID_CODE)state->result = INF_ERR_INVALID_CODE; state->State = INFLATE_STATE_DONE
;
;
296 return -1;
297}
298
299/* Inline the common <= 9 bits case */
300#define Huffman_UNSAFE_Decode(state, table, result){ while (state->NumBits < 16) { state->AvailIn--; state
->Bits |= (cc_uint32)(*state->NextIn++) << state->
NumBits; state->NumBits += 8;; }; packed = table.Fast[(state
->Bits & ((1UL << (9)) - 1UL))]; if (packed >=
0) { consumedBits = packed >> 9; state->Bits >>=
(consumedBits); state->NumBits -= (consumedBits);; result
= packed & 0x1FF; } else { result = Huffman_UNSAFE_Decode_Slow
(state, &table); }}
\
301{\
302 Inflate_UNSAFE_EnsureBits(state, INFLATE_MAX_BITS)while (state->NumBits < 16) { state->AvailIn--; state
->Bits |= (cc_uint32)(*state->NextIn++) << state->
NumBits; state->NumBits += 8;; }
;\
303 packed = table.Fast[Inflate_PeekBits(state, INFLATE_FAST_BITS)(state->Bits & ((1UL << (9)) - 1UL))];\
304 if (packed >= 0) {\
305 consumedBits = packed >> INFLATE_FAST_BITS9;\
306 Inflate_ConsumeBits(state, consumedBits)state->Bits >>= (consumedBits); state->NumBits -=
(consumedBits);
;\
307 result = packed & 0x1FF;\
308 } else {\
309 result = Huffman_UNSAFE_Decode_Slow(state, &table);\
310 }\
311}
312
313static int Huffman_UNSAFE_Decode_Slow(struct InflateState* state, struct HuffmanTable* table) {
314 cc_uint32 i, j, codeword;
315 int offset;
316
317 /* Slow, bit by bit lookup. Need to reverse order for huffman. */
318 codeword = Inflate_PeekBits(state, INFLATE_FAST_BITS)(state->Bits & ((1UL << (9)) - 1UL));
319 codeword = Huffman_ReverseBits(codeword, INFLATE_FAST_BITS9);
320
321 for (i = INFLATE_FAST_BITS9 + 1, j = INFLATE_FAST_BITS9; i < INFLATE_MAX_BITS16; i++, j++) {
322 codeword = (codeword << 1) | ((state->Bits >> j) & 1);
323
324 if (codeword < table->EndCodewords[i]) {
325 offset = table->FirstOffsets[i] + (codeword - table->FirstCodewords[i]);
326 Inflate_ConsumeBits(state, i)state->Bits >>= (i); state->NumBits -= (i);;
327 return table->Values[offset];
328 }
329 }
330
331 Inflate_Fail(state, INF_ERR_INVALID_CODE)state->result = INF_ERR_INVALID_CODE; state->State = INFLATE_STATE_DONE
;
;
332 /* Need to exit the fast decode loop */
333 /* TODO: This means a few garbage bytes can get written */
334 /* to the output, but it probably doesn't matter */
335 state->AvailIn = 0;
336 return 0;
337}
338
339void Inflate_Init2(struct InflateState* state, struct Stream* source) {
340 state->State = INFLATE_STATE_HEADER;
341 state->LastBlock = false0;
342 state->Bits = 0;
343 state->NumBits = 0;
344 state->NextIn = state->Input;
345 state->AvailIn = 0;
346 state->Output = NULL((void*)0);
347 state->AvailOut = 0;
348 state->Source = source;
349 state->WindowIndex = 0;
350 state->result = 0;
351}
352
353static const cc_uint8 fixed_lits[INFLATE_MAX_LITS288] = {
354 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
355 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
356 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
357 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
358 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
359 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
360 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
361 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
362 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8
363};
364static const cc_uint8 fixed_dists[INFLATE_MAX_DISTS32] = {
365 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
366};
367
368static const cc_uint16 len_base[31] = {
369 3,4,5,6,7,8,9,10,11,13,
370 15,17,19,23,27,31,35,43,51,59,
371 67,83,99,115,131,163,195,227,258,0,0
372};
373static const cc_uint8 len_bits[31] = {
374 0,0,0,0,0,0,0,0,1,1,
375 1,1,2,2,2,2,3,3,3,3,
376 4,4,4,4,5,5,5,5,0,0,0
377};
378static const cc_uint16 dist_base[32] = {
379 1,2,3,4,5,7,9,13,17,25,
380 33,49,65,97,129,193,257,385,513,769,
381 1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0
382};
383static const cc_uint8 dist_bits[32] = {
384 0,0,0,0,1,1,2,2,3,3,
385 4,4,5,5,6,6,7,7,8,8,
386 9,9,10,10,11,11,12,12,13,13,0,0
387};
388static const cc_uint8 codelens_order[INFLATE_MAX_CODELENS19] = {
389 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15
390};
391
392static void Inflate_InflateFast(struct InflateState* s) {
393 /* huffman variables */
394 cc_uint32 lit, len, dist;
395 cc_uint32 bits, lenIdx, distIdx;
396 int packed, consumedBits;
397
398 /* window variables */
399 cc_uint8* window;
400 cc_uint32 i, curIdx, startIdx;
401 cc_uint32 copyStart, copyLen, partLen;
402
403 window = s->Window;
404 curIdx = s->WindowIndex;
405 copyStart = s->WindowIndex;
406 copyLen = 0;
407
408#define INFLATE_FAST_COPY_MAX(0x8000UL - 258) (INFLATE_WINDOW_SIZE0x8000UL - INFLATE_FASTINF_OUT258)
409 while (s->AvailOut >= INFLATE_FASTINF_OUT258 && s->AvailIn >= INFLATE_FASTINF_IN10 && copyLen < INFLATE_FAST_COPY_MAX(0x8000UL - 258)) {
410 Huffman_UNSAFE_Decode(s, s->Table.Lits, lit){ while (s->NumBits < 16) { s->AvailIn--; s->Bits
|= (cc_uint32)(*s->NextIn++) << s->NumBits; s->
NumBits += 8;; }; packed = s->Table.Lits.Fast[(s->Bits &
((1UL << (9)) - 1UL))]; if (packed >= 0) { consumedBits
= packed >> 9; s->Bits >>= (consumedBits); s->
NumBits -= (consumedBits);; lit = packed & 0x1FF; } else {
lit = Huffman_UNSAFE_Decode_Slow(s, &s->Table.Lits); }
}
;
411
412 if (lit <= 256) {
413 if (lit < 256) {
414 window[curIdx] = (cc_uint8)lit;
415 s->AvailOut--; copyLen++;
416 curIdx = (curIdx + 1) & INFLATE_WINDOW_MASK0x7FFFUL;
417 } else {
418 s->State = Inflate_NextBlockState(s)(s->LastBlock ? INFLATE_STATE_DONE : INFLATE_STATE_HEADER);
419 break;
420 }
421 } else {
422 lenIdx = lit - 257;
423 bits = len_bits[lenIdx];
424 Inflate_UNSAFE_EnsureBits(s, bits)while (s->NumBits < bits) { s->AvailIn--; s->Bits
|= (cc_uint32)(*s->NextIn++) << s->NumBits; s->
NumBits += 8;; }
;
425 len = len_base[lenIdx] + Inflate_ReadBits(s, bits)(s->Bits & ((1UL << (bits)) - 1UL)); s->Bits >>=
(bits); s->NumBits -= (bits);;
;
426
427 Huffman_UNSAFE_Decode(s, s->TableDists, distIdx){ while (s->NumBits < 16) { s->AvailIn--; s->Bits
|= (cc_uint32)(*s->NextIn++) << s->NumBits; s->
NumBits += 8;; }; packed = s->TableDists.Fast[(s->Bits &
((1UL << (9)) - 1UL))]; if (packed >= 0) { consumedBits
= packed >> 9; s->Bits >>= (consumedBits); s->
NumBits -= (consumedBits);; distIdx = packed & 0x1FF; } else
{ distIdx = Huffman_UNSAFE_Decode_Slow(s, &s->TableDists
); }}
;
428 bits = dist_bits[distIdx];
429 Inflate_UNSAFE_EnsureBits(s, bits)while (s->NumBits < bits) { s->AvailIn--; s->Bits
|= (cc_uint32)(*s->NextIn++) << s->NumBits; s->
NumBits += 8;; }
;
430 dist = dist_base[distIdx] + Inflate_ReadBits(s, bits)(s->Bits & ((1UL << (bits)) - 1UL)); s->Bits >>=
(bits); s->NumBits -= (bits);;
;
431
432 /* Window infinitely repeats like ...xyz|uvwxyz|uvwxyz|uvw... */
433 /* If start and end don't cross a boundary, can avoid masking index */
434 startIdx = (curIdx - dist) & INFLATE_WINDOW_MASK0x7FFFUL;
435 if (curIdx >= startIdx && (curIdx + len) < INFLATE_WINDOW_SIZE0x8000UL) {
436 cc_uint8* src = &window[startIdx];
437 cc_uint8* dst = &window[curIdx];
438
439 for (i = 0; i < (len & ~0x3); i += 4) {
440 *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++;
441 }
442 for (; i < len; i++) { *dst++ = *src++; }
443 } else {
444 for (i = 0; i < len; i++) {
445 window[(curIdx + i) & INFLATE_WINDOW_MASK0x7FFFUL] = window[(startIdx + i) & INFLATE_WINDOW_MASK0x7FFFUL];
446 }
447 }
448 curIdx = (curIdx + len) & INFLATE_WINDOW_MASK0x7FFFUL;
449 s->AvailOut -= len; copyLen += len;
450 }
451 }
452
453 s->WindowIndex = curIdx;
454 if (!copyLen) return;
455
456 if (copyStart + copyLen < INFLATE_WINDOW_SIZE0x8000UL) {
457 Mem_Copy(s->Output, &s->Window[copyStart], copyLen);
458 s->Output += copyLen;
459 } else {
460 partLen = INFLATE_WINDOW_SIZE0x8000UL - copyStart;
461 Mem_Copy(s->Output, &s->Window[copyStart], partLen);
462 s->Output += partLen;
463 Mem_Copy(s->Output, s->Window, copyLen - partLen);
464 s->Output += (copyLen - partLen);
465 }
466}
467
468void Inflate_Process(struct InflateState* s) {
469 cc_uint32 len, dist, nlen;
470 cc_uint32 i, bits;
471 cc_uint32 blockHeader;
472 cc_result res;
473
474 /* len/dist table variables */
475 cc_uint32 distIdx, lenIdx;
476 int lit;
477 /* code lens table variables */
478 cc_uint32 count, repeatCount;
1
'repeatCount' declared without an initial value
479 cc_uint8 repeatValue;
480 /* window variables */
481 cc_uint32 startIdx, curIdx;
482 cc_uint32 copyLen, windowCopyLen;
483
484 for (;;) {
2
Loop condition is true. Entering loop body
485 switch (s->State) {
3
Control jumps to 'case INFLATE_STATE_DYNAMIC_LITSDISTSREPEAT:' at line 613
486 case INFLATE_STATE_HEADER: {
487 Inflate_EnsureBits(s, 3)while (s->NumBits < 3) { if (!s->AvailIn) return; s->
AvailIn--; s->Bits |= (cc_uint32)(*s->NextIn++) <<
s->NumBits; s->NumBits += 8;; }
;
488 blockHeader = Inflate_ReadBits(s, 3)(s->Bits & ((1UL << (3)) - 1UL)); s->Bits >>=
(3); s->NumBits -= (3);;
;
489 s->LastBlock = blockHeader & 1;
490
491 switch (blockHeader >> 1) {
492 case 0: { /* Uncompressed block */
493 Inflate_AlignBits(s)cc_uint32 alignSkip = s->NumBits & 7; s->Bits >>=
(alignSkip); s->NumBits -= (alignSkip);;
;
494 s->State = INFLATE_STATE_UNCOMPRESSED_HEADER;
495 } break;
496
497 case 1: { /* Fixed/static huffman compressed */
498 (void)Huffman_Build(&s->Table.Lits, fixed_lits, INFLATE_MAX_LITS288);
499 (void)Huffman_Build(&s->TableDists, fixed_dists, INFLATE_MAX_DISTS32);
500 s->State = Inflate_NextCompressState(s)((s->AvailIn >= 10 && s->AvailOut >= 258)
? INFLATE_STATE_FASTCOMPRESSED : INFLATE_STATE_COMPRESSED_LIT
)
;
501 } break;
502
503 case 2: { /* Dynamic huffman compressed */
504 s->State = INFLATE_STATE_DYNAMIC_HEADER;
505 } break;
506
507 case 3: {
508 Inflate_Fail(s, INF_ERR_BLOCKTYPE)s->result = INF_ERR_BLOCKTYPE; s->State = INFLATE_STATE_DONE
;
;
509 } break;
510
511 }
512 break;
513 }
514
515 case INFLATE_STATE_UNCOMPRESSED_HEADER: {
516 Inflate_EnsureBits(s, 32)while (s->NumBits < 32) { if (!s->AvailIn) return; s
->AvailIn--; s->Bits |= (cc_uint32)(*s->NextIn++) <<
s->NumBits; s->NumBits += 8;; }
;
517 len = Inflate_ReadBits(s, 16)(s->Bits & ((1UL << (16)) - 1UL)); s->Bits >>=
(16); s->NumBits -= (16);;
;
518 nlen = Inflate_ReadBits(s, 16)(s->Bits & ((1UL << (16)) - 1UL)); s->Bits >>=
(16); s->NumBits -= (16);;
;
519
520 if (len != (nlen ^ 0xFFFFUL)) {
521 Inflate_Fail(s, INF_ERR_BLOCKTYPE)s->result = INF_ERR_BLOCKTYPE; s->State = INFLATE_STATE_DONE
;
; return;
522 }
523 s->Index = len; /* Reuse for 'uncompressed length' */
524 s->State = INFLATE_STATE_UNCOMPRESSED_DATA;
525 }
526
527 case INFLATE_STATE_UNCOMPRESSED_DATA: {
528 /* read bits left in bit buffer (slow way) */
529 while (s->NumBits && s->AvailOut && s->Index) {
530 *s->Output = Inflate_ReadBits(s, 8)(s->Bits & ((1UL << (8)) - 1UL)); s->Bits >>=
(8); s->NumBits -= (8);;
;
531 s->Window[s->WindowIndex] = *s->Output;
532
533 s->WindowIndex = (s->WindowIndex + 1) & INFLATE_WINDOW_MASK0x7FFFUL;
534 s->Output++; s->AvailOut--; s->Index--;
535 }
536 if (!s->AvailIn || !s->AvailOut) return;
537
538 copyLen = min(s->AvailIn, s->AvailOut)((s->AvailIn) < (s->AvailOut) ? (s->AvailIn) : (s
->AvailOut))
;
539 copyLen = min(copyLen, s->Index)((copyLen) < (s->Index) ? (copyLen) : (s->Index));
540 if (copyLen > 0) {
541 Mem_Copy(s->Output, s->NextIn, copyLen);
542 windowCopyLen = INFLATE_WINDOW_SIZE0x8000UL - s->WindowIndex;
543 windowCopyLen = min(windowCopyLen, copyLen)((windowCopyLen) < (copyLen) ? (windowCopyLen) : (copyLen)
)
;
544
545 Mem_Copy(&s->Window[s->WindowIndex], s->Output, windowCopyLen);
546 /* Wrap around remainder of copy to start from beginning of window */
547 if (windowCopyLen < copyLen) {
548 Mem_Copy(s->Window, &s->Output[windowCopyLen], copyLen - windowCopyLen);
549 }
550
551 s->WindowIndex = (s->WindowIndex + copyLen) & INFLATE_WINDOW_MASK0x7FFFUL;
552 s->Output += copyLen; s->AvailOut -= copyLen; s->Index -= copyLen;
553 s->NextIn += copyLen; s->AvailIn -= copyLen;
554 }
555
556 if (!s->Index) { s->State = Inflate_NextBlockState(s)(s->LastBlock ? INFLATE_STATE_DONE : INFLATE_STATE_HEADER); }
557 break;
558 }
559
560 case INFLATE_STATE_DYNAMIC_HEADER: {
561 Inflate_EnsureBits(s, 14)while (s->NumBits < 14) { if (!s->AvailIn) return; s
->AvailIn--; s->Bits |= (cc_uint32)(*s->NextIn++) <<
s->NumBits; s->NumBits += 8;; }
;
562 s->NumLits = 257 + Inflate_ReadBits(s, 5)(s->Bits & ((1UL << (5)) - 1UL)); s->Bits >>=
(5); s->NumBits -= (5);;
;
563 s->NumDists = 1 + Inflate_ReadBits(s, 5)(s->Bits & ((1UL << (5)) - 1UL)); s->Bits >>=
(5); s->NumBits -= (5);;
;
564 s->NumCodeLens = 4 + Inflate_ReadBits(s, 4)(s->Bits & ((1UL << (4)) - 1UL)); s->Bits >>=
(4); s->NumBits -= (4);;
;
565 s->Index = 0;
566 s->State = INFLATE_STATE_DYNAMIC_CODELENS;
567 }
568
569 case INFLATE_STATE_DYNAMIC_CODELENS: {
570 while (s->Index < s->NumCodeLens) {
571 Inflate_EnsureBits(s, 3)while (s->NumBits < 3) { if (!s->AvailIn) return; s->
AvailIn--; s->Bits |= (cc_uint32)(*s->NextIn++) <<
s->NumBits; s->NumBits += 8;; }
;
572 i = codelens_order[s->Index];
573 s->Buffer[i] = Inflate_ReadBits(s, 3)(s->Bits & ((1UL << (3)) - 1UL)); s->Bits >>=
(3); s->NumBits -= (3);;
;
574 s->Index++;
575 }
576 for (i = s->NumCodeLens; i < INFLATE_MAX_CODELENS19; i++) {
577 s->Buffer[codelens_order[i]] = 0;
578 }
579
580 s->Index = 0;
581 s->State = INFLATE_STATE_DYNAMIC_LITSDISTS;
582 res = Huffman_Build(&s->Table.CodeLens, s->Buffer, INFLATE_MAX_CODELENS19);
583 if (res) { Inflate_Fail(s, res)s->result = res; s->State = INFLATE_STATE_DONE;; return; }
584 }
585
586 case INFLATE_STATE_DYNAMIC_LITSDISTS: {
587 count = s->NumLits + s->NumDists;
588 while (s->Index < count) {
589 int bits = Huffman_Decode(s, &s->Table.CodeLens);
590 if (bits < 16) {
591 if (bits == -1) return;
592 s->Buffer[s->Index] = (cc_uint8)bits;
593 s->Index++;
594 } else {
595 s->TmpCodeLens = bits;
596 s->State = INFLATE_STATE_DYNAMIC_LITSDISTSREPEAT;
597 break;
598 }
599 }
600
601 if (s->Index == count) {
602 s->Index = 0;
603 s->State = Inflate_NextCompressState(s)((s->AvailIn >= 10 && s->AvailOut >= 258)
? INFLATE_STATE_FASTCOMPRESSED : INFLATE_STATE_COMPRESSED_LIT
)
;
604
605 res = Huffman_Build(&s->Table.Lits, s->Buffer, s->NumLits);
606 if (res) { Inflate_Fail(s, res)s->result = res; s->State = INFLATE_STATE_DONE;; return; }
607 res = Huffman_Build(&s->TableDists, s->Buffer + s->NumLits, s->NumDists);
608 if (res) { Inflate_Fail(s, res)s->result = res; s->State = INFLATE_STATE_DONE;; return; }
609 }
610 break;
611 }
612
613 case INFLATE_STATE_DYNAMIC_LITSDISTSREPEAT: {
614 switch (s->TmpCodeLens) {
4
'Default' branch taken. Execution continues on line 635
615 case 16:
616 Inflate_EnsureBits(s, 2)while (s->NumBits < 2) { if (!s->AvailIn) return; s->
AvailIn--; s->Bits |= (cc_uint32)(*s->NextIn++) <<
s->NumBits; s->NumBits += 8;; }
;
617 repeatCount = Inflate_ReadBits(s, 2)(s->Bits & ((1UL << (2)) - 1UL)); s->Bits >>=
(2); s->NumBits -= (2);;
;
618 if (!s->Index) { Inflate_Fail(s, INF_ERR_REPEAT_BEG)s->result = INF_ERR_REPEAT_BEG; s->State = INFLATE_STATE_DONE
;
; return; }
619 repeatCount += 3; repeatValue = s->Buffer[s->Index - 1];
620 break;
621
622 case 17:
623 Inflate_EnsureBits(s, 3)while (s->NumBits < 3) { if (!s->AvailIn) return; s->
AvailIn--; s->Bits |= (cc_uint32)(*s->NextIn++) <<
s->NumBits; s->NumBits += 8;; }
;
624 repeatCount = Inflate_ReadBits(s, 3)(s->Bits & ((1UL << (3)) - 1UL)); s->Bits >>=
(3); s->NumBits -= (3);;
;
625 repeatCount += 3; repeatValue = 0;
626 break;
627
628 case 18:
629 Inflate_EnsureBits(s, 7)while (s->NumBits < 7) { if (!s->AvailIn) return; s->
AvailIn--; s->Bits |= (cc_uint32)(*s->NextIn++) <<
s->NumBits; s->NumBits += 8;; }
;
630 repeatCount = Inflate_ReadBits(s, 7)(s->Bits & ((1UL << (7)) - 1UL)); s->Bits >>=
(7); s->NumBits -= (7);;
;
631 repeatCount += 11; repeatValue = 0;
632 break;
633 }
634
635 count = s->NumLits + s->NumDists;
636 if (s->Index + repeatCount > count) {
5
The right operand of '+' is a garbage value
637 Inflate_Fail(s, INF_ERR_REPEAT_END)s->result = INF_ERR_REPEAT_END; s->State = INFLATE_STATE_DONE
;
; return;
638 }
639
640 Mem_Set(&s->Buffer[s->Index], repeatValue, repeatCount);
641 s->Index += repeatCount;
642 s->State = INFLATE_STATE_DYNAMIC_LITSDISTS;
643 break;
644 }
645
646 case INFLATE_STATE_COMPRESSED_LIT: {
647 if (!s->AvailOut) return;
648 lit = Huffman_Decode(s, &s->Table.Lits);
649
650 if (lit < 256) {
651 if (lit == -1) return;
652 *s->Output = (cc_uint8)lit;
653 s->Window[s->WindowIndex] = (cc_uint8)lit;
654 s->Output++; s->AvailOut--;
655 s->WindowIndex = (s->WindowIndex + 1) & INFLATE_WINDOW_MASK0x7FFFUL;
656 break;
657 } else if (lit == 256) {
658 s->State = Inflate_NextBlockState(s)(s->LastBlock ? INFLATE_STATE_DONE : INFLATE_STATE_HEADER);
659 break;
660 } else {
661 s->TmpLit = lit - 257;
662 s->State = INFLATE_STATE_COMPRESSED_LITEXTRA;
663 }
664 }
665
666 case INFLATE_STATE_COMPRESSED_LITEXTRA: {
667 lenIdx = s->TmpLit;
668 bits = len_bits[lenIdx];
669 Inflate_EnsureBits(s, bits)while (s->NumBits < bits) { if (!s->AvailIn) return;
s->AvailIn--; s->Bits |= (cc_uint32)(*s->NextIn++) <<
s->NumBits; s->NumBits += 8;; }
;
670 s->TmpLit = len_base[lenIdx] + Inflate_ReadBits(s, bits)(s->Bits & ((1UL << (bits)) - 1UL)); s->Bits >>=
(bits); s->NumBits -= (bits);;
;
671 s->State = INFLATE_STATE_COMPRESSED_DIST;
672 }
673
674 case INFLATE_STATE_COMPRESSED_DIST: {
675 s->TmpDist = Huffman_Decode(s, &s->TableDists);
676 if (s->TmpDist == -1) return;
677 s->State = INFLATE_STATE_COMPRESSED_DISTEXTRA;
678 }
679
680 case INFLATE_STATE_COMPRESSED_DISTEXTRA: {
681 distIdx = s->TmpDist;
682 bits = dist_bits[distIdx];
683 Inflate_EnsureBits(s, bits)while (s->NumBits < bits) { if (!s->AvailIn) return;
s->AvailIn--; s->Bits |= (cc_uint32)(*s->NextIn++) <<
s->NumBits; s->NumBits += 8;; }
;
684 s->TmpDist = dist_base[distIdx] + Inflate_ReadBits(s, bits)(s->Bits & ((1UL << (bits)) - 1UL)); s->Bits >>=
(bits); s->NumBits -= (bits);;
;
685 s->State = INFLATE_STATE_COMPRESSED_DATA;
686 }
687
688 case INFLATE_STATE_COMPRESSED_DATA: {
689 if (!s->AvailOut) return;
690 len = s->TmpLit; dist = s->TmpDist;
691 len = min(len, s->AvailOut)((len) < (s->AvailOut) ? (len) : (s->AvailOut));
692
693 /* TODO: Should we test outside of the loop, whether a masking will be required or not? */
694 startIdx = (s->WindowIndex - dist) & INFLATE_WINDOW_MASK0x7FFFUL;
695 curIdx = s->WindowIndex;
696 for (i = 0; i < len; i++) {
697 cc_uint8 value = s->Window[(startIdx + i) & INFLATE_WINDOW_MASK0x7FFFUL];
698 *s->Output = value;
699 s->Window[(curIdx + i) & INFLATE_WINDOW_MASK0x7FFFUL] = value;
700 s->Output++;
701 }
702
703 s->WindowIndex = (curIdx + len) & INFLATE_WINDOW_MASK0x7FFFUL;
704 s->TmpLit -= len;
705 s->AvailOut -= len;
706 if (!s->TmpLit) { s->State = Inflate_NextCompressState(s)((s->AvailIn >= 10 && s->AvailOut >= 258)
? INFLATE_STATE_FASTCOMPRESSED : INFLATE_STATE_COMPRESSED_LIT
)
; }
707 break;
708 }
709
710 case INFLATE_STATE_FASTCOMPRESSED: {
711 Inflate_InflateFast(s);
712 if (s->State == INFLATE_STATE_FASTCOMPRESSED) {
713 s->State = Inflate_NextCompressState(s)((s->AvailIn >= 10 && s->AvailOut >= 258)
? INFLATE_STATE_FASTCOMPRESSED : INFLATE_STATE_COMPRESSED_LIT
)
;
714 }
715 break;
716 }
717
718 case INFLATE_STATE_DONE:
719 return;
720 }
721 }
722}
723
724static cc_result Inflate_StreamRead(struct Stream* stream, cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
725 struct InflateState* state;
726 cc_uint8* inputEnd;
727 cc_uint32 read, left;
728 cc_uint32 startAvailOut;
729 cc_bool hasInput;
730 cc_result res;
731
732 *modified = 0;
733 state = (struct InflateState*)stream->Meta.Inflate;
734 state->Output = data;
735 state->AvailOut = count;
736
737 hasInput = true1;
738 while (state->AvailOut > 0 && hasInput) {
739 if (state->State == INFLATE_STATE_DONE) return state->result;
740
741 if (!state->AvailIn) {
742 /* Fully used up input buffer. Cycle back to start. */
743 inputEnd = state->Input + INFLATE_MAX_INPUT8192;
744 if (state->NextIn == inputEnd) state->NextIn = state->Input;
745
746 left = (cc_uint32)(inputEnd - state->NextIn);
747 res = state->Source->Read(state->Source, state->NextIn, left, &read);
748 if (res) return res;
749
750 /* Did we fail to read in more input data? Can't immediately return here, */
751 /* because there might be a few bits of data left in the bit buffer */
752 hasInput = read > 0;
753 state->AvailIn += read;
754 }
755
756 /* Reading data reduces available out */
757 startAvailOut = state->AvailOut;
758 Inflate_Process(state);
759 *modified += (startAvailOut - state->AvailOut);
760 }
761 return 0;
762}
763
764void Inflate_MakeStream2(struct Stream* stream, struct InflateState* state, struct Stream* underlying) {
765 Stream_Init(stream);
766 Inflate_Init2(state, underlying);
767 stream->Meta.Inflate = state;
768 stream->Read = Inflate_StreamRead;
769}
770
771
772/*########################################################################################################################*
773*---------------------------------------------------Deflate (compress)----------------------------------------------------*
774*#########################################################################################################################*/
775/* these are copies of len_base and dist_base, with UINT16_MAX instead of 0 for sentinel cutoff */
776static const cc_uint16 deflate_len[30] = {
777 3,4,5,6,7,8,9,10,11,13,
778 15,17,19,23,27,31,35,43,51,59,
779 67,83,99,115,131,163,195,227,258,UInt16_MaxValue((cc_uint16)65535)
780};
781static const cc_uint16 deflate_dist[31] = {
782 1,2,3,4,5,7,9,13,17,25,
783 33,49,65,97,129,193,257,385,513,769,
784 1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,UInt16_MaxValue((cc_uint16)65535)
785};
786
787/* Pushes given bits, but does not write them */
788#define Deflate_PushBits(state, value, bits)state->Bits |= (value) << state->NumBits; state->
NumBits += (bits);
state->Bits |= (value) << state->NumBits; state->NumBits += (bits);
789/* Pushes bits of the huffman codeword bits for the given literal, but does not write them */
790#define Deflate_PushLit(state, value)state->Bits |= (state->LitsCodewords[value]) << state
->NumBits; state->NumBits += (state->LitsLens[value]
);
Deflate_PushBits(state, state->LitsCodewords[value], state->LitsLens[value])state->Bits |= (state->LitsCodewords[value]) << state
->NumBits; state->NumBits += (state->LitsLens[value]
);
791/* Pushes given bits (reversing for huffman code), but does not write them */
792#define Deflate_PushHuff(state, value, bits)state->Bits |= (Huffman_ReverseBits(value, bits)) <<
state->NumBits; state->NumBits += (bits);
Deflate_PushBits(state, Huffman_ReverseBits(value, bits), bits)state->Bits |= (Huffman_ReverseBits(value, bits)) <<
state->NumBits; state->NumBits += (bits);
793/* Writes given byte to output */
794#define Deflate_WriteByte(state)*state->NextOut++ = state->Bits; state->AvailOut--; state
->Bits >>= 8; state->NumBits -= 8;
*state->NextOut++ = state->Bits; state->AvailOut--; state->Bits >>= 8; state->NumBits -= 8;
795/* Flushes bits in buffer to output buffer */
796#define Deflate_FlushBits(state)while (state->NumBits >= 8) { *state->NextOut++ = state
->Bits; state->AvailOut--; state->Bits >>= 8; state
->NumBits -= 8;; }
while (state->NumBits >= 8) { Deflate_WriteByte(state)*state->NextOut++ = state->Bits; state->AvailOut--; state
->Bits >>= 8; state->NumBits -= 8;
; }
797
798#define MIN_MATCH_LEN3 3
799#define MAX_MATCH_LEN258 258
800
801/* Number of bytes that match (are the same) from a and b */
802static int Deflate_MatchLen(cc_uint8* a, cc_uint8* b, int maxLen) {
803 int i = 0;
804 while (i < maxLen && *a == *b) { i++; a++; b++; }
805 return i;
806}
807
808/* Hashes 3 bytes of data */
809static cc_uint32 Deflate_Hash(cc_uint8* src) {
810 return (cc_uint32)((src[0] << 8) ^ (src[1] << 4) ^ (src[2])) & DEFLATE_HASH_MASK0x0FFFUL;
811}
812
813/* Writes a literal to state->Output */
814static void Deflate_Lit(struct DeflateState* state, int lit) {
815 Deflate_PushLit(state, lit)state->Bits |= (state->LitsCodewords[lit]) << state
->NumBits; state->NumBits += (state->LitsLens[lit]);
;
816 Deflate_FlushBits(state)while (state->NumBits >= 8) { *state->NextOut++ = state
->Bits; state->AvailOut--; state->Bits >>= 8; state
->NumBits -= 8;; }
;
817}
818
819/* Writes a length-distance pair to state->Output */
820static void Deflate_LenDist(struct DeflateState* state, int len, int dist) {
821 int j;
822 /* TODO: Do we actually need the if (len_bits[j]) ????????? does writing 0 bits matter??? */
823
824 for (j = 0; len >= deflate_len[j + 1]; j++);
825 Deflate_PushLit(state, j + 257)state->Bits |= (state->LitsCodewords[j + 257]) <<
state->NumBits; state->NumBits += (state->LitsLens[
j + 257]);
;
826 if (len_bits[j]) { Deflate_PushBits(state, len - deflate_len[j], len_bits[j])state->Bits |= (len - deflate_len[j]) << state->NumBits
; state->NumBits += (len_bits[j]);
; }
827 Deflate_FlushBits(state)while (state->NumBits >= 8) { *state->NextOut++ = state
->Bits; state->AvailOut--; state->Bits >>= 8; state
->NumBits -= 8;; }
;
828
829 for (j = 0; dist >= deflate_dist[j + 1]; j++);
830 Deflate_PushHuff(state, j, 5)state->Bits |= (Huffman_ReverseBits(j, 5)) << state->
NumBits; state->NumBits += (5);
;
831 if (dist_bits[j]) { Deflate_PushBits(state, dist - deflate_dist[j], dist_bits[j])state->Bits |= (dist - deflate_dist[j]) << state->
NumBits; state->NumBits += (dist_bits[j]);
; }
832 Deflate_FlushBits(state)while (state->NumBits >= 8) { *state->NextOut++ = state
->Bits; state->AvailOut--; state->Bits >>= 8; state
->NumBits -= 8;; }
;
833}
834
835/* Moves "current block" to "previous block", adjusting state if needed. */
836static void Deflate_MoveBlock(struct DeflateState* state) {
837 int i;
838 Mem_Copy(state->Input, state->Input + DEFLATE_BLOCK_SIZE16384, DEFLATE_BLOCK_SIZE16384);
839 state->InputPosition = DEFLATE_BLOCK_SIZE16384;
840
841 /* adjust hash table offsets, removing offsets that are no longer in data at all */
842 for (i = 0; i < Array_Elems(state->Head)(sizeof(state->Head) / sizeof(state->Head[0])); i++) {
843 state->Head[i] = state->Head[i] < DEFLATE_BLOCK_SIZE16384 ? 0 : (state->Head[i] - DEFLATE_BLOCK_SIZE16384);
844 }
845 for (i = 0; i < Array_Elems(state->Prev)(sizeof(state->Prev) / sizeof(state->Prev[0])); i++) {
846 state->Prev[i] = state->Prev[i] < DEFLATE_BLOCK_SIZE16384 ? 0 : (state->Prev[i] - DEFLATE_BLOCK_SIZE16384);
847 }
848}
849
850/* Compresses current block of data */
851static cc_result Deflate_FlushBlock(struct DeflateState* state, int len) {
852 cc_uint32 hash, nextHash;
853 int bestLen, maxLen, matchLen, depth;
854 int bestPos, pos, nextPos;
855 cc_uint16 oldHead;
856 cc_uint8* input;
857 cc_uint8* cur;
858 cc_result res;
859
860 if (!state->WroteHeader) {
861 state->WroteHeader = true1;
862 Deflate_PushBits(state, 3, 3)state->Bits |= (3) << state->NumBits; state->NumBits
+= (3);
; /* final block TRUE, block type FIXED */
863 }
864
865 /* Based off descriptions from http://www.gzip.org/algorithm.txt and
866 https://github.com/nothings/stb/blob/master/stb_image_write.h */
867 input = state->Input;
868 cur = input + DEFLATE_BLOCK_SIZE16384;
869
870 /* Compress current block of data */
871 /* Use > instead of >=, because also try match at one byte after current */
872 while (len > MIN_MATCH_LEN3) {
873 hash = Deflate_Hash(cur);
874 maxLen = min(len, MAX_MATCH_LEN)((len) < (258) ? (len) : (258));
875
876 bestLen = MIN_MATCH_LEN3 - 1; /* Match must be at least 3 bytes */
877 bestPos = 0;
878
879 /* Find longest match starting at this byte */
880 /* Only explore up to 5 previous matches, to avoid slow performance */
881 /* (i.e prefer quickly saving maps/screenshots to completely optimal filesize) */
882 pos = state->Head[hash];
883 for (depth = 0; pos != 0 && depth < 5; depth++) {
884 matchLen = Deflate_MatchLen(&input[pos], cur, maxLen);
885 if (matchLen > bestLen) { bestLen = matchLen; bestPos = pos; }
886 pos = state->Prev[pos];
887 }
888
889 /* Insert this entry into the hash chain */
890 pos = (int)(cur - input);
891 oldHead = state->Head[hash];
892 state->Head[hash] = pos;
893 state->Prev[pos] = oldHead;
894
895 /* Lazy evaluation: Find longest match starting at next byte */
896 /* If that's longer than the longest match at current byte, throwaway this match */
897 if (bestPos) {
898 nextHash = Deflate_Hash(cur + 1);
899 nextPos = state->Head[nextHash];
900 maxLen = min(len - 1, MAX_MATCH_LEN)((len - 1) < (258) ? (len - 1) : (258));
901
902 for (depth = 0; nextPos != 0 && depth < 5; depth++) {
903 matchLen = Deflate_MatchLen(&input[nextPos], cur + 1, maxLen);
904 if (matchLen > bestLen) { bestPos = 0; break; }
905 nextPos = state->Prev[nextPos];
906 }
907 }
908
909 if (bestPos) {
910 Deflate_LenDist(state, bestLen, pos - bestPos);
911 len -= bestLen; cur += bestLen;
912 } else {
913 Deflate_Lit(state, *cur);
914 len--; cur++;
915 }
916
917 /* leave room for a few bytes and literals at end */
918 if (state->AvailOut >= 20) continue;
919 res = Stream_Write(state->Dest, state->Output, DEFLATE_OUT_SIZE8192 - state->AvailOut);
920 state->NextOut = state->Output;
921 state->AvailOut = DEFLATE_OUT_SIZE8192;
922 if (res) return res;
923 }
924
925 /* literals for last few bytes */
926 while (len > 0) {
927 Deflate_Lit(state, *cur);
928 len--; cur++;
929 }
930
931 res = Stream_Write(state->Dest, state->Output, DEFLATE_OUT_SIZE8192 - state->AvailOut);
932 state->NextOut = state->Output;
933 state->AvailOut = DEFLATE_OUT_SIZE8192;
934
935 Deflate_MoveBlock(state);
936 return res;
937}
938
939/* Adds data to buffered output data, flushing if needed */
940static cc_result Deflate_StreamWrite(struct Stream* stream, const cc_uint8* data, cc_uint32 total, cc_uint32* modified) {
941 struct DeflateState* state;
942 cc_result res;
943
944 state = (struct DeflateState*)stream->Meta.Inflate;
945 *modified = 0;
946
947 while (total > 0) {
948 cc_uint8* dst = &state->Input[state->InputPosition];
949 cc_uint32 len = total;
950 if (state->InputPosition + len >= DEFLATE_BUFFER_SIZE32768) {
951 len = DEFLATE_BUFFER_SIZE32768 - state->InputPosition;
952 }
953
954 Mem_Copy(dst, data, len);
955 total -= len;
956 state->InputPosition += len;
957 *modified += len;
958 data += len;
959
960 if (state->InputPosition == DEFLATE_BUFFER_SIZE32768) {
961 res = Deflate_FlushBlock(state, DEFLATE_BLOCK_SIZE16384);
962 if (res) return res;
963 }
964 }
965 return 0;
966}
967
968/* Flushes any buffered data, then writes terminating symbol */
969static cc_result Deflate_StreamClose(struct Stream* stream) {
970 struct DeflateState* state;
971 cc_result res;
972
973 state = (struct DeflateState*)stream->Meta.Inflate;
974 res = Deflate_FlushBlock(state, state->InputPosition - DEFLATE_BLOCK_SIZE16384);
975 if (res) return res;
976
977 /* Write huffman encoded "literal 256" to terminate symbols */
978 Deflate_PushLit(state, 256)state->Bits |= (state->LitsCodewords[256]) << state
->NumBits; state->NumBits += (state->LitsLens[256]);
;
979 Deflate_FlushBits(state)while (state->NumBits >= 8) { *state->NextOut++ = state
->Bits; state->AvailOut--; state->Bits >>= 8; state
->NumBits -= 8;; }
;
980
981 /* In case last byte still has a few extra bits */
982 if (state->NumBits) {
983 while (state->NumBits < 8) { Deflate_PushBits(state, 0, 1)state->Bits |= (0) << state->NumBits; state->NumBits
+= (1);
; }
984 Deflate_FlushBits(state)while (state->NumBits >= 8) { *state->NextOut++ = state
->Bits; state->AvailOut--; state->Bits >>= 8; state
->NumBits -= 8;; }
;
985 }
986
987 return Stream_Write(state->Dest, state->Output, DEFLATE_OUT_SIZE8192 - state->AvailOut);
988}
989
990/* Constructs a huffman encoding table (for values to codewords) */
991static void Deflate_BuildTable(const cc_uint8* lens, int count, cc_uint16* codewords, cc_uint8* bitlens) {
992 int i, j, offset, codeword;
993 struct HuffmanTable table;
994
995 /* NOTE: Can ignore since lens table is not user controlled */
996 (void)Huffman_Build(&table, lens, count);
997 for (i = 0; i < INFLATE_MAX_BITS16; i++) {
998 if (!table.EndCodewords[i]) continue;
999 count = table.EndCodewords[i] - table.FirstCodewords[i];
1000
1001 for (j = 0; j < count; j++) {
1002 offset = table.Values[table.FirstOffsets[i] + j];
1003 codeword = table.FirstCodewords[i] + j;
1004 bitlens[offset] = i;
1005 codewords[offset] = Huffman_ReverseBits(codeword, i);
1006 }
1007 }
1008}
1009
1010void Deflate_MakeStream(struct Stream* stream, struct DeflateState* state, struct Stream* underlying) {
1011 Stream_Init(stream);
1012 stream->Meta.Inflate = state;
1013 stream->Write = Deflate_StreamWrite;
1014 stream->Close = Deflate_StreamClose;
1015
1016 /* First half of buffer is "previous block" */
1017 state->InputPosition = DEFLATE_BLOCK_SIZE16384;
1018 state->Bits = 0;
1019 state->NumBits = 0;
1020
1021 state->NextOut = state->Output;
1022 state->AvailOut = DEFLATE_OUT_SIZE8192;
1023 state->Dest = underlying;
1024 state->WroteHeader = false0;
1025
1026 Mem_Set(state->Head, 0, sizeof(state->Head));
1027 Mem_Set(state->Prev, 0, sizeof(state->Prev));
1028 Deflate_BuildTable(fixed_lits, INFLATE_MAX_LITS288, state->LitsCodewords, state->LitsLens);
1029}
1030
1031
1032/*########################################################################################################################*
1033*-----------------------------------------------------GZip (compress)-----------------------------------------------------*
1034*#########################################################################################################################*/
1035static cc_result GZip_StreamClose(struct Stream* stream) {
1036 struct GZipState* state = (struct GZipState*)stream->Meta.Inflate;
1037 cc_uint8 data[8];
1038 cc_result res;
1039
1040 if ((res = Deflate_StreamClose(stream))) return res;
1041 Stream_SetU32_LE(&data[0], state->Crc32 ^ 0xFFFFFFFFUL);
1042 Stream_SetU32_LE(&data[4], state->Size);
1043 return Stream_Write(state->Base.Dest, data, sizeof(data));
1044}
1045
1046static cc_result GZip_StreamWrite(struct Stream* stream, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
1047 struct GZipState* state = (struct GZipState*)stream->Meta.Inflate;
1048 cc_uint32 i, crc32 = state->Crc32;
1049 state->Size += count;
1050
1051 /* TODO: Optimise this calculation */
1052 for (i = 0; i < count; i++) {
1053 crc32 = Utils_Crc32Table[(crc32 ^ data[i]) & 0xFF] ^ (crc32 >> 8);
1054 }
1055
1056 state->Crc32 = crc32;
1057 return Deflate_StreamWrite(stream, data, count, modified);
1058}
1059
1060static cc_result GZip_StreamWriteFirst(struct Stream* stream, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
1061 static cc_uint8 header[10] = { 0x1F, 0x8B, 0x08 }; /* GZip header */
1062 struct GZipState* state = (struct GZipState*)stream->Meta.Inflate;
1063 cc_result res;
1064
1065 if ((res = Stream_Write(state->Base.Dest, header, sizeof(header)))) return res;
1066 stream->Write = GZip_StreamWrite;
1067 return GZip_StreamWrite(stream, data, count, modified);
1068}
1069
1070void GZip_MakeStream(struct Stream* stream, struct GZipState* state, struct Stream* underlying) {
1071 Deflate_MakeStream(stream, &state->Base, underlying);
1072 state->Crc32 = 0xFFFFFFFFUL;
1073 state->Size = 0;
1074 stream->Write = GZip_StreamWriteFirst;
1075 stream->Close = GZip_StreamClose;
1076}
1077
1078
1079/*########################################################################################################################*
1080*-----------------------------------------------------ZLib (compress)-----------------------------------------------------*
1081*#########################################################################################################################*/
1082static cc_result ZLib_StreamClose(struct Stream* stream) {
1083 struct ZLibState* state = (struct ZLibState*)stream->Meta.Inflate;
1084 cc_uint8 data[4];
1085 cc_result res;
1086
1087 if ((res = Deflate_StreamClose(stream))) return res;
1088 Stream_SetU32_BE(&data[0], state->Adler32);
1089 return Stream_Write(state->Base.Dest, data, sizeof(data));
1090}
1091
1092static cc_result ZLib_StreamWrite(struct Stream* stream, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
1093 struct ZLibState* state = (struct ZLibState*)stream->Meta.Inflate;
1094 cc_uint32 i, adler32 = state->Adler32;
1095 cc_uint32 s1 = adler32 & 0xFFFF, s2 = (adler32 >> 16) & 0xFFFF;
1096
1097 /* TODO: Optimise this calculation */
1098 for (i = 0; i < count; i++) {
1099 #define ADLER32_BASE65521 65521
1100 s1 = (s1 + data[i]) % ADLER32_BASE65521;
1101 s2 = (s2 + s1) % ADLER32_BASE65521;
1102 }
1103
1104 state->Adler32 = (s2 << 16) | s1;
1105 return Deflate_StreamWrite(stream, data, count, modified);
1106}
1107
1108static cc_result ZLib_StreamWriteFirst(struct Stream* stream, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
1109 static cc_uint8 header[2] = { 0x78, 0x9C }; /* ZLib header */
1110 struct ZLibState* state = (struct ZLibState*)stream->Meta.Inflate;
1111 cc_result res;
1112
1113 if ((res = Stream_Write(state->Base.Dest, header, sizeof(header)))) return res;
1114 stream->Write = ZLib_StreamWrite;
1115 return ZLib_StreamWrite(stream, data, count, modified);
1116}
1117
1118void ZLib_MakeStream(struct Stream* stream, struct ZLibState* state, struct Stream* underlying) {
1119 Deflate_MakeStream(stream, &state->Base, underlying);
1120 state->Adler32 = 1;
1121 stream->Write = ZLib_StreamWriteFirst;
1122 stream->Close = ZLib_StreamClose;
1123}
1124
1125
1126/*########################################################################################################################*
1127*--------------------------------------------------------ZipEntry---------------------------------------------------------*
1128*#########################################################################################################################*/
1129#define ZIP_MAXNAMELEN512 512
1130static cc_result Zip_ReadLocalFileHeader(struct ZipState* state, struct ZipEntry* entry) {
1131 struct Stream* stream = state->input;
1132 cc_uint8 header[26];
1133 cc_uint32 compressedSize, uncompressedSize;
1134 int method, pathLen, extraLen;
1135
1136 cc_string path; char pathBuffer[ZIP_MAXNAMELEN512];
1137 struct Stream portion, compStream;
1138 struct InflateState inflate;
1139 cc_result res;
1140 if ((res = Stream_Read(stream, header, sizeof(header)))) return res;
1141
1142 method = Stream_GetU16_LE(&header[4]);
1143 compressedSize = Stream_GetU32_LE(&header[14]);
1144 uncompressedSize = Stream_GetU32_LE(&header[18]);
1145
1146 /* Some .zip files don't set these in local file header */
1147 if (!compressedSize) compressedSize = entry->CompressedSize;
1148 if (!uncompressedSize) uncompressedSize = entry->UncompressedSize;
1149
1150 pathLen = Stream_GetU16_LE(&header[22]);
1151 extraLen = Stream_GetU16_LE(&header[24]);
1152 if (pathLen > ZIP_MAXNAMELEN512) return ZIP_ERR_FILENAME_LEN;
1153
1154 /* NOTE: ZIP spec says path uses code page 437 for encoding */
1155 path = String_Init(pathBuffer, pathLen, pathLen);
1156 if ((res = Stream_Read(stream, (cc_uint8*)pathBuffer, pathLen))) return res;
1157 state->_curEntry = entry;
1158
1159 if (!state->SelectEntry(&path)) return 0;
1160 /* local file may have extra data before actual data (e.g. ZIP64) */
1161 if ((res = stream->Skip(stream, extraLen))) return res;
1162
1163 if (method == 0) {
1164 Stream_ReadonlyPortion(&portion, stream, uncompressedSize);
1165 return state->ProcessEntry(&path, &portion, state);
1166 } else if (method == 8) {
1167 Stream_ReadonlyPortion(&portion, stream, compressedSize);
1168 Inflate_MakeStream2(&compStream, &inflate, &portion);
1169 return state->ProcessEntry(&path, &compStream, state);
1170 } else {
1171 Platform_Log1("Unsupported.zip entry compression method: %i", &method);
1172 /* TODO: Should this be an error */
1173 }
1174 return 0;
1175}
1176
1177static cc_result Zip_ReadCentralDirectory(struct ZipState* state) {
1178 struct Stream* stream = state->input;
1179 struct ZipEntry* entry;
1180 cc_uint8 header[42];
1181
1182 cc_string path; char pathBuffer[ZIP_MAXNAMELEN512];
1183 int pathLen, extraLen, commentLen;
1184 cc_result res;
1185 if ((res = Stream_Read(stream, header, sizeof(header)))) return res;
1186
1187 pathLen = Stream_GetU16_LE(&header[24]);
1188 if (pathLen > ZIP_MAXNAMELEN512) return ZIP_ERR_FILENAME_LEN;
1189
1190 /* NOTE: ZIP spec says path uses code page 437 for encoding */
1191 path = String_Init(pathBuffer, pathLen, pathLen);
1192 if ((res = Stream_Read(stream, (cc_uint8*)pathBuffer, pathLen))) return res;
1193
1194 /* skip data following central directory entry header */
1195 extraLen = Stream_GetU16_LE(&header[26]);
1196 commentLen = Stream_GetU16_LE(&header[28]);
1197 if ((res = stream->Skip(stream, extraLen + commentLen))) return res;
1198
1199 if (!state->SelectEntry(&path)) return 0;
1200 if (state->_usedEntries >= ZIP_MAX_ENTRIES1024) return ZIP_ERR_TOO_MANY_ENTRIES;
1201 entry = &state->entries[state->_usedEntries++];
1202
1203 entry->CRC32 = Stream_GetU32_LE(&header[12]);
1204 entry->CompressedSize = Stream_GetU32_LE(&header[16]);
1205 entry->UncompressedSize = Stream_GetU32_LE(&header[20]);
1206 entry->LocalHeaderOffset = Stream_GetU32_LE(&header[38]);
1207 return 0;
1208}
1209
1210static cc_result Zip_ReadEndOfCentralDirectory(struct ZipState* state) {
1211 struct Stream* stream = state->input;
1212 cc_uint8 header[18];
1213
1214 cc_result res;
1215 if ((res = Stream_Read(stream, header, sizeof(header)))) return res;
1216
1217 state->_totalEntries = Stream_GetU16_LE(&header[6]);
1218 state->_centralDirBeg = Stream_GetU32_LE(&header[12]);
1219 return 0;
1220}
1221
1222enum ZipSig {
1223 ZIP_SIG_ENDOFCENTRALDIR = 0x06054b50,
1224 ZIP_SIG_CENTRALDIR = 0x02014b50,
1225 ZIP_SIG_LOCALFILEHEADER = 0x04034b50
1226};
1227
1228static cc_result Zip_DefaultProcessor(const cc_string* path, struct Stream* data, struct ZipState* s) { return 0; }
1229static cc_bool Zip_DefaultSelector(const cc_string* path) { return true1; }
1230void Zip_Init(struct ZipState* state, struct Stream* input) {
1231 state->input = input;
1232 state->obj = NULL((void*)0);
1233 state->ProcessEntry = Zip_DefaultProcessor;
1234 state->SelectEntry = Zip_DefaultSelector;
1235}
1236
1237cc_result Zip_Extract(struct ZipState* state) {
1238 struct Stream* stream = state->input;
1239 cc_uint32 stream_len;
1240 cc_uint32 sig = 0;
1241 int i, count;
1242
1243 cc_result res;
1244 if ((res = stream->Length(stream, &stream_len))) return res;
1245
1246 /* At -22 for nearly all zips, but try a bit further back in case of comment */
1247 count = min(257, stream_len)((257) < (stream_len) ? (257) : (stream_len));
1248 for (i = 22; i < count; i++) {
1249 res = stream->Seek(stream, stream_len - i);
1250 if (res) return ZIP_ERR_SEEK_END_OF_CENTRAL_DIR;
1251
1252 if ((res = Stream_ReadU32_LE(stream, &sig))) return res;
1253 if (sig == ZIP_SIG_ENDOFCENTRALDIR) break;
1254 }
1255
1256 if (sig != ZIP_SIG_ENDOFCENTRALDIR) return ZIP_ERR_NO_END_OF_CENTRAL_DIR;
1257 res = Zip_ReadEndOfCentralDirectory(state);
1258 if (res) return res;
1259
1260 res = stream->Seek(stream, state->_centralDirBeg);
1261 if (res) return ZIP_ERR_SEEK_CENTRAL_DIR;
1262 state->_usedEntries = 0;
1263
1264 /* Read all the central directory entries */
1265 for (i = 0; i < state->_totalEntries; i++) {
1266 if ((res = Stream_ReadU32_LE(stream, &sig))) return res;
1267
1268 if (sig == ZIP_SIG_CENTRALDIR) {
1269 res = Zip_ReadCentralDirectory(state);
1270 if (res) return res;
1271 } else if (sig == ZIP_SIG_ENDOFCENTRALDIR) {
1272 break;
1273 } else {
1274 return ZIP_ERR_INVALID_CENTRAL_DIR;
1275 }
1276 }
1277
1278 /* Now read the local file header entries */
1279 for (i = 0; i < state->_usedEntries; i++) {
1280 struct ZipEntry* entry = &state->entries[i];
1281 res = stream->Seek(stream, entry->LocalHeaderOffset);
1282 if (res) return ZIP_ERR_SEEK_LOCAL_DIR;
1283
1284 if ((res = Stream_ReadU32_LE(stream, &sig))) return res;
1285 if (sig != ZIP_SIG_LOCALFILEHEADER) return ZIP_ERR_INVALID_LOCAL_DIR;
1286
1287 res = Zip_ReadLocalFileHeader(state, entry);
1288 if (res) return res;
1289 }
1290 return 0;
1291}