Bug Summary

File:Deflate.c
Warning:line 627, 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/2020-12-10-180422-33404-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 void 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 if (bl_count[i] > (1 << i)) {
199 Logger_Abort("Too many huffman codes for bit length");
200 }
201 }
202
203 /* Compute the codewords for the huffman tree.
204 * Codewords are ordered, so consider this example tree:
205 * 2 of length 2, 3 of length 3, 1 of length 4
206 * Codewords produced would be: 00,01 100,101,110, 1110
207 */
208 code = 0; offset = 0;
209 for (i = 1; i < INFLATE_MAX_BITS16; i++) {
210 code = (code + bl_count[i - 1]) << 1;
211 bl_offsets[i] = offset;
212
213 table->FirstCodewords[i] = code;
214 table->FirstOffsets[i] = offset;
215 offset += bl_count[i];
216
217 /* Last codeword is actually: code + (bl_count[i] - 1)
218 * However, when decoding we peform < against this value though, so need to add 1 here.
219 * This way, don't need to special case bit lengths with 0 codewords when decoding.
220 */
221 if (bl_count[i]) {
222 table->EndCodewords[i] = code + bl_count[i];
223 } else {
224 table->EndCodewords[i] = 0;
225 }
226 }
227
228 /* Assigns values to each codeword.
229 * Note that although codewords are ordered, values may not be.
230 * Some values may also not be assigned to any codeword.
231 */
232 value = 0;
233 Mem_Set(table->Fast, UInt8_MaxValue((cc_uint8)255), sizeof(table->Fast));
234 for (i = 0; i < count; i++, value++) {
235 int len = bitLens[i];
236 if (!len) continue;
237 table->Values[bl_offsets[len]] = value;
238
239 /* Compute the accelerated lookup table values for this codeword.
240 * For example, assume len = 4 and codeword = 0100
241 * - Shift it left to be 0100_00000
242 * - Then, for all the indices from 0100_00000 to 0100_11111,
243 * - bit reverse index, as huffman codes are read backwards
244 * - set fast value to specify a 'value' value, and to skip 'len' bits
245 */
246 if (len <= INFLATE_FAST_BITS9) {
247 cc_int16 packed = (cc_int16)((len << INFLATE_FAST_BITS9) | value);
248 int codeword = table->FirstCodewords[len] + (bl_offsets[len] - table->FirstOffsets[len]);
249 codeword <<= (INFLATE_FAST_BITS9 - len);
250
251 for (j = 0; j < 1 << (INFLATE_FAST_BITS9 - len); j++, codeword++) {
252 int index = Huffman_ReverseBits(codeword, INFLATE_FAST_BITS9);
253 table->Fast[index] = packed;
254 }
255 }
256 bl_offsets[len]++;
257 }
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 Logger_Abort("DEFLATE - Invalid huffman code");
332 return -1;
333}
334
335void Inflate_Init2(struct InflateState* state, struct Stream* source) {
336 state->State = INFLATE_STATE_HEADER;
337 state->LastBlock = false0;
338 state->Bits = 0;
339 state->NumBits = 0;
340 state->NextIn = state->Input;
341 state->AvailIn = 0;
342 state->Output = NULL((void*)0);
343 state->AvailOut = 0;
344 state->Source = source;
345 state->WindowIndex = 0;
346 state->result = 0;
347}
348
349static const cc_uint8 fixed_lits[INFLATE_MAX_LITS288] = {
350 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,
351 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,
352 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,
353 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,
354 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,
355 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,
356 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,
357 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,
358 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
359};
360static const cc_uint8 fixed_dists[INFLATE_MAX_DISTS32] = {
361 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
362};
363
364static const cc_uint16 len_base[31] = {
365 3,4,5,6,7,8,9,10,11,13,
366 15,17,19,23,27,31,35,43,51,59,
367 67,83,99,115,131,163,195,227,258,0,0
368};
369static const cc_uint8 len_bits[31] = {
370 0,0,0,0,0,0,0,0,1,1,
371 1,1,2,2,2,2,3,3,3,3,
372 4,4,4,4,5,5,5,5,0,0,0
373};
374static const cc_uint16 dist_base[32] = {
375 1,2,3,4,5,7,9,13,17,25,
376 33,49,65,97,129,193,257,385,513,769,
377 1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0
378};
379static const cc_uint8 dist_bits[32] = {
380 0,0,0,0,1,1,2,2,3,3,
381 4,4,5,5,6,6,7,7,8,8,
382 9,9,10,10,11,11,12,12,13,13,0,0
383};
384static const cc_uint8 codelens_order[INFLATE_MAX_CODELENS19] = {
385 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15
386};
387
388static void Inflate_InflateFast(struct InflateState* s) {
389 /* huffman variables */
390 cc_uint32 lit, len, dist;
391 cc_uint32 bits, lenIdx, distIdx;
392 int packed, consumedBits;
393
394 /* window variables */
395 cc_uint8* window;
396 cc_uint32 i, curIdx, startIdx;
397 cc_uint32 copyStart, copyLen, partLen;
398
399 window = s->Window;
400 curIdx = s->WindowIndex;
401 copyStart = s->WindowIndex;
402 copyLen = 0;
403
404#define INFLATE_FAST_COPY_MAX(0x8000UL - 258) (INFLATE_WINDOW_SIZE0x8000UL - INFLATE_FASTINF_OUT258)
405 while (s->AvailOut >= INFLATE_FASTINF_OUT258 && s->AvailIn >= INFLATE_FASTINF_IN10 && copyLen < INFLATE_FAST_COPY_MAX(0x8000UL - 258)) {
406 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); }
}
;
407
408 if (lit <= 256) {
409 if (lit < 256) {
410 window[curIdx] = (cc_uint8)lit;
411 s->AvailOut--; copyLen++;
412 curIdx = (curIdx + 1) & INFLATE_WINDOW_MASK0x7FFFUL;
413 } else {
414 s->State = Inflate_NextBlockState(s)(s->LastBlock ? INFLATE_STATE_DONE : INFLATE_STATE_HEADER);
415 break;
416 }
417 } else {
418 lenIdx = lit - 257;
419 bits = len_bits[lenIdx];
420 Inflate_UNSAFE_EnsureBits(s, bits)while (s->NumBits < bits) { s->AvailIn--; s->Bits
|= (cc_uint32)(*s->NextIn++) << s->NumBits; s->
NumBits += 8;; }
;
421 len = len_base[lenIdx] + Inflate_ReadBits(s, bits)(s->Bits & ((1UL << (bits)) - 1UL)); s->Bits >>=
(bits); s->NumBits -= (bits);;
;
422
423 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
); }}
;
424 bits = dist_bits[distIdx];
425 Inflate_UNSAFE_EnsureBits(s, bits)while (s->NumBits < bits) { s->AvailIn--; s->Bits
|= (cc_uint32)(*s->NextIn++) << s->NumBits; s->
NumBits += 8;; }
;
426 dist = dist_base[distIdx] + Inflate_ReadBits(s, bits)(s->Bits & ((1UL << (bits)) - 1UL)); s->Bits >>=
(bits); s->NumBits -= (bits);;
;
427
428 /* Window infinitely repeats like ...xyz|uvwxyz|uvwxyz|uvw... */
429 /* If start and end don't cross a boundary, can avoid masking index */
430 startIdx = (curIdx - dist) & INFLATE_WINDOW_MASK0x7FFFUL;
431 if (curIdx >= startIdx && (curIdx + len) < INFLATE_WINDOW_SIZE0x8000UL) {
432 cc_uint8* src = &window[startIdx];
433 cc_uint8* dst = &window[curIdx];
434
435 for (i = 0; i < (len & ~0x3); i += 4) {
436 *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++;
437 }
438 for (; i < len; i++) { *dst++ = *src++; }
439 } else {
440 for (i = 0; i < len; i++) {
441 window[(curIdx + i) & INFLATE_WINDOW_MASK0x7FFFUL] = window[(startIdx + i) & INFLATE_WINDOW_MASK0x7FFFUL];
442 }
443 }
444 curIdx = (curIdx + len) & INFLATE_WINDOW_MASK0x7FFFUL;
445 s->AvailOut -= len; copyLen += len;
446 }
447 }
448
449 s->WindowIndex = curIdx;
450 if (!copyLen) return;
451
452 if (copyStart + copyLen < INFLATE_WINDOW_SIZE0x8000UL) {
453 Mem_Copy(s->Output, &s->Window[copyStart], copyLen);
454 s->Output += copyLen;
455 } else {
456 partLen = INFLATE_WINDOW_SIZE0x8000UL - copyStart;
457 Mem_Copy(s->Output, &s->Window[copyStart], partLen);
458 s->Output += partLen;
459 Mem_Copy(s->Output, s->Window, copyLen - partLen);
460 s->Output += (copyLen - partLen);
461 }
462}
463
464void Inflate_Process(struct InflateState* s) {
465 cc_uint32 len, dist, nlen;
466 cc_uint32 i, bits;
467 cc_uint32 blockHeader;
468
469 /* len/dist table variables */
470 cc_uint32 distIdx, lenIdx;
471 int lit;
472 /* code lens table variables */
473 cc_uint32 count, repeatCount;
1
'repeatCount' declared without an initial value
474 cc_uint8 repeatValue;
475 /* window variables */
476 cc_uint32 startIdx, curIdx;
477 cc_uint32 copyLen, windowCopyLen;
478
479 for (;;) {
2
Loop condition is true. Entering loop body
480 switch (s->State) {
3
Control jumps to 'case INFLATE_STATE_DYNAMIC_LITSDISTSREPEAT:' at line 604
481 case INFLATE_STATE_HEADER: {
482 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;; }
;
483 blockHeader = Inflate_ReadBits(s, 3)(s->Bits & ((1UL << (3)) - 1UL)); s->Bits >>=
(3); s->NumBits -= (3);;
;
484 s->LastBlock = blockHeader & 1;
485
486 switch (blockHeader >> 1) {
487 case 0: { /* Uncompressed block */
488 Inflate_AlignBits(s)cc_uint32 alignSkip = s->NumBits & 7; s->Bits >>=
(alignSkip); s->NumBits -= (alignSkip);;
;
489 s->State = INFLATE_STATE_UNCOMPRESSED_HEADER;
490 } break;
491
492 case 1: { /* Fixed/static huffman compressed */
493 Huffman_Build(&s->Table.Lits, fixed_lits, INFLATE_MAX_LITS288);
494 Huffman_Build(&s->TableDists, fixed_dists, INFLATE_MAX_DISTS32);
495 s->State = Inflate_NextCompressState(s)((s->AvailIn >= 10 && s->AvailOut >= 258)
? INFLATE_STATE_FASTCOMPRESSED : INFLATE_STATE_COMPRESSED_LIT
)
;
496 } break;
497
498 case 2: { /* Dynamic huffman compressed */
499 s->State = INFLATE_STATE_DYNAMIC_HEADER;
500 } break;
501
502 case 3: {
503 Inflate_Fail(s, INF_ERR_BLOCKTYPE)s->result = INF_ERR_BLOCKTYPE; s->State = INFLATE_STATE_DONE
;
;
504 } break;
505
506 }
507 break;
508 }
509
510 case INFLATE_STATE_UNCOMPRESSED_HEADER: {
511 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;; }
;
512 len = Inflate_ReadBits(s, 16)(s->Bits & ((1UL << (16)) - 1UL)); s->Bits >>=
(16); s->NumBits -= (16);;
;
513 nlen = Inflate_ReadBits(s, 16)(s->Bits & ((1UL << (16)) - 1UL)); s->Bits >>=
(16); s->NumBits -= (16);;
;
514
515 if (len != (nlen ^ 0xFFFFUL)) {
516 Inflate_Fail(s, INF_ERR_BLOCKTYPE)s->result = INF_ERR_BLOCKTYPE; s->State = INFLATE_STATE_DONE
;
; return;
517 }
518 s->Index = len; /* Reuse for 'uncompressed length' */
519 s->State = INFLATE_STATE_UNCOMPRESSED_DATA;
520 }
521
522 case INFLATE_STATE_UNCOMPRESSED_DATA: {
523 /* read bits left in bit buffer (slow way) */
524 while (s->NumBits && s->AvailOut && s->Index) {
525 *s->Output = Inflate_ReadBits(s, 8)(s->Bits & ((1UL << (8)) - 1UL)); s->Bits >>=
(8); s->NumBits -= (8);;
;
526 s->Window[s->WindowIndex] = *s->Output;
527
528 s->WindowIndex = (s->WindowIndex + 1) & INFLATE_WINDOW_MASK0x7FFFUL;
529 s->Output++; s->AvailOut--; s->Index--;
530 }
531 if (!s->AvailIn || !s->AvailOut) return;
532
533 copyLen = min(s->AvailIn, s->AvailOut)((s->AvailIn) < (s->AvailOut) ? (s->AvailIn) : (s
->AvailOut))
;
534 copyLen = min(copyLen, s->Index)((copyLen) < (s->Index) ? (copyLen) : (s->Index));
535 if (copyLen > 0) {
536 Mem_Copy(s->Output, s->NextIn, copyLen);
537 windowCopyLen = INFLATE_WINDOW_SIZE0x8000UL - s->WindowIndex;
538 windowCopyLen = min(windowCopyLen, copyLen)((windowCopyLen) < (copyLen) ? (windowCopyLen) : (copyLen)
)
;
539
540 Mem_Copy(&s->Window[s->WindowIndex], s->Output, windowCopyLen);
541 /* Wrap around remainder of copy to start from beginning of window */
542 if (windowCopyLen < copyLen) {
543 Mem_Copy(s->Window, &s->Output[windowCopyLen], copyLen - windowCopyLen);
544 }
545
546 s->WindowIndex = (s->WindowIndex + copyLen) & INFLATE_WINDOW_MASK0x7FFFUL;
547 s->Output += copyLen; s->AvailOut -= copyLen; s->Index -= copyLen;
548 s->NextIn += copyLen; s->AvailIn -= copyLen;
549 }
550
551 if (!s->Index) { s->State = Inflate_NextBlockState(s)(s->LastBlock ? INFLATE_STATE_DONE : INFLATE_STATE_HEADER); }
552 break;
553 }
554
555 case INFLATE_STATE_DYNAMIC_HEADER: {
556 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;; }
;
557 s->NumLits = 257 + Inflate_ReadBits(s, 5)(s->Bits & ((1UL << (5)) - 1UL)); s->Bits >>=
(5); s->NumBits -= (5);;
;
558 s->NumDists = 1 + Inflate_ReadBits(s, 5)(s->Bits & ((1UL << (5)) - 1UL)); s->Bits >>=
(5); s->NumBits -= (5);;
;
559 s->NumCodeLens = 4 + Inflate_ReadBits(s, 4)(s->Bits & ((1UL << (4)) - 1UL)); s->Bits >>=
(4); s->NumBits -= (4);;
;
560 s->Index = 0;
561 s->State = INFLATE_STATE_DYNAMIC_CODELENS;
562 }
563
564 case INFLATE_STATE_DYNAMIC_CODELENS: {
565 while (s->Index < s->NumCodeLens) {
566 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;; }
;
567 i = codelens_order[s->Index];
568 s->Buffer[i] = Inflate_ReadBits(s, 3)(s->Bits & ((1UL << (3)) - 1UL)); s->Bits >>=
(3); s->NumBits -= (3);;
;
569 s->Index++;
570 }
571 for (i = s->NumCodeLens; i < INFLATE_MAX_CODELENS19; i++) {
572 s->Buffer[codelens_order[i]] = 0;
573 }
574
575 s->Index = 0;
576 s->State = INFLATE_STATE_DYNAMIC_LITSDISTS;
577 Huffman_Build(&s->Table.CodeLens, s->Buffer, INFLATE_MAX_CODELENS19);
578 }
579
580 case INFLATE_STATE_DYNAMIC_LITSDISTS: {
581 count = s->NumLits + s->NumDists;
582 while (s->Index < count) {
583 int bits = Huffman_Decode(s, &s->Table.CodeLens);
584 if (bits < 16) {
585 if (bits == -1) return;
586 s->Buffer[s->Index] = (cc_uint8)bits;
587 s->Index++;
588 } else {
589 s->TmpCodeLens = bits;
590 s->State = INFLATE_STATE_DYNAMIC_LITSDISTSREPEAT;
591 break;
592 }
593 }
594
595 if (s->Index == count) {
596 s->Index = 0;
597 s->State = Inflate_NextCompressState(s)((s->AvailIn >= 10 && s->AvailOut >= 258)
? INFLATE_STATE_FASTCOMPRESSED : INFLATE_STATE_COMPRESSED_LIT
)
;
598 Huffman_Build(&s->Table.Lits, s->Buffer, s->NumLits);
599 Huffman_Build(&s->TableDists, &s->Buffer[s->NumLits], s->NumDists);
600 }
601 break;
602 }
603
604 case INFLATE_STATE_DYNAMIC_LITSDISTSREPEAT: {
605 switch (s->TmpCodeLens) {
4
'Default' branch taken. Execution continues on line 626
606 case 16:
607 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;; }
;
608 repeatCount = Inflate_ReadBits(s, 2)(s->Bits & ((1UL << (2)) - 1UL)); s->Bits >>=
(2); s->NumBits -= (2);;
;
609 if (!s->Index) { Inflate_Fail(s, INF_ERR_REPEAT_BEG)s->result = INF_ERR_REPEAT_BEG; s->State = INFLATE_STATE_DONE
;
; return; }
610 repeatCount += 3; repeatValue = s->Buffer[s->Index - 1];
611 break;
612
613 case 17:
614 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;; }
;
615 repeatCount = Inflate_ReadBits(s, 3)(s->Bits & ((1UL << (3)) - 1UL)); s->Bits >>=
(3); s->NumBits -= (3);;
;
616 repeatCount += 3; repeatValue = 0;
617 break;
618
619 case 18:
620 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;; }
;
621 repeatCount = Inflate_ReadBits(s, 7)(s->Bits & ((1UL << (7)) - 1UL)); s->Bits >>=
(7); s->NumBits -= (7);;
;
622 repeatCount += 11; repeatValue = 0;
623 break;
624 }
625
626 count = s->NumLits + s->NumDists;
627 if (s->Index + repeatCount > count) {
5
The right operand of '+' is a garbage value
628 Inflate_Fail(s, INF_ERR_REPEAT_END)s->result = INF_ERR_REPEAT_END; s->State = INFLATE_STATE_DONE
;
; return;
629 }
630
631 Mem_Set(&s->Buffer[s->Index], repeatValue, repeatCount);
632 s->Index += repeatCount;
633 s->State = INFLATE_STATE_DYNAMIC_LITSDISTS;
634 break;
635 }
636
637 case INFLATE_STATE_COMPRESSED_LIT: {
638 if (!s->AvailOut) return;
639 lit = Huffman_Decode(s, &s->Table.Lits);
640
641 if (lit < 256) {
642 if (lit == -1) return;
643 *s->Output = (cc_uint8)lit;
644 s->Window[s->WindowIndex] = (cc_uint8)lit;
645 s->Output++; s->AvailOut--;
646 s->WindowIndex = (s->WindowIndex + 1) & INFLATE_WINDOW_MASK0x7FFFUL;
647 break;
648 } else if (lit == 256) {
649 s->State = Inflate_NextBlockState(s)(s->LastBlock ? INFLATE_STATE_DONE : INFLATE_STATE_HEADER);
650 break;
651 } else {
652 s->TmpLit = lit - 257;
653 s->State = INFLATE_STATE_COMPRESSED_LITEXTRA;
654 }
655 }
656
657 case INFLATE_STATE_COMPRESSED_LITEXTRA: {
658 lenIdx = s->TmpLit;
659 bits = len_bits[lenIdx];
660 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;; }
;
661 s->TmpLit = len_base[lenIdx] + Inflate_ReadBits(s, bits)(s->Bits & ((1UL << (bits)) - 1UL)); s->Bits >>=
(bits); s->NumBits -= (bits);;
;
662 s->State = INFLATE_STATE_COMPRESSED_DIST;
663 }
664
665 case INFLATE_STATE_COMPRESSED_DIST: {
666 s->TmpDist = Huffman_Decode(s, &s->TableDists);
667 if (s->TmpDist == -1) return;
668 s->State = INFLATE_STATE_COMPRESSED_DISTEXTRA;
669 }
670
671 case INFLATE_STATE_COMPRESSED_DISTEXTRA: {
672 distIdx = s->TmpDist;
673 bits = dist_bits[distIdx];
674 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;; }
;
675 s->TmpDist = dist_base[distIdx] + Inflate_ReadBits(s, bits)(s->Bits & ((1UL << (bits)) - 1UL)); s->Bits >>=
(bits); s->NumBits -= (bits);;
;
676 s->State = INFLATE_STATE_COMPRESSED_DATA;
677 }
678
679 case INFLATE_STATE_COMPRESSED_DATA: {
680 if (!s->AvailOut) return;
681 len = s->TmpLit; dist = s->TmpDist;
682 len = min(len, s->AvailOut)((len) < (s->AvailOut) ? (len) : (s->AvailOut));
683
684 /* TODO: Should we test outside of the loop, whether a masking will be required or not? */
685 startIdx = (s->WindowIndex - dist) & INFLATE_WINDOW_MASK0x7FFFUL;
686 curIdx = s->WindowIndex;
687 for (i = 0; i < len; i++) {
688 cc_uint8 value = s->Window[(startIdx + i) & INFLATE_WINDOW_MASK0x7FFFUL];
689 *s->Output = value;
690 s->Window[(curIdx + i) & INFLATE_WINDOW_MASK0x7FFFUL] = value;
691 s->Output++;
692 }
693
694 s->WindowIndex = (curIdx + len) & INFLATE_WINDOW_MASK0x7FFFUL;
695 s->TmpLit -= len;
696 s->AvailOut -= len;
697 if (!s->TmpLit) { s->State = Inflate_NextCompressState(s)((s->AvailIn >= 10 && s->AvailOut >= 258)
? INFLATE_STATE_FASTCOMPRESSED : INFLATE_STATE_COMPRESSED_LIT
)
; }
698 break;
699 }
700
701 case INFLATE_STATE_FASTCOMPRESSED: {
702 Inflate_InflateFast(s);
703 if (s->State == INFLATE_STATE_FASTCOMPRESSED) {
704 s->State = Inflate_NextCompressState(s)((s->AvailIn >= 10 && s->AvailOut >= 258)
? INFLATE_STATE_FASTCOMPRESSED : INFLATE_STATE_COMPRESSED_LIT
)
;
705 }
706 break;
707 }
708
709 case INFLATE_STATE_DONE:
710 return;
711 }
712 }
713}
714
715static cc_result Inflate_StreamRead(struct Stream* stream, cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
716 struct InflateState* state;
717 cc_uint8* inputEnd;
718 cc_uint32 read, left;
719 cc_uint32 startAvailOut;
720 cc_bool hasInput;
721 cc_result res;
722
723 *modified = 0;
724 state = (struct InflateState*)stream->Meta.Inflate;
725 state->Output = data;
726 state->AvailOut = count;
727
728 hasInput = true1;
729 while (state->AvailOut > 0 && hasInput) {
730 if (state->State == INFLATE_STATE_DONE) return state->result;
731
732 if (!state->AvailIn) {
733 /* Fully used up input buffer. Cycle back to start. */
734 inputEnd = state->Input + INFLATE_MAX_INPUT8192;
735 if (state->NextIn == inputEnd) state->NextIn = state->Input;
736
737 left = (cc_uint32)(inputEnd - state->NextIn);
738 res = state->Source->Read(state->Source, state->NextIn, left, &read);
739 if (res) return res;
740
741 /* Did we fail to read in more input data? Can't immediately return here, */
742 /* because there might be a few bits of data left in the bit buffer */
743 hasInput = read > 0;
744 state->AvailIn += read;
745 }
746
747 /* Reading data reduces available out */
748 startAvailOut = state->AvailOut;
749 Inflate_Process(state);
750 *modified += (startAvailOut - state->AvailOut);
751 }
752 return 0;
753}
754
755void Inflate_MakeStream2(struct Stream* stream, struct InflateState* state, struct Stream* underlying) {
756 Stream_Init(stream);
757 Inflate_Init2(state, underlying);
758 stream->Meta.Inflate = state;
759 stream->Read = Inflate_StreamRead;
760}
761
762
763/*########################################################################################################################*
764*---------------------------------------------------Deflate (compress)----------------------------------------------------*
765*#########################################################################################################################*/
766/* these are copies of len_base and dist_base, with UINT16_MAX instead of 0 for sentinel cutoff */
767static const cc_uint16 deflate_len[30] = {
768 3,4,5,6,7,8,9,10,11,13,
769 15,17,19,23,27,31,35,43,51,59,
770 67,83,99,115,131,163,195,227,258,UInt16_MaxValue((cc_uint16)65535)
771};
772static const cc_uint16 deflate_dist[31] = {
773 1,2,3,4,5,7,9,13,17,25,
774 33,49,65,97,129,193,257,385,513,769,
775 1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,UInt16_MaxValue((cc_uint16)65535)
776};
777
778/* Pushes given bits, but does not write them */
779#define Deflate_PushBits(state, value, bits)state->Bits |= (value) << state->NumBits; state->
NumBits += (bits);
state->Bits |= (value) << state->NumBits; state->NumBits += (bits);
780/* Pushes bits of the huffman codeword bits for the given literal, but does not write them */
781#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]
);
782/* Pushes given bits (reversing for huffman code), but does not write them */
783#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);
784/* Writes given byte to output */
785#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;
786/* Flushes bits in buffer to output buffer */
787#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;
; }
788
789#define MIN_MATCH_LEN3 3
790#define MAX_MATCH_LEN258 258
791
792/* Number of bytes that match (are the same) from a and b */
793static int Deflate_MatchLen(cc_uint8* a, cc_uint8* b, int maxLen) {
794 int i = 0;
795 while (i < maxLen && *a == *b) { i++; a++; b++; }
796 return i;
797}
798
799/* Hashes 3 bytes of data */
800static cc_uint32 Deflate_Hash(cc_uint8* src) {
801 return (cc_uint32)((src[0] << 8) ^ (src[1] << 4) ^ (src[2])) & DEFLATE_HASH_MASK0x0FFFUL;
802}
803
804/* Writes a literal to state->Output */
805static void Deflate_Lit(struct DeflateState* state, int lit) {
806 Deflate_PushLit(state, lit)state->Bits |= (state->LitsCodewords[lit]) << state
->NumBits; state->NumBits += (state->LitsLens[lit]);
;
807 Deflate_FlushBits(state)while (state->NumBits >= 8) { *state->NextOut++ = state
->Bits; state->AvailOut--; state->Bits >>= 8; state
->NumBits -= 8;; }
;
808}
809
810/* Writes a length-distance pair to state->Output */
811static void Deflate_LenDist(struct DeflateState* state, int len, int dist) {
812 int j;
813 /* TODO: Do we actually need the if (len_bits[j]) ????????? does writing 0 bits matter??? */
814
815 for (j = 0; len >= deflate_len[j + 1]; j++);
816 Deflate_PushLit(state, j + 257)state->Bits |= (state->LitsCodewords[j + 257]) <<
state->NumBits; state->NumBits += (state->LitsLens[
j + 257]);
;
817 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]);
; }
818 Deflate_FlushBits(state)while (state->NumBits >= 8) { *state->NextOut++ = state
->Bits; state->AvailOut--; state->Bits >>= 8; state
->NumBits -= 8;; }
;
819
820 for (j = 0; dist >= deflate_dist[j + 1]; j++);
821 Deflate_PushHuff(state, j, 5)state->Bits |= (Huffman_ReverseBits(j, 5)) << state->
NumBits; state->NumBits += (5);
;
822 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]);
; }
823 Deflate_FlushBits(state)while (state->NumBits >= 8) { *state->NextOut++ = state
->Bits; state->AvailOut--; state->Bits >>= 8; state
->NumBits -= 8;; }
;
824}
825
826/* Moves "current block" to "previous block", adjusting state if needed. */
827static void Deflate_MoveBlock(struct DeflateState* state) {
828 int i;
829 Mem_Copy(state->Input, state->Input + DEFLATE_BLOCK_SIZE16384, DEFLATE_BLOCK_SIZE16384);
830 state->InputPosition = DEFLATE_BLOCK_SIZE16384;
831
832 /* adjust hash table offsets, removing offsets that are no longer in data at all */
833 for (i = 0; i < Array_Elems(state->Head)(sizeof(state->Head) / sizeof(state->Head[0])); i++) {
834 state->Head[i] = state->Head[i] < DEFLATE_BLOCK_SIZE16384 ? 0 : (state->Head[i] - DEFLATE_BLOCK_SIZE16384);
835 }
836 for (i = 0; i < Array_Elems(state->Prev)(sizeof(state->Prev) / sizeof(state->Prev[0])); i++) {
837 state->Prev[i] = state->Prev[i] < DEFLATE_BLOCK_SIZE16384 ? 0 : (state->Prev[i] - DEFLATE_BLOCK_SIZE16384);
838 }
839}
840
841/* Compresses current block of data */
842static cc_result Deflate_FlushBlock(struct DeflateState* state, int len) {
843 cc_uint32 hash, nextHash;
844 int bestLen, maxLen, matchLen, depth;
845 int bestPos, pos, nextPos;
846 cc_uint16 oldHead;
847 cc_uint8* input;
848 cc_uint8* cur;
849 cc_result res;
850
851 if (!state->WroteHeader) {
852 state->WroteHeader = true1;
853 Deflate_PushBits(state, 3, 3)state->Bits |= (3) << state->NumBits; state->NumBits
+= (3);
; /* final block TRUE, block type FIXED */
854 }
855
856 /* Based off descriptions from http://www.gzip.org/algorithm.txt and
857 https://github.com/nothings/stb/blob/master/stb_image_write.h */
858 input = state->Input;
859 cur = input + DEFLATE_BLOCK_SIZE16384;
860
861 /* Compress current block of data */
862 /* Use > instead of >=, because also try match at one byte after current */
863 while (len > MIN_MATCH_LEN3) {
864 hash = Deflate_Hash(cur);
865 maxLen = min(len, MAX_MATCH_LEN)((len) < (258) ? (len) : (258));
866
867 bestLen = MIN_MATCH_LEN3 - 1; /* Match must be at least 3 bytes */
868 bestPos = 0;
869
870 /* Find longest match starting at this byte */
871 /* Only explore up to 5 previous matches, to avoid slow performance */
872 /* (i.e prefer quickly saving maps/screenshots to completely optimal filesize) */
873 pos = state->Head[hash];
874 for (depth = 0; pos != 0 && depth < 5; depth++) {
875 matchLen = Deflate_MatchLen(&input[pos], cur, maxLen);
876 if (matchLen > bestLen) { bestLen = matchLen; bestPos = pos; }
877 pos = state->Prev[pos];
878 }
879
880 /* Insert this entry into the hash chain */
881 pos = (int)(cur - input);
882 oldHead = state->Head[hash];
883 state->Head[hash] = pos;
884 state->Prev[pos] = oldHead;
885
886 /* Lazy evaluation: Find longest match starting at next byte */
887 /* If that's longer than the longest match at current byte, throwaway this match */
888 if (bestPos) {
889 nextHash = Deflate_Hash(cur + 1);
890 nextPos = state->Head[nextHash];
891 maxLen = min(len - 1, MAX_MATCH_LEN)((len - 1) < (258) ? (len - 1) : (258));
892
893 for (depth = 0; nextPos != 0 && depth < 5; depth++) {
894 matchLen = Deflate_MatchLen(&input[nextPos], cur + 1, maxLen);
895 if (matchLen > bestLen) { bestPos = 0; break; }
896 nextPos = state->Prev[nextPos];
897 }
898 }
899
900 if (bestPos) {
901 Deflate_LenDist(state, bestLen, pos - bestPos);
902 len -= bestLen; cur += bestLen;
903 } else {
904 Deflate_Lit(state, *cur);
905 len--; cur++;
906 }
907
908 /* leave room for a few bytes and literals at end */
909 if (state->AvailOut >= 20) continue;
910 res = Stream_Write(state->Dest, state->Output, DEFLATE_OUT_SIZE8192 - state->AvailOut);
911 state->NextOut = state->Output;
912 state->AvailOut = DEFLATE_OUT_SIZE8192;
913 if (res) return res;
914 }
915
916 /* literals for last few bytes */
917 while (len > 0) {
918 Deflate_Lit(state, *cur);
919 len--; cur++;
920 }
921
922 res = Stream_Write(state->Dest, state->Output, DEFLATE_OUT_SIZE8192 - state->AvailOut);
923 state->NextOut = state->Output;
924 state->AvailOut = DEFLATE_OUT_SIZE8192;
925
926 Deflate_MoveBlock(state);
927 return res;
928}
929
930/* Adds data to buffered output data, flushing if needed */
931static cc_result Deflate_StreamWrite(struct Stream* stream, const cc_uint8* data, cc_uint32 total, cc_uint32* modified) {
932 struct DeflateState* state;
933 cc_result res;
934
935 state = (struct DeflateState*)stream->Meta.Inflate;
936 *modified = 0;
937
938 while (total > 0) {
939 cc_uint8* dst = &state->Input[state->InputPosition];
940 cc_uint32 len = total;
941 if (state->InputPosition + len >= DEFLATE_BUFFER_SIZE32768) {
942 len = DEFLATE_BUFFER_SIZE32768 - state->InputPosition;
943 }
944
945 Mem_Copy(dst, data, len);
946 total -= len;
947 state->InputPosition += len;
948 *modified += len;
949 data += len;
950
951 if (state->InputPosition == DEFLATE_BUFFER_SIZE32768) {
952 res = Deflate_FlushBlock(state, DEFLATE_BLOCK_SIZE16384);
953 if (res) return res;
954 }
955 }
956 return 0;
957}
958
959/* Flushes any buffered data, then writes terminating symbol */
960static cc_result Deflate_StreamClose(struct Stream* stream) {
961 struct DeflateState* state;
962 cc_result res;
963
964 state = (struct DeflateState*)stream->Meta.Inflate;
965 res = Deflate_FlushBlock(state, state->InputPosition - DEFLATE_BLOCK_SIZE16384);
966 if (res) return res;
967
968 /* Write huffman encoded "literal 256" to terminate symbols */
969 Deflate_PushLit(state, 256)state->Bits |= (state->LitsCodewords[256]) << state
->NumBits; state->NumBits += (state->LitsLens[256]);
;
970 Deflate_FlushBits(state)while (state->NumBits >= 8) { *state->NextOut++ = state
->Bits; state->AvailOut--; state->Bits >>= 8; state
->NumBits -= 8;; }
;
971
972 /* In case last byte still has a few extra bits */
973 if (state->NumBits) {
974 while (state->NumBits < 8) { Deflate_PushBits(state, 0, 1)state->Bits |= (0) << state->NumBits; state->NumBits
+= (1);
; }
975 Deflate_FlushBits(state)while (state->NumBits >= 8) { *state->NextOut++ = state
->Bits; state->AvailOut--; state->Bits >>= 8; state
->NumBits -= 8;; }
;
976 }
977
978 return Stream_Write(state->Dest, state->Output, DEFLATE_OUT_SIZE8192 - state->AvailOut);
979}
980
981/* Constructs a huffman encoding table (for values to codewords) */
982static void Deflate_BuildTable(const cc_uint8* lens, int count, cc_uint16* codewords, cc_uint8* bitlens) {
983 int i, j, offset, codeword;
984 struct HuffmanTable table;
985
986 Huffman_Build(&table, lens, count);
987 for (i = 0; i < INFLATE_MAX_BITS16; i++) {
988 if (!table.EndCodewords[i]) continue;
989 count = table.EndCodewords[i] - table.FirstCodewords[i];
990
991 for (j = 0; j < count; j++) {
992 offset = table.Values[table.FirstOffsets[i] + j];
993 codeword = table.FirstCodewords[i] + j;
994 bitlens[offset] = i;
995 codewords[offset] = Huffman_ReverseBits(codeword, i);
996 }
997 }
998}
999
1000void Deflate_MakeStream(struct Stream* stream, struct DeflateState* state, struct Stream* underlying) {
1001 Stream_Init(stream);
1002 stream->Meta.Inflate = state;
1003 stream->Write = Deflate_StreamWrite;
1004 stream->Close = Deflate_StreamClose;
1005
1006 /* First half of buffer is "previous block" */
1007 state->InputPosition = DEFLATE_BLOCK_SIZE16384;
1008 state->Bits = 0;
1009 state->NumBits = 0;
1010
1011 state->NextOut = state->Output;
1012 state->AvailOut = DEFLATE_OUT_SIZE8192;
1013 state->Dest = underlying;
1014 state->WroteHeader = false0;
1015
1016 Mem_Set(state->Head, 0, sizeof(state->Head));
1017 Mem_Set(state->Prev, 0, sizeof(state->Prev));
1018 Deflate_BuildTable(fixed_lits, INFLATE_MAX_LITS288, state->LitsCodewords, state->LitsLens);
1019}
1020
1021
1022/*########################################################################################################################*
1023*-----------------------------------------------------GZip (compress)-----------------------------------------------------*
1024*#########################################################################################################################*/
1025static cc_result GZip_StreamClose(struct Stream* stream) {
1026 struct GZipState* state = (struct GZipState*)stream->Meta.Inflate;
1027 cc_uint8 data[8];
1028 cc_result res;
1029
1030 if ((res = Deflate_StreamClose(stream))) return res;
1031 Stream_SetU32_LE(&data[0], state->Crc32 ^ 0xFFFFFFFFUL);
1032 Stream_SetU32_LE(&data[4], state->Size);
1033 return Stream_Write(state->Base.Dest, data, sizeof(data));
1034}
1035
1036static cc_result GZip_StreamWrite(struct Stream* stream, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
1037 struct GZipState* state = (struct GZipState*)stream->Meta.Inflate;
1038 cc_uint32 i, crc32 = state->Crc32;
1039 state->Size += count;
1040
1041 /* TODO: Optimise this calculation */
1042 for (i = 0; i < count; i++) {
1043 crc32 = Utils_Crc32Table[(crc32 ^ data[i]) & 0xFF] ^ (crc32 >> 8);
1044 }
1045
1046 state->Crc32 = crc32;
1047 return Deflate_StreamWrite(stream, data, count, modified);
1048}
1049
1050static cc_result GZip_StreamWriteFirst(struct Stream* stream, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
1051 static cc_uint8 header[10] = { 0x1F, 0x8B, 0x08 }; /* GZip header */
1052 struct GZipState* state = (struct GZipState*)stream->Meta.Inflate;
1053 cc_result res;
1054
1055 if ((res = Stream_Write(state->Base.Dest, header, sizeof(header)))) return res;
1056 stream->Write = GZip_StreamWrite;
1057 return GZip_StreamWrite(stream, data, count, modified);
1058}
1059
1060void GZip_MakeStream(struct Stream* stream, struct GZipState* state, struct Stream* underlying) {
1061 Deflate_MakeStream(stream, &state->Base, underlying);
1062 state->Crc32 = 0xFFFFFFFFUL;
1063 state->Size = 0;
1064 stream->Write = GZip_StreamWriteFirst;
1065 stream->Close = GZip_StreamClose;
1066}
1067
1068
1069/*########################################################################################################################*
1070*-----------------------------------------------------ZLib (compress)-----------------------------------------------------*
1071*#########################################################################################################################*/
1072static cc_result ZLib_StreamClose(struct Stream* stream) {
1073 struct ZLibState* state = (struct ZLibState*)stream->Meta.Inflate;
1074 cc_uint8 data[4];
1075 cc_result res;
1076
1077 if ((res = Deflate_StreamClose(stream))) return res;
1078 Stream_SetU32_BE(&data[0], state->Adler32);
1079 return Stream_Write(state->Base.Dest, data, sizeof(data));
1080}
1081
1082static cc_result ZLib_StreamWrite(struct Stream* stream, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
1083 struct ZLibState* state = (struct ZLibState*)stream->Meta.Inflate;
1084 cc_uint32 i, adler32 = state->Adler32;
1085 cc_uint32 s1 = adler32 & 0xFFFF, s2 = (adler32 >> 16) & 0xFFFF;
1086
1087 /* TODO: Optimise this calculation */
1088 for (i = 0; i < count; i++) {
1089 #define ADLER32_BASE65521 65521
1090 s1 = (s1 + data[i]) % ADLER32_BASE65521;
1091 s2 = (s2 + s1) % ADLER32_BASE65521;
1092 }
1093
1094 state->Adler32 = (s2 << 16) | s1;
1095 return Deflate_StreamWrite(stream, data, count, modified);
1096}
1097
1098static cc_result ZLib_StreamWriteFirst(struct Stream* stream, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
1099 static cc_uint8 header[2] = { 0x78, 0x9C }; /* ZLib header */
1100 struct ZLibState* state = (struct ZLibState*)stream->Meta.Inflate;
1101 cc_result res;
1102
1103 if ((res = Stream_Write(state->Base.Dest, header, sizeof(header)))) return res;
1104 stream->Write = ZLib_StreamWrite;
1105 return ZLib_StreamWrite(stream, data, count, modified);
1106}
1107
1108void ZLib_MakeStream(struct Stream* stream, struct ZLibState* state, struct Stream* underlying) {
1109 Deflate_MakeStream(stream, &state->Base, underlying);
1110 state->Adler32 = 1;
1111 stream->Write = ZLib_StreamWriteFirst;
1112 stream->Close = ZLib_StreamClose;
1113}
1114
1115
1116/*########################################################################################################################*
1117*--------------------------------------------------------ZipEntry---------------------------------------------------------*
1118*#########################################################################################################################*/
1119#define ZIP_MAXNAMELEN512 512
1120static cc_result Zip_ReadLocalFileHeader(struct ZipState* state, struct ZipEntry* entry) {
1121 struct Stream* stream = state->input;
1122 cc_uint8 header[26];
1123 cc_uint32 compressedSize, uncompressedSize;
1124 int method, pathLen, extraLen;
1125
1126 cc_string path; char pathBuffer[ZIP_MAXNAMELEN512];
1127 struct Stream portion, compStream;
1128 struct InflateState inflate;
1129 cc_result res;
1130 if ((res = Stream_Read(stream, header, sizeof(header)))) return res;
1131
1132 method = Stream_GetU16_LE(&header[4]);
1133 compressedSize = Stream_GetU32_LE(&header[14]);
1134 uncompressedSize = Stream_GetU32_LE(&header[18]);
1135
1136 /* Some .zip files don't set these in local file header */
1137 if (!compressedSize) compressedSize = entry->CompressedSize;
1138 if (!uncompressedSize) uncompressedSize = entry->UncompressedSize;
1139
1140 pathLen = Stream_GetU16_LE(&header[22]);
1141 extraLen = Stream_GetU16_LE(&header[24]);
1142 if (pathLen > ZIP_MAXNAMELEN512) return ZIP_ERR_FILENAME_LEN;
1143
1144 /* NOTE: ZIP spec says path uses code page 437 for encoding */
1145 path = String_Init(pathBuffer, pathLen, pathLen);
1146 if ((res = Stream_Read(stream, (cc_uint8*)pathBuffer, pathLen))) return res;
1147 state->_curEntry = entry;
1148
1149 if (!state->SelectEntry(&path)) return 0;
1150 /* local file may have extra data before actual data (e.g. ZIP64) */
1151 if ((res = stream->Skip(stream, extraLen))) return res;
1152
1153 if (method == 0) {
1154 Stream_ReadonlyPortion(&portion, stream, uncompressedSize);
1155 return state->ProcessEntry(&path, &portion, state);
1156 } else if (method == 8) {
1157 Stream_ReadonlyPortion(&portion, stream, compressedSize);
1158 Inflate_MakeStream2(&compStream, &inflate, &portion);
1159 return state->ProcessEntry(&path, &compStream, state);
1160 } else {
1161 Platform_Log1("Unsupported.zip entry compression method: %i", &method);
1162 /* TODO: Should this be an error */
1163 }
1164 return 0;
1165}
1166
1167static cc_result Zip_ReadCentralDirectory(struct ZipState* state) {
1168 struct Stream* stream = state->input;
1169 struct ZipEntry* entry;
1170 cc_uint8 header[42];
1171
1172 cc_string path; char pathBuffer[ZIP_MAXNAMELEN512];
1173 int pathLen, extraLen, commentLen;
1174 cc_result res;
1175 if ((res = Stream_Read(stream, header, sizeof(header)))) return res;
1176
1177 pathLen = Stream_GetU16_LE(&header[24]);
1178 if (pathLen > ZIP_MAXNAMELEN512) return ZIP_ERR_FILENAME_LEN;
1179
1180 /* NOTE: ZIP spec says path uses code page 437 for encoding */
1181 path = String_Init(pathBuffer, pathLen, pathLen);
1182 if ((res = Stream_Read(stream, (cc_uint8*)pathBuffer, pathLen))) return res;
1183
1184 /* skip data following central directory entry header */
1185 extraLen = Stream_GetU16_LE(&header[26]);
1186 commentLen = Stream_GetU16_LE(&header[28]);
1187 if ((res = stream->Skip(stream, extraLen + commentLen))) return res;
1188
1189 if (!state->SelectEntry(&path)) return 0;
1190 if (state->_usedEntries >= ZIP_MAX_ENTRIES1024) return ZIP_ERR_TOO_MANY_ENTRIES;
1191 entry = &state->entries[state->_usedEntries++];
1192
1193 entry->CRC32 = Stream_GetU32_LE(&header[12]);
1194 entry->CompressedSize = Stream_GetU32_LE(&header[16]);
1195 entry->UncompressedSize = Stream_GetU32_LE(&header[20]);
1196 entry->LocalHeaderOffset = Stream_GetU32_LE(&header[38]);
1197 return 0;
1198}
1199
1200static cc_result Zip_ReadEndOfCentralDirectory(struct ZipState* state) {
1201 struct Stream* stream = state->input;
1202 cc_uint8 header[18];
1203
1204 cc_result res;
1205 if ((res = Stream_Read(stream, header, sizeof(header)))) return res;
1206
1207 state->_totalEntries = Stream_GetU16_LE(&header[6]);
1208 state->_centralDirBeg = Stream_GetU32_LE(&header[12]);
1209 return 0;
1210}
1211
1212enum ZipSig {
1213 ZIP_SIG_ENDOFCENTRALDIR = 0x06054b50,
1214 ZIP_SIG_CENTRALDIR = 0x02014b50,
1215 ZIP_SIG_LOCALFILEHEADER = 0x04034b50
1216};
1217
1218static cc_result Zip_DefaultProcessor(const cc_string* path, struct Stream* data, struct ZipState* s) { return 0; }
1219static cc_bool Zip_DefaultSelector(const cc_string* path) { return true1; }
1220void Zip_Init(struct ZipState* state, struct Stream* input) {
1221 state->input = input;
1222 state->obj = NULL((void*)0);
1223 state->ProcessEntry = Zip_DefaultProcessor;
1224 state->SelectEntry = Zip_DefaultSelector;
1225}
1226
1227cc_result Zip_Extract(struct ZipState* state) {
1228 struct Stream* stream = state->input;
1229 cc_uint32 stream_len;
1230 cc_uint32 sig = 0;
1231 int i, count;
1232
1233 cc_result res;
1234 if ((res = stream->Length(stream, &stream_len))) return res;
1235
1236 /* At -22 for nearly all zips, but try a bit further back in case of comment */
1237 count = min(257, stream_len)((257) < (stream_len) ? (257) : (stream_len));
1238 for (i = 22; i < count; i++) {
1239 res = stream->Seek(stream, stream_len - i);
1240 if (res) return ZIP_ERR_SEEK_END_OF_CENTRAL_DIR;
1241
1242 if ((res = Stream_ReadU32_LE(stream, &sig))) return res;
1243 if (sig == ZIP_SIG_ENDOFCENTRALDIR) break;
1244 }
1245
1246 if (sig != ZIP_SIG_ENDOFCENTRALDIR) return ZIP_ERR_NO_END_OF_CENTRAL_DIR;
1247 res = Zip_ReadEndOfCentralDirectory(state);
1248 if (res) return res;
1249
1250 res = stream->Seek(stream, state->_centralDirBeg);
1251 if (res) return ZIP_ERR_SEEK_CENTRAL_DIR;
1252 state->_usedEntries = 0;
1253
1254 /* Read all the central directory entries */
1255 for (i = 0; i < state->_totalEntries; i++) {
1256 if ((res = Stream_ReadU32_LE(stream, &sig))) return res;
1257
1258 if (sig == ZIP_SIG_CENTRALDIR) {
1259 res = Zip_ReadCentralDirectory(state);
1260 if (res) return res;
1261 } else if (sig == ZIP_SIG_ENDOFCENTRALDIR) {
1262 break;
1263 } else {
1264 return ZIP_ERR_INVALID_CENTRAL_DIR;
1265 }
1266 }
1267
1268 /* Now read the local file header entries */
1269 for (i = 0; i < state->_usedEntries; i++) {
1270 struct ZipEntry* entry = &state->entries[i];
1271 res = stream->Seek(stream, entry->LocalHeaderOffset);
1272 if (res) return ZIP_ERR_SEEK_LOCAL_DIR;
1273
1274 if ((res = Stream_ReadU32_LE(stream, &sig))) return res;
1275 if (sig != ZIP_SIG_LOCALFILEHEADER) return ZIP_ERR_INVALID_LOCAL_DIR;
1276
1277 res = Zip_ReadLocalFileHeader(state, entry);
1278 if (res) return res;
1279 }
1280 return 0;
1281}