]>
Commit | Line | Data |
---|---|---|
224ce89b WB |
1 | /********************************************************************** |
2 | Copyright(c) 2011-2016 Intel Corporation All rights reserved. | |
3 | ||
4 | Redistribution and use in source and binary forms, with or without | |
5 | modification, are permitted provided that the following conditions | |
6 | are met: | |
7 | * Redistributions of source code must retain the above copyright | |
8 | notice, this list of conditions and the following disclaimer. | |
9 | * Redistributions in binary form must reproduce the above copyright | |
10 | notice, this list of conditions and the following disclaimer in | |
11 | the documentation and/or other materials provided with the | |
12 | distribution. | |
13 | * Neither the name of Intel Corporation nor the names of its | |
14 | contributors may be used to endorse or promote products derived | |
15 | from this software without specific prior written permission. | |
16 | ||
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
28 | **********************************************************************/ | |
29 | ||
30 | #include <stdint.h> | |
31 | #include "igzip_lib.h" | |
f91f0fd5 | 32 | #include "crc.h" |
224ce89b | 33 | #include "huff_codes.h" |
f91f0fd5 TL |
34 | #include "igzip_checksums.h" |
35 | #include "igzip_wrapper.h" | |
36 | #include "unaligned.h" | |
37 | ||
38 | #ifndef NO_STATIC_INFLATE_H | |
39 | #include "static_inflate.h" | |
40 | #endif | |
41 | ||
42 | #ifdef __FreeBSD__ | |
43 | #include <sys/types.h> | |
44 | #include <sys/endian.h> | |
45 | # define bswap_32(x) bswap32(x) | |
46 | #elif defined (__APPLE__) | |
47 | #include <libkern/OSByteOrder.h> | |
48 | # define bswap_32(x) OSSwapInt32(x) | |
49 | #elif defined (__GNUC__) && !defined (__MINGW32__) | |
50 | # include <byteswap.h> | |
51 | #elif defined _WIN64 | |
52 | # define bswap_32(x) _byteswap_ulong(x) | |
53 | #endif | |
54 | ||
55 | extern int decode_huffman_code_block_stateless(struct inflate_state *, uint8_t * start_out); | |
20effc67 | 56 | extern struct isal_hufftables hufftables_default; /* For known header detection */ |
f91f0fd5 TL |
57 | |
58 | #define LARGE_SHORT_SYM_LEN 25 | |
59 | #define LARGE_SHORT_SYM_MASK ((1 << LARGE_SHORT_SYM_LEN) - 1) | |
60 | #define LARGE_LONG_SYM_LEN 10 | |
61 | #define LARGE_LONG_SYM_MASK ((1 << LARGE_LONG_SYM_LEN) - 1) | |
62 | #define LARGE_SHORT_CODE_LEN_OFFSET 28 | |
63 | #define LARGE_LONG_CODE_LEN_OFFSET 10 | |
64 | #define LARGE_FLAG_BIT_OFFSET 25 | |
65 | #define LARGE_FLAG_BIT (1 << LARGE_FLAG_BIT_OFFSET) | |
66 | #define LARGE_SYM_COUNT_OFFSET 26 | |
67 | #define LARGE_SYM_COUNT_LEN 2 | |
68 | #define LARGE_SYM_COUNT_MASK ((1 << LARGE_SYM_COUNT_LEN) - 1) | |
69 | #define LARGE_SHORT_MAX_LEN_OFFSET 26 | |
70 | ||
71 | #define SMALL_SHORT_SYM_LEN 9 | |
72 | #define SMALL_SHORT_SYM_MASK ((1 << SMALL_SHORT_SYM_LEN) - 1) | |
73 | #define SMALL_LONG_SYM_LEN 9 | |
74 | #define SMALL_LONG_SYM_MASK ((1 << SMALL_LONG_SYM_LEN) - 1) | |
75 | #define SMALL_SHORT_CODE_LEN_OFFSET 11 | |
76 | #define SMALL_LONG_CODE_LEN_OFFSET 10 | |
77 | #define SMALL_FLAG_BIT_OFFSET 10 | |
78 | #define SMALL_FLAG_BIT (1 << SMALL_FLAG_BIT_OFFSET) | |
79 | ||
80 | #define DIST_SYM_OFFSET 0 | |
81 | #define DIST_SYM_LEN 5 | |
82 | #define DIST_SYM_MASK ((1 << DIST_SYM_LEN) - 1) | |
83 | #define DIST_SYM_EXTRA_OFFSET 5 | |
84 | #define DIST_SYM_EXTRA_LEN 4 | |
85 | #define DIST_SYM_EXTRA_MASK ((1 << DIST_SYM_EXTRA_LEN) - 1) | |
86 | ||
87 | #define MAX_LIT_LEN_CODE_LEN 21 | |
88 | #define MAX_LIT_LEN_COUNT (MAX_LIT_LEN_CODE_LEN + 2) | |
89 | #define MAX_LIT_LEN_SYM 512 | |
90 | #define LIT_LEN_ELEMS 514 | |
91 | ||
92 | #define INVALID_SYMBOL 0x1FFF | |
93 | #define INVALID_CODE 0xFFFFFF | |
94 | ||
95 | #define MIN_DEF_MATCH 3 | |
96 | ||
97 | #define TRIPLE_SYM_FLAG 0 | |
98 | #define DOUBLE_SYM_FLAG TRIPLE_SYM_FLAG + 1 | |
99 | #define SINGLE_SYM_FLAG DOUBLE_SYM_FLAG + 1 | |
100 | #define DEFAULT_SYM_FLAG TRIPLE_SYM_FLAG | |
101 | ||
102 | #define SINGLE_SYM_THRESH (2 * 1024) | |
103 | #define DOUBLE_SYM_THRESH (4 * 1024) | |
224ce89b WB |
104 | |
105 | /* structure contain lookup data based on RFC 1951 */ | |
106 | struct rfc1951_tables { | |
107 | uint8_t dist_extra_bit_count[32]; | |
108 | uint32_t dist_start[32]; | |
109 | uint8_t len_extra_bit_count[32]; | |
110 | uint16_t len_start[32]; | |
111 | ||
112 | }; | |
113 | ||
114 | /* The following tables are based on the tables in the deflate standard, | |
115 | * RFC 1951 page 11. */ | |
116 | static struct rfc1951_tables rfc_lookup_table = { | |
117 | .dist_extra_bit_count = { | |
118 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, | |
119 | 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, | |
120 | 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, | |
121 | 0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x00, 0x00}, | |
122 | ||
123 | .dist_start = { | |
124 | 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0007, 0x0009, 0x000d, | |
125 | 0x0011, 0x0019, 0x0021, 0x0031, 0x0041, 0x0061, 0x0081, 0x00c1, | |
126 | 0x0101, 0x0181, 0x0201, 0x0301, 0x0401, 0x0601, 0x0801, 0x0c01, | |
127 | 0x1001, 0x1801, 0x2001, 0x3001, 0x4001, 0x6001, 0x0000, 0x0000}, | |
128 | ||
129 | .len_extra_bit_count = { | |
130 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
131 | 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, | |
132 | 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, | |
133 | 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00}, | |
134 | ||
135 | .len_start = { | |
136 | 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, | |
137 | 0x000b, 0x000d, 0x000f, 0x0011, 0x0013, 0x0017, 0x001b, 0x001f, | |
138 | 0x0023, 0x002b, 0x0033, 0x003b, 0x0043, 0x0053, 0x0063, 0x0073, | |
f91f0fd5 | 139 | 0x0083, 0x00a3, 0x00c3, 0x00e3, 0x0102, 0x0103, 0x0000, 0x0000} |
224ce89b WB |
140 | }; |
141 | ||
142 | struct slver { | |
143 | uint16_t snum; | |
144 | uint8_t ver; | |
145 | uint8_t core; | |
146 | }; | |
147 | ||
148 | /* Version info */ | |
149 | struct slver isal_inflate_init_slver_00010088; | |
150 | struct slver isal_inflate_init_slver = { 0x0088, 0x01, 0x00 }; | |
151 | ||
f91f0fd5 TL |
152 | struct slver isal_inflate_reset_slver_0001008f; |
153 | struct slver isal_inflate_reset_slver = { 0x008f, 0x01, 0x00 }; | |
154 | ||
224ce89b WB |
155 | struct slver isal_inflate_stateless_slver_00010089; |
156 | struct slver isal_inflate_stateless_slver = { 0x0089, 0x01, 0x00 }; | |
157 | ||
158 | struct slver isal_inflate_slver_0001008a; | |
159 | struct slver isal_inflate_slver = { 0x008a, 0x01, 0x00 }; | |
160 | ||
f91f0fd5 TL |
161 | struct slver isal_inflate_set_dict_slver_0001008d; |
162 | struct slver isal_inflate_set_dict_slver = { 0x008d, 0x01, 0x00 }; | |
163 | ||
224ce89b WB |
164 | /*Performs a copy of length repeat_length data starting at dest - |
165 | * lookback_distance into dest. This copy copies data previously copied when the | |
166 | * src buffer and the dest buffer overlap. */ | |
167 | static void inline byte_copy(uint8_t * dest, uint64_t lookback_distance, int repeat_length) | |
168 | { | |
169 | uint8_t *src = dest - lookback_distance; | |
170 | ||
171 | for (; repeat_length > 0; repeat_length--) | |
172 | *dest++ = *src++; | |
173 | } | |
174 | ||
f91f0fd5 TL |
175 | static void update_checksum(struct inflate_state *state, uint8_t * start_in, uint64_t length) |
176 | { | |
177 | switch (state->crc_flag) { | |
178 | case ISAL_GZIP: | |
179 | case ISAL_GZIP_NO_HDR: | |
180 | case ISAL_GZIP_NO_HDR_VER: | |
181 | state->crc = crc32_gzip_refl(state->crc, start_in, length); | |
182 | break; | |
183 | case ISAL_ZLIB: | |
184 | case ISAL_ZLIB_NO_HDR: | |
185 | case ISAL_ZLIB_NO_HDR_VER: | |
186 | state->crc = isal_adler32_bam1(state->crc, start_in, length); | |
187 | break; | |
188 | } | |
189 | } | |
190 | ||
191 | static void finalize_adler32(struct inflate_state *state) | |
192 | { | |
193 | ||
194 | state->crc = (state->crc & 0xffff0000) | (((state->crc & 0xffff) + 1) % ADLER_MOD); | |
195 | } | |
196 | ||
197 | static const uint8_t bitrev_table[] = { | |
198 | 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, | |
199 | 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, | |
200 | 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, | |
201 | 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, | |
202 | 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, | |
203 | 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, | |
204 | 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, | |
205 | 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, | |
206 | 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, | |
207 | 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, | |
208 | 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, | |
209 | 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, | |
210 | 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, | |
211 | 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, | |
212 | 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, | |
213 | 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, | |
214 | 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, | |
215 | 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, | |
216 | 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, | |
217 | 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, | |
218 | 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, | |
219 | 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, | |
220 | 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, | |
221 | 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, | |
222 | 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, | |
223 | 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, | |
224 | 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, | |
225 | 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, | |
226 | 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, | |
227 | 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, | |
228 | 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, | |
229 | 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, | |
230 | ||
231 | }; | |
232 | ||
224ce89b WB |
233 | /* |
234 | * Returns integer with first length bits reversed and all higher bits zeroed | |
235 | */ | |
f91f0fd5 | 236 | static uint32_t inline bit_reverse2(uint16_t bits, uint8_t length) |
224ce89b | 237 | { |
f91f0fd5 TL |
238 | uint32_t bitrev; |
239 | bitrev = bitrev_table[bits >> 8]; | |
240 | bitrev |= bitrev_table[bits & 0xFF] << 8; | |
241 | ||
242 | return bitrev >> (16 - length); | |
224ce89b WB |
243 | } |
244 | ||
245 | /* Load data from the in_stream into a buffer to allow for handling unaligned data*/ | |
246 | static void inline inflate_in_load(struct inflate_state *state, int min_required) | |
247 | { | |
248 | uint64_t temp = 0; | |
249 | uint8_t new_bytes; | |
250 | ||
251 | if (state->read_in_length >= 64) | |
252 | return; | |
253 | ||
254 | if (state->avail_in >= 8) { | |
255 | /* If there is enough space to load a 64 bits, load the data and use | |
256 | * that to fill read_in */ | |
257 | new_bytes = 8 - (state->read_in_length + 7) / 8; | |
f91f0fd5 | 258 | temp = load_u64(state->next_in); |
224ce89b WB |
259 | |
260 | state->read_in |= temp << state->read_in_length; | |
261 | state->next_in += new_bytes; | |
262 | state->avail_in -= new_bytes; | |
263 | state->read_in_length += new_bytes * 8; | |
264 | ||
265 | } else { | |
266 | /* Else fill the read_in buffer 1 byte at a time */ | |
267 | while (state->read_in_length < 57 && state->avail_in > 0) { | |
268 | temp = *state->next_in; | |
269 | state->read_in |= temp << state->read_in_length; | |
270 | state->next_in++; | |
271 | state->avail_in--; | |
272 | state->read_in_length += 8; | |
273 | ||
274 | } | |
275 | } | |
276 | } | |
277 | ||
f91f0fd5 TL |
278 | static uint64_t inline inflate_in_read_bits_unsafe(struct inflate_state *state, |
279 | uint8_t bit_count) | |
224ce89b WB |
280 | { |
281 | uint64_t ret; | |
224ce89b WB |
282 | |
283 | ret = (state->read_in) & ((1 << bit_count) - 1); | |
284 | state->read_in >>= bit_count; | |
285 | state->read_in_length -= bit_count; | |
286 | ||
287 | return ret; | |
288 | } | |
289 | ||
f91f0fd5 TL |
290 | /* Returns the next bit_count bits from the in stream and shifts the stream over |
291 | * by bit-count bits */ | |
292 | static uint64_t inline inflate_in_read_bits(struct inflate_state *state, uint8_t bit_count) | |
293 | { | |
294 | /* Load inflate_in if not enough data is in the read_in buffer */ | |
295 | inflate_in_load(state, bit_count); | |
296 | return inflate_in_read_bits_unsafe(state, bit_count); | |
297 | } | |
298 | ||
299 | static void inline write_huff_code(struct huff_code *huff_code, uint32_t code, uint32_t length) | |
300 | { | |
301 | huff_code->code_and_length = code | length << 24; | |
302 | } | |
303 | ||
304 | static int inline set_codes(struct huff_code *huff_code_table, int table_length, | |
305 | uint16_t * count) | |
306 | { | |
307 | uint32_t max, code, length; | |
308 | uint32_t next_code[MAX_HUFF_TREE_DEPTH + 1]; | |
309 | int i; | |
310 | struct huff_code *table_end = huff_code_table + table_length; | |
311 | ||
312 | /* Setup for calculating huffman codes */ | |
313 | next_code[0] = 0; | |
314 | next_code[1] = 0; | |
315 | for (i = 2; i < MAX_HUFF_TREE_DEPTH + 1; i++) | |
316 | next_code[i] = (next_code[i - 1] + count[i - 1]) << 1; | |
317 | ||
318 | max = (next_code[MAX_HUFF_TREE_DEPTH] + count[MAX_HUFF_TREE_DEPTH]); | |
319 | ||
320 | if (max > (1 << MAX_HUFF_TREE_DEPTH)) | |
321 | return ISAL_INVALID_BLOCK; | |
322 | ||
323 | /* Calculate code corresponding to a given symbol */ | |
324 | for (; huff_code_table < table_end; huff_code_table++) { | |
325 | length = huff_code_table->length; | |
326 | if (length == 0) | |
327 | continue; | |
328 | ||
329 | code = bit_reverse2(next_code[length], length); | |
330 | ||
331 | write_huff_code(huff_code_table, code, length); | |
332 | next_code[length] += 1; | |
333 | } | |
334 | return 0; | |
335 | } | |
336 | ||
337 | static int inline set_and_expand_lit_len_huffcode(struct huff_code *lit_len_huff, | |
338 | uint32_t table_length, | |
339 | uint16_t * count, | |
340 | uint16_t * expand_count, | |
341 | uint32_t * code_list) | |
342 | { | |
343 | int len_sym, len_size, extra_count, extra; | |
344 | uint32_t count_total, count_tmp; | |
345 | uint32_t code, code_len, expand_len; | |
346 | struct huff_code *expand_next = &lit_len_huff[ISAL_DEF_LIT_SYMBOLS]; | |
347 | struct huff_code tmp_table[LIT_LEN - ISAL_DEF_LIT_SYMBOLS]; | |
348 | uint32_t max; | |
349 | uint32_t next_code[MAX_HUFF_TREE_DEPTH + 1]; | |
350 | int i; | |
351 | struct huff_code *table_end; | |
352 | struct huff_code *huff_code_table = lit_len_huff; | |
353 | uint32_t insert_index; | |
354 | ||
355 | /* Setup for calculating huffman codes */ | |
356 | count_total = 0; | |
357 | count_tmp = expand_count[1]; | |
358 | next_code[0] = 0; | |
359 | next_code[1] = 0; | |
360 | expand_count[0] = 0; | |
361 | expand_count[1] = 0; | |
362 | ||
363 | for (i = 1; i < MAX_HUFF_TREE_DEPTH; i++) { | |
364 | count_total = count[i] + count_tmp + count_total; | |
365 | count_tmp = expand_count[i + 1]; | |
366 | expand_count[i + 1] = count_total; | |
367 | next_code[i + 1] = (next_code[i] + count[i]) << 1; | |
368 | } | |
369 | ||
370 | count_tmp = count[i] + count_tmp; | |
371 | ||
372 | for (; i < MAX_LIT_LEN_COUNT - 1; i++) { | |
373 | count_total = count_tmp + count_total; | |
374 | count_tmp = expand_count[i + 1]; | |
375 | expand_count[i + 1] = count_total; | |
376 | } | |
377 | ||
378 | /* Correct for extra symbols used by static header */ | |
379 | if (table_length > LIT_LEN) | |
380 | count[8] -= 2; | |
381 | ||
382 | max = (next_code[MAX_HUFF_TREE_DEPTH] + count[MAX_HUFF_TREE_DEPTH]); | |
383 | ||
384 | if (max > (1 << MAX_HUFF_TREE_DEPTH)) | |
385 | return ISAL_INVALID_BLOCK; | |
386 | ||
387 | memcpy(count, expand_count, sizeof(*count) * MAX_LIT_LEN_COUNT); | |
388 | ||
389 | memcpy(tmp_table, &lit_len_huff[ISAL_DEF_LIT_SYMBOLS], | |
390 | sizeof(*lit_len_huff) * (LIT_LEN - ISAL_DEF_LIT_SYMBOLS)); | |
391 | memset(&lit_len_huff[ISAL_DEF_LIT_SYMBOLS], 0, | |
392 | sizeof(*lit_len_huff) * (LIT_LEN_ELEMS - ISAL_DEF_LIT_SYMBOLS)); | |
393 | ||
394 | /* Calculate code corresponding to a given literal symbol */ | |
395 | table_end = huff_code_table + ISAL_DEF_LIT_SYMBOLS; | |
396 | for (; huff_code_table < table_end; huff_code_table++) { | |
397 | code_len = huff_code_table->length; | |
398 | if (code_len == 0) | |
399 | continue; | |
400 | ||
401 | code = bit_reverse2(next_code[code_len], code_len); | |
402 | ||
403 | insert_index = expand_count[code_len]; | |
404 | code_list[insert_index] = huff_code_table - lit_len_huff; | |
405 | expand_count[code_len]++; | |
406 | ||
407 | write_huff_code(huff_code_table, code, code_len); | |
408 | next_code[code_len] += 1; | |
409 | } | |
410 | ||
411 | /* Calculate code corresponding to a given len symbol */ | |
412 | for (len_sym = 0; len_sym < LIT_LEN - ISAL_DEF_LIT_SYMBOLS; len_sym++) { | |
413 | extra_count = rfc_lookup_table.len_extra_bit_count[len_sym]; | |
414 | len_size = (1 << extra_count); | |
415 | ||
416 | code_len = tmp_table[len_sym].length; | |
417 | if (code_len == 0) { | |
418 | expand_next += len_size; | |
419 | continue; | |
420 | } | |
421 | ||
422 | code = bit_reverse2(next_code[code_len], code_len); | |
423 | expand_len = code_len + extra_count; | |
424 | next_code[code_len] += 1; | |
425 | insert_index = expand_count[expand_len]; | |
426 | expand_count[expand_len] += len_size; | |
427 | ||
428 | for (extra = 0; extra < len_size; extra++) { | |
429 | code_list[insert_index] = expand_next - lit_len_huff; | |
430 | write_huff_code(expand_next, code | (extra << code_len), expand_len); | |
431 | insert_index++; | |
432 | expand_next++; | |
433 | } | |
434 | } | |
435 | ||
436 | return 0; | |
437 | } | |
438 | ||
439 | static int inline index_to_sym(int index) | |
440 | { | |
441 | return (index != 513) ? index : 512; | |
442 | } | |
443 | ||
224ce89b WB |
444 | /* Sets result to the inflate_huff_code corresponding to the huffcode defined by |
445 | * the lengths in huff_code_table,where count is a histogram of the appearance | |
446 | * of each code length */ | |
f91f0fd5 TL |
447 | static void make_inflate_huff_code_lit_len(struct inflate_huff_code_large *result, |
448 | struct huff_code *huff_code_table, | |
449 | uint32_t table_length, uint16_t * count_total, | |
450 | uint32_t * code_list, uint32_t multisym) | |
224ce89b | 451 | { |
f91f0fd5 | 452 | int i, j; |
224ce89b | 453 | uint16_t code = 0; |
f91f0fd5 | 454 | uint32_t *long_code_list; |
224ce89b | 455 | uint32_t long_code_length = 0; |
f91f0fd5 | 456 | uint16_t temp_code_list[1 << (MAX_LIT_LEN_CODE_LEN - ISAL_DECODE_LONG_BITS)]; |
224ce89b WB |
457 | uint32_t temp_code_length; |
458 | uint32_t long_code_lookup_length = 0; | |
459 | uint32_t max_length; | |
460 | uint16_t first_bits; | |
461 | uint32_t code_length; | |
462 | uint16_t long_bits; | |
463 | uint16_t min_increment; | |
224ce89b | 464 | uint32_t code_list_len; |
f91f0fd5 | 465 | uint32_t last_length, min_length; |
224ce89b | 466 | uint32_t copy_size; |
f91f0fd5 TL |
467 | uint32_t *short_code_lookup = result->short_code_lookup; |
468 | int index1, index2, index3; | |
469 | int sym1, sym2, sym3, sym1_index, sym2_index, sym3_index; | |
470 | uint32_t sym1_code, sym2_code, sym3_code, sym1_len, sym2_len, sym3_len; | |
224ce89b | 471 | |
f91f0fd5 TL |
472 | uint32_t max_symbol = MAX_LIT_LEN_SYM; |
473 | ||
474 | code_list_len = count_total[MAX_LIT_LEN_COUNT - 1]; | |
224ce89b | 475 | |
224ce89b WB |
476 | if (code_list_len == 0) { |
477 | memset(result->short_code_lookup, 0, sizeof(result->short_code_lookup)); | |
478 | return; | |
479 | } | |
480 | ||
f91f0fd5 | 481 | /* Determine the length of the first code */ |
224ce89b WB |
482 | last_length = huff_code_table[code_list[0]].length; |
483 | if (last_length > ISAL_DECODE_LONG_BITS) | |
f91f0fd5 TL |
484 | last_length = ISAL_DECODE_LONG_BITS + 1; |
485 | copy_size = (1 << (last_length - 1)); | |
224ce89b WB |
486 | |
487 | /* Initialize short_code_lookup, so invalid lookups process data */ | |
488 | memset(short_code_lookup, 0x00, copy_size * sizeof(*short_code_lookup)); | |
489 | ||
f91f0fd5 TL |
490 | min_length = last_length; |
491 | for (; last_length <= ISAL_DECODE_LONG_BITS; last_length++) { | |
492 | /* Copy forward previosly set codes */ | |
493 | memcpy(short_code_lookup + copy_size, short_code_lookup, | |
494 | sizeof(*short_code_lookup) * copy_size); | |
495 | copy_size *= 2; | |
496 | ||
497 | /* Encode code singletons */ | |
498 | for (index1 = count_total[last_length]; | |
499 | index1 < count_total[last_length + 1]; index1++) { | |
500 | sym1_index = code_list[index1]; | |
501 | sym1 = index_to_sym(sym1_index); | |
502 | sym1_len = huff_code_table[sym1_index].length; | |
503 | sym1_code = huff_code_table[sym1_index].code; | |
504 | ||
505 | if (sym1 > max_symbol) | |
506 | continue; | |
507 | ||
508 | /* Set new codes */ | |
509 | short_code_lookup[sym1_code] = | |
510 | sym1 | sym1_len << LARGE_SHORT_CODE_LEN_OFFSET | | |
511 | (1 << LARGE_SYM_COUNT_OFFSET); | |
512 | } | |
513 | ||
514 | /* Continue if no pairs are possible */ | |
515 | if (multisym >= SINGLE_SYM_FLAG || last_length < 2 * min_length) | |
516 | continue; | |
517 | ||
518 | /* Encode code pairs */ | |
519 | for (index1 = count_total[min_length]; | |
520 | index1 < count_total[last_length - min_length + 1]; index1++) { | |
521 | sym1_index = code_list[index1]; | |
522 | sym1 = index_to_sym(sym1_index); | |
523 | sym1_len = huff_code_table[sym1_index].length; | |
524 | sym1_code = huff_code_table[sym1_index].code; | |
525 | ||
526 | /*Check that sym1 is a literal */ | |
527 | if (sym1 >= 256) { | |
528 | index1 = count_total[sym1_len + 1] - 1; | |
529 | continue; | |
530 | } | |
531 | ||
532 | sym2_len = last_length - sym1_len; | |
533 | for (index2 = count_total[sym2_len]; | |
534 | index2 < count_total[sym2_len + 1]; index2++) { | |
535 | sym2_index = code_list[index2]; | |
536 | sym2 = index_to_sym(sym2_index); | |
537 | ||
538 | /* Check that sym2 is an existing symbol */ | |
539 | if (sym2 > max_symbol) | |
540 | break; | |
224ce89b | 541 | |
f91f0fd5 TL |
542 | sym2_code = huff_code_table[sym2_index].code; |
543 | code = sym1_code | (sym2_code << sym1_len); | |
544 | code_length = sym1_len + sym2_len; | |
545 | short_code_lookup[code] = | |
546 | sym1 | (sym2 << 8) | | |
547 | (code_length << LARGE_SHORT_CODE_LEN_OFFSET) | |
548 | | (2 << LARGE_SYM_COUNT_OFFSET); | |
549 | } | |
224ce89b WB |
550 | } |
551 | ||
f91f0fd5 TL |
552 | /* Continue if no triples are possible */ |
553 | if (multisym >= DOUBLE_SYM_FLAG || last_length < 3 * min_length) | |
554 | continue; | |
224ce89b | 555 | |
f91f0fd5 TL |
556 | /* Encode code triples */ |
557 | for (index1 = count_total[min_length]; | |
558 | index1 < count_total[last_length - 2 * min_length + 1]; index1++) { | |
559 | sym1_index = code_list[index1]; | |
560 | sym1 = index_to_sym(sym1_index); | |
561 | sym1_len = huff_code_table[sym1_index].length; | |
562 | sym1_code = huff_code_table[sym1_index].code; | |
563 | /*Check that sym1 is a literal */ | |
564 | if (sym1 >= 256) { | |
565 | index1 = count_total[sym1_len + 1] - 1; | |
566 | continue; | |
567 | } | |
224ce89b | 568 | |
f91f0fd5 TL |
569 | if (last_length - sym1_len < 2 * min_length) |
570 | break; | |
224ce89b | 571 | |
f91f0fd5 TL |
572 | for (index2 = count_total[min_length]; |
573 | index2 < count_total[last_length - sym1_len - min_length + 1]; | |
574 | index2++) { | |
575 | sym2_index = code_list[index2]; | |
576 | sym2 = index_to_sym(sym2_index); | |
577 | sym2_len = huff_code_table[sym2_index].length; | |
578 | sym2_code = huff_code_table[sym2_index].code; | |
579 | ||
580 | /* Check that sym2 is a literal */ | |
581 | if (sym2 >= 256) { | |
582 | index2 = count_total[sym2_len + 1] - 1; | |
583 | continue; | |
584 | } | |
224ce89b | 585 | |
f91f0fd5 TL |
586 | sym3_len = last_length - sym1_len - sym2_len; |
587 | for (index3 = count_total[sym3_len]; | |
588 | index3 < count_total[sym3_len + 1]; index3++) { | |
589 | sym3_index = code_list[index3]; | |
590 | sym3 = index_to_sym(sym3_index); | |
591 | sym3_code = huff_code_table[sym3_index].code; | |
224ce89b | 592 | |
f91f0fd5 TL |
593 | /* Check that sym3 is writable existing symbol */ |
594 | if (sym3 > max_symbol - 1) | |
595 | break; | |
224ce89b | 596 | |
f91f0fd5 TL |
597 | code = sym1_code | (sym2_code << sym1_len) | |
598 | (sym3_code << (sym2_len + sym1_len)); | |
599 | code_length = sym1_len + sym2_len + sym3_len; | |
600 | short_code_lookup[code] = | |
601 | sym1 | (sym2 << 8) | sym3 << 16 | | |
602 | (code_length << LARGE_SHORT_CODE_LEN_OFFSET) | |
603 | | (3 << LARGE_SYM_COUNT_OFFSET); | |
224ce89b | 604 | |
f91f0fd5 | 605 | } |
224ce89b | 606 | |
f91f0fd5 TL |
607 | } |
608 | } | |
224ce89b | 609 | |
224ce89b WB |
610 | } |
611 | ||
f91f0fd5 TL |
612 | index1 = count_total[ISAL_DECODE_LONG_BITS + 1]; |
613 | long_code_length = code_list_len - index1; | |
614 | long_code_list = &code_list[index1]; | |
224ce89b WB |
615 | for (i = 0; i < long_code_length; i++) { |
616 | /*Set the look up table to point to a hint where the symbol can be found | |
617 | * in the list of long codes and add the current symbol to the list of | |
618 | * long codes. */ | |
f91f0fd5 | 619 | if (huff_code_table[long_code_list[i]].code_and_extra == INVALID_CODE) |
224ce89b WB |
620 | continue; |
621 | ||
622 | max_length = huff_code_table[long_code_list[i]].length; | |
623 | first_bits = | |
f91f0fd5 | 624 | huff_code_table[long_code_list[i]].code_and_extra |
224ce89b WB |
625 | & ((1 << ISAL_DECODE_LONG_BITS) - 1); |
626 | ||
627 | temp_code_list[0] = long_code_list[i]; | |
628 | temp_code_length = 1; | |
629 | ||
630 | for (j = i + 1; j < long_code_length; j++) { | |
631 | if ((huff_code_table[long_code_list[j]].code & | |
632 | ((1 << ISAL_DECODE_LONG_BITS) - 1)) == first_bits) { | |
f91f0fd5 | 633 | max_length = huff_code_table[long_code_list[j]].length; |
224ce89b WB |
634 | temp_code_list[temp_code_length] = long_code_list[j]; |
635 | temp_code_length++; | |
636 | } | |
637 | } | |
638 | ||
639 | memset(&result->long_code_lookup[long_code_lookup_length], 0x00, | |
f91f0fd5 TL |
640 | sizeof(*result->long_code_lookup) * |
641 | (1 << (max_length - ISAL_DECODE_LONG_BITS))); | |
224ce89b WB |
642 | |
643 | for (j = 0; j < temp_code_length; j++) { | |
f91f0fd5 TL |
644 | sym1_index = temp_code_list[j]; |
645 | sym1 = index_to_sym(sym1_index); | |
646 | sym1_len = huff_code_table[sym1_index].length; | |
647 | sym1_code = huff_code_table[sym1_index].code_and_extra; | |
648 | ||
649 | long_bits = sym1_code >> ISAL_DECODE_LONG_BITS; | |
650 | min_increment = 1 << (sym1_len - ISAL_DECODE_LONG_BITS); | |
651 | ||
224ce89b WB |
652 | for (; long_bits < (1 << (max_length - ISAL_DECODE_LONG_BITS)); |
653 | long_bits += min_increment) { | |
654 | result->long_code_lookup[long_code_lookup_length + long_bits] = | |
f91f0fd5 | 655 | sym1 | (sym1_len << LARGE_LONG_CODE_LEN_OFFSET); |
224ce89b | 656 | } |
f91f0fd5 TL |
657 | huff_code_table[sym1_index].code_and_extra = INVALID_CODE; |
658 | ||
224ce89b | 659 | } |
f91f0fd5 TL |
660 | result->short_code_lookup[first_bits] = long_code_lookup_length | |
661 | (max_length << LARGE_SHORT_MAX_LEN_OFFSET) | LARGE_FLAG_BIT; | |
224ce89b | 662 | long_code_lookup_length += 1 << (max_length - ISAL_DECODE_LONG_BITS); |
224ce89b WB |
663 | } |
664 | } | |
665 | ||
f91f0fd5 TL |
666 | static void inline make_inflate_huff_code_dist(struct inflate_huff_code_small *result, |
667 | struct huff_code *huff_code_table, | |
668 | uint32_t table_length, uint16_t * count, | |
669 | uint32_t max_symbol) | |
224ce89b WB |
670 | { |
671 | int i, j, k; | |
f91f0fd5 | 672 | uint32_t *long_code_list; |
224ce89b WB |
673 | uint32_t long_code_length = 0; |
674 | uint16_t temp_code_list[1 << (15 - ISAL_DECODE_SHORT_BITS)]; | |
675 | uint32_t temp_code_length; | |
676 | uint32_t long_code_lookup_length = 0; | |
677 | uint32_t max_length; | |
678 | uint16_t first_bits; | |
679 | uint32_t code_length; | |
680 | uint16_t long_bits; | |
681 | uint16_t min_increment; | |
682 | uint32_t code_list[DIST_LEN + 2]; /* The +2 is for the extra codes in the static header */ | |
683 | uint32_t code_list_len; | |
f91f0fd5 | 684 | uint32_t count_total[17], count_total_tmp[17]; |
224ce89b WB |
685 | uint32_t insert_index; |
686 | uint32_t last_length; | |
687 | uint32_t copy_size; | |
688 | uint16_t *short_code_lookup = result->short_code_lookup; | |
f91f0fd5 | 689 | uint32_t sym; |
224ce89b WB |
690 | |
691 | count_total[0] = 0; | |
692 | count_total[1] = 0; | |
693 | for (i = 2; i < 17; i++) | |
694 | count_total[i] = count_total[i - 1] + count[i - 1]; | |
f91f0fd5 | 695 | memcpy(count_total_tmp, count_total, sizeof(count_total_tmp)); |
224ce89b WB |
696 | |
697 | code_list_len = count_total[16]; | |
698 | if (code_list_len == 0) { | |
699 | memset(result->short_code_lookup, 0, sizeof(result->short_code_lookup)); | |
700 | return; | |
701 | } | |
702 | ||
703 | for (i = 0; i < table_length; i++) { | |
704 | code_length = huff_code_table[i].length; | |
f91f0fd5 TL |
705 | if (code_length == 0) |
706 | continue; | |
224ce89b | 707 | |
f91f0fd5 TL |
708 | insert_index = count_total_tmp[code_length]; |
709 | code_list[insert_index] = i; | |
710 | count_total_tmp[code_length]++; | |
711 | } | |
224ce89b WB |
712 | |
713 | last_length = huff_code_table[code_list[0]].length; | |
714 | if (last_length > ISAL_DECODE_SHORT_BITS) | |
f91f0fd5 TL |
715 | last_length = ISAL_DECODE_SHORT_BITS + 1; |
716 | copy_size = (1 << (last_length - 1)); | |
224ce89b WB |
717 | |
718 | /* Initialize short_code_lookup, so invalid lookups process data */ | |
719 | memset(short_code_lookup, 0x00, copy_size * sizeof(*short_code_lookup)); | |
720 | ||
f91f0fd5 TL |
721 | for (; last_length <= ISAL_DECODE_SHORT_BITS; last_length++) { |
722 | memcpy(short_code_lookup + copy_size, short_code_lookup, | |
723 | sizeof(*short_code_lookup) * copy_size); | |
724 | copy_size *= 2; | |
725 | ||
726 | for (k = count_total[last_length]; k < count_total[last_length + 1]; k++) { | |
727 | i = code_list[k]; | |
728 | ||
729 | if (i >= max_symbol) { | |
730 | /* If the symbol is invalid, set code to be the | |
731 | * length of the symbol and the code_length to 0 | |
732 | * to determine if there was enough input */ | |
733 | short_code_lookup[huff_code_table[i].code] = | |
734 | huff_code_table[i].length; | |
735 | continue; | |
736 | } | |
224ce89b | 737 | |
f91f0fd5 TL |
738 | /* Set lookup table to return the current symbol concatenated |
739 | * with the code length when the first DECODE_LENGTH bits of the | |
740 | * address are the same as the code for the current symbol. The | |
741 | * first 9 bits are the code, bits 14:10 are the code length, | |
742 | * bit 15 is a flag representing this is a symbol*/ | |
743 | short_code_lookup[huff_code_table[i].code] = i | | |
744 | rfc_lookup_table.dist_extra_bit_count[i] << DIST_SYM_EXTRA_OFFSET | | |
745 | (huff_code_table[i].length) << SMALL_SHORT_CODE_LEN_OFFSET; | |
224ce89b | 746 | } |
f91f0fd5 TL |
747 | } |
748 | ||
749 | k = count_total[ISAL_DECODE_SHORT_BITS + 1]; | |
750 | long_code_list = &code_list[k]; | |
751 | long_code_length = code_list_len - k; | |
752 | for (i = 0; i < long_code_length; i++) { | |
753 | /*Set the look up table to point to a hint where the symbol can be found | |
754 | * in the list of long codes and add the current symbol to the list of | |
755 | * long codes. */ | |
756 | if (huff_code_table[long_code_list[i]].code == 0xFFFF) | |
757 | continue; | |
224ce89b | 758 | |
f91f0fd5 TL |
759 | max_length = huff_code_table[long_code_list[i]].length; |
760 | first_bits = | |
761 | huff_code_table[long_code_list[i]].code | |
762 | & ((1 << ISAL_DECODE_SHORT_BITS) - 1); | |
224ce89b | 763 | |
f91f0fd5 TL |
764 | temp_code_list[0] = long_code_list[i]; |
765 | temp_code_length = 1; | |
224ce89b | 766 | |
f91f0fd5 TL |
767 | for (j = i + 1; j < long_code_length; j++) { |
768 | if ((huff_code_table[long_code_list[j]].code & | |
769 | ((1 << ISAL_DECODE_SHORT_BITS) - 1)) == first_bits) { | |
770 | max_length = huff_code_table[long_code_list[j]].length; | |
771 | temp_code_list[temp_code_length] = long_code_list[j]; | |
772 | temp_code_length++; | |
773 | } | |
774 | } | |
775 | ||
776 | memset(&result->long_code_lookup[long_code_lookup_length], 0x00, | |
777 | 2 * (1 << (max_length - ISAL_DECODE_SHORT_BITS))); | |
778 | ||
779 | for (j = 0; j < temp_code_length; j++) { | |
780 | sym = temp_code_list[j]; | |
781 | code_length = huff_code_table[sym].length; | |
782 | long_bits = huff_code_table[sym].code >> ISAL_DECODE_SHORT_BITS; | |
783 | min_increment = 1 << (code_length - ISAL_DECODE_SHORT_BITS); | |
784 | for (; long_bits < (1 << (max_length - ISAL_DECODE_SHORT_BITS)); | |
785 | long_bits += min_increment) { | |
786 | if (sym >= max_symbol) { | |
787 | /* If the symbol is invalid, set code to be the | |
788 | * length of the symbol and the code_length to 0 | |
789 | * to determine if there was enough input */ | |
790 | result->long_code_lookup[long_code_lookup_length + | |
791 | long_bits] = code_length; | |
792 | continue; | |
793 | } | |
794 | result->long_code_lookup[long_code_lookup_length + long_bits] = | |
795 | sym | | |
796 | rfc_lookup_table.dist_extra_bit_count[sym] << | |
797 | DIST_SYM_EXTRA_OFFSET | | |
798 | (code_length << SMALL_LONG_CODE_LEN_OFFSET); | |
799 | } | |
800 | huff_code_table[sym].code = 0xFFFF; | |
801 | } | |
802 | result->short_code_lookup[first_bits] = long_code_lookup_length | | |
803 | (max_length << SMALL_SHORT_CODE_LEN_OFFSET) | SMALL_FLAG_BIT; | |
804 | long_code_lookup_length += 1 << (max_length - ISAL_DECODE_SHORT_BITS); | |
805 | ||
806 | } | |
807 | } | |
808 | ||
809 | static void inline make_inflate_huff_code_header(struct inflate_huff_code_small *result, | |
810 | struct huff_code *huff_code_table, | |
811 | uint32_t table_length, uint16_t * count, | |
812 | uint32_t max_symbol) | |
813 | { | |
814 | int i, j, k; | |
815 | uint32_t *long_code_list; | |
816 | uint32_t long_code_length = 0; | |
817 | uint16_t temp_code_list[1 << (15 - ISAL_DECODE_SHORT_BITS)]; | |
818 | uint32_t temp_code_length; | |
819 | uint32_t long_code_lookup_length = 0; | |
820 | uint32_t max_length; | |
821 | uint16_t first_bits; | |
822 | uint32_t code_length; | |
823 | uint16_t long_bits; | |
824 | uint16_t min_increment; | |
825 | uint32_t code_list[DIST_LEN + 2]; /* The +2 is for the extra codes in the static header */ | |
826 | uint32_t code_list_len; | |
827 | uint32_t count_total[17], count_total_tmp[17]; | |
828 | uint32_t insert_index; | |
829 | uint32_t last_length; | |
830 | uint32_t copy_size; | |
831 | uint16_t *short_code_lookup = result->short_code_lookup; | |
832 | ||
833 | count_total[0] = 0; | |
834 | count_total[1] = 0; | |
835 | for (i = 2; i < 17; i++) | |
836 | count_total[i] = count_total[i - 1] + count[i - 1]; | |
837 | ||
838 | memcpy(count_total_tmp, count_total, sizeof(count_total_tmp)); | |
839 | ||
840 | code_list_len = count_total[16]; | |
841 | if (code_list_len == 0) { | |
842 | memset(result->short_code_lookup, 0, sizeof(result->short_code_lookup)); | |
843 | return; | |
844 | } | |
845 | ||
846 | for (i = 0; i < table_length; i++) { | |
847 | code_length = huff_code_table[i].length; | |
848 | if (code_length == 0) | |
849 | continue; | |
850 | ||
851 | insert_index = count_total_tmp[code_length]; | |
852 | code_list[insert_index] = i; | |
853 | count_total_tmp[code_length]++; | |
224ce89b WB |
854 | } |
855 | ||
f91f0fd5 TL |
856 | last_length = huff_code_table[code_list[0]].length; |
857 | if (last_length > ISAL_DECODE_SHORT_BITS) | |
858 | last_length = ISAL_DECODE_SHORT_BITS + 1; | |
859 | copy_size = (1 << (last_length - 1)); | |
860 | ||
861 | /* Initialize short_code_lookup, so invalid lookups process data */ | |
862 | memset(short_code_lookup, 0x00, copy_size * sizeof(*short_code_lookup)); | |
863 | ||
864 | for (; last_length <= ISAL_DECODE_SHORT_BITS; last_length++) { | |
224ce89b WB |
865 | memcpy(short_code_lookup + copy_size, short_code_lookup, |
866 | sizeof(*short_code_lookup) * copy_size); | |
f91f0fd5 | 867 | copy_size *= 2; |
224ce89b | 868 | |
f91f0fd5 TL |
869 | for (k = count_total[last_length]; k < count_total[last_length + 1]; k++) { |
870 | i = code_list[k]; | |
224ce89b | 871 | |
f91f0fd5 TL |
872 | if (i >= max_symbol) |
873 | continue; | |
224ce89b | 874 | |
f91f0fd5 TL |
875 | /* Set lookup table to return the current symbol concatenated |
876 | * with the code length when the first DECODE_LENGTH bits of the | |
877 | * address are the same as the code for the current symbol. The | |
878 | * first 9 bits are the code, bits 14:10 are the code length, | |
879 | * bit 15 is a flag representing this is a symbol*/ | |
880 | short_code_lookup[huff_code_table[i].code] = | |
881 | i | (huff_code_table[i].length) << SMALL_SHORT_CODE_LEN_OFFSET; | |
882 | } | |
224ce89b WB |
883 | } |
884 | ||
f91f0fd5 TL |
885 | k = count_total[ISAL_DECODE_SHORT_BITS + 1]; |
886 | long_code_list = &code_list[k]; | |
887 | long_code_length = code_list_len - k; | |
224ce89b WB |
888 | for (i = 0; i < long_code_length; i++) { |
889 | /*Set the look up table to point to a hint where the symbol can be found | |
890 | * in the list of long codes and add the current symbol to the list of | |
891 | * long codes. */ | |
892 | if (huff_code_table[long_code_list[i]].code == 0xFFFF) | |
893 | continue; | |
894 | ||
895 | max_length = huff_code_table[long_code_list[i]].length; | |
896 | first_bits = | |
897 | huff_code_table[long_code_list[i]].code | |
898 | & ((1 << ISAL_DECODE_SHORT_BITS) - 1); | |
899 | ||
900 | temp_code_list[0] = long_code_list[i]; | |
901 | temp_code_length = 1; | |
902 | ||
903 | for (j = i + 1; j < long_code_length; j++) { | |
904 | if ((huff_code_table[long_code_list[j]].code & | |
905 | ((1 << ISAL_DECODE_SHORT_BITS) - 1)) == first_bits) { | |
906 | if (max_length < huff_code_table[long_code_list[j]].length) | |
907 | max_length = huff_code_table[long_code_list[j]].length; | |
908 | temp_code_list[temp_code_length] = long_code_list[j]; | |
909 | temp_code_length++; | |
910 | } | |
911 | } | |
912 | ||
913 | memset(&result->long_code_lookup[long_code_lookup_length], 0x00, | |
914 | 2 * (1 << (max_length - ISAL_DECODE_SHORT_BITS))); | |
915 | ||
916 | for (j = 0; j < temp_code_length; j++) { | |
917 | code_length = huff_code_table[temp_code_list[j]].length; | |
918 | long_bits = | |
919 | huff_code_table[temp_code_list[j]].code >> ISAL_DECODE_SHORT_BITS; | |
920 | min_increment = 1 << (code_length - ISAL_DECODE_SHORT_BITS); | |
921 | for (; long_bits < (1 << (max_length - ISAL_DECODE_SHORT_BITS)); | |
922 | long_bits += min_increment) { | |
923 | result->long_code_lookup[long_code_lookup_length + long_bits] = | |
f91f0fd5 TL |
924 | temp_code_list[j] | |
925 | (code_length << SMALL_LONG_CODE_LEN_OFFSET); | |
224ce89b WB |
926 | } |
927 | huff_code_table[temp_code_list[j]].code = 0xFFFF; | |
928 | } | |
f91f0fd5 TL |
929 | result->short_code_lookup[first_bits] = long_code_lookup_length | |
930 | (max_length << SMALL_SHORT_CODE_LEN_OFFSET) | SMALL_FLAG_BIT; | |
224ce89b WB |
931 | long_code_lookup_length += 1 << (max_length - ISAL_DECODE_SHORT_BITS); |
932 | ||
933 | } | |
934 | } | |
935 | ||
20effc67 TL |
936 | static int header_matches_pregen(struct inflate_state *state) |
937 | { | |
938 | #ifndef ISAL_STATIC_INFLATE_TABLE | |
939 | return 0; | |
940 | #else | |
941 | uint8_t *in, *hdr; | |
942 | uint32_t in_end_bits, hdr_end_bits; | |
943 | uint32_t bytes_read_in, header_len, last_bits, last_bit_mask; | |
944 | uint64_t bits_read_mask; | |
945 | uint64_t hdr_stash, in_stash; | |
946 | const uint64_t bits_read_prior = 3; // Have read bfinal(1) and btype(2) | |
947 | ||
948 | /* Check if stashed read_in_bytes match header */ | |
949 | hdr = &(hufftables_default.deflate_hdr[0]); | |
950 | bits_read_mask = (1ull << state->read_in_length) - 1; | |
951 | hdr_stash = (load_u64(hdr) >> bits_read_prior) & bits_read_mask; | |
952 | in_stash = state->read_in & bits_read_mask; | |
953 | ||
954 | if (hdr_stash != in_stash) | |
955 | return 0; | |
956 | ||
957 | /* Check if input is byte aligned */ | |
958 | if ((state->read_in_length + bits_read_prior) % 8) | |
959 | return 0; | |
960 | ||
961 | /* Check if header bulk is the same */ | |
962 | in = state->next_in; | |
963 | bytes_read_in = (state->read_in_length + bits_read_prior) / 8; | |
964 | header_len = hufftables_default.deflate_hdr_count; | |
965 | ||
966 | if (memcmp(in, &hdr[bytes_read_in], header_len - bytes_read_in)) | |
967 | return 0; | |
968 | ||
969 | /* If there are any last/end bits to the header check them too */ | |
970 | last_bits = hufftables_default.deflate_hdr_extra_bits; | |
971 | last_bit_mask = (1 << last_bits) - 1; | |
972 | ||
973 | if (0 == last_bits) { | |
974 | state->next_in += header_len - bytes_read_in; | |
975 | state->avail_in -= header_len - bytes_read_in; | |
976 | state->read_in_length = 0; | |
977 | state->read_in = 0; | |
978 | return 1; | |
979 | } | |
980 | ||
981 | in_end_bits = in[header_len - bytes_read_in] & last_bit_mask; | |
982 | hdr_end_bits = hdr[header_len] & last_bit_mask; | |
983 | if (in_end_bits == hdr_end_bits) { | |
984 | state->next_in += header_len - bytes_read_in; | |
985 | state->avail_in -= header_len - bytes_read_in; | |
986 | state->read_in_length = 0; | |
987 | state->read_in = 0; | |
988 | inflate_in_read_bits(state, last_bits); | |
989 | return 1; | |
990 | } | |
991 | ||
992 | return 0; | |
993 | #endif // ISAL_STATIC_INFLATE_TABLE | |
994 | } | |
995 | ||
996 | static int setup_pregen_header(struct inflate_state *state) | |
997 | { | |
998 | #ifdef ISAL_STATIC_INFLATE_TABLE | |
999 | memcpy(&state->lit_huff_code, &pregen_lit_huff_code, sizeof(pregen_lit_huff_code)); | |
1000 | memcpy(&state->dist_huff_code, &pregen_dist_huff_code, sizeof(pregen_dist_huff_code)); | |
1001 | state->block_state = ISAL_BLOCK_CODED; | |
1002 | #endif // ISAL_STATIC_INFLATE_TABLE | |
1003 | return 0; | |
1004 | } | |
1005 | ||
224ce89b WB |
1006 | /* Sets the inflate_huff_codes in state to be the huffcodes corresponding to the |
1007 | * deflate static header */ | |
1008 | static int inline setup_static_header(struct inflate_state *state) | |
1009 | { | |
f91f0fd5 TL |
1010 | #ifdef ISAL_STATIC_INFLATE_TABLE |
1011 | memcpy(&state->lit_huff_code, &static_lit_huff_code, sizeof(static_lit_huff_code)); | |
1012 | memcpy(&state->dist_huff_code, &static_dist_huff_code, sizeof(static_dist_huff_code)); | |
1013 | #else | |
1014 | ||
1015 | #ifndef NO_STATIC_INFLATE_H | |
1016 | # warning "Defaulting to static inflate table fallback." | |
1017 | # warning "For best performance, run generate_static_inflate, replace static_inflate.h, and recompile" | |
1018 | #endif | |
224ce89b | 1019 | int i; |
f91f0fd5 | 1020 | struct huff_code lit_code[LIT_LEN_ELEMS]; |
224ce89b | 1021 | struct huff_code dist_code[DIST_LEN + 2]; |
f91f0fd5 | 1022 | uint32_t multisym = SINGLE_SYM_FLAG, max_dist = DIST_LEN; |
224ce89b WB |
1023 | /* These tables are based on the static huffman tree described in RFC |
1024 | * 1951 */ | |
f91f0fd5 TL |
1025 | uint16_t lit_count[MAX_LIT_LEN_COUNT] = { |
1026 | 0, 0, 0, 0, 0, 0, 0, 24, 152, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
1027 | }; | |
1028 | ||
1029 | uint16_t lit_expand_count[MAX_LIT_LEN_COUNT] = { | |
1030 | 0, 0, 0, 0, 0, 0, 0, -15, 1, 16, 32, 48, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0 | |
224ce89b WB |
1031 | }; |
1032 | uint16_t dist_count[16] = { | |
1033 | 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
1034 | }; | |
f91f0fd5 | 1035 | uint32_t code_list[LIT_LEN_ELEMS + 2]; /* The +2 is for the extra codes in the static header */ |
224ce89b WB |
1036 | /* These for loops set the code lengths for the static literal/length |
1037 | * and distance codes defined in the deflate standard RFC 1951 */ | |
1038 | for (i = 0; i < 144; i++) | |
1039 | lit_code[i].length = 8; | |
1040 | ||
1041 | for (i = 144; i < 256; i++) | |
1042 | lit_code[i].length = 9; | |
1043 | ||
1044 | for (i = 256; i < 280; i++) | |
1045 | lit_code[i].length = 7; | |
1046 | ||
1047 | for (i = 280; i < LIT_LEN + 2; i++) | |
1048 | lit_code[i].length = 8; | |
1049 | ||
1050 | for (i = 0; i < DIST_LEN + 2; i++) | |
1051 | dist_code[i].length = 5; | |
1052 | ||
f91f0fd5 TL |
1053 | set_and_expand_lit_len_huffcode(lit_code, LIT_LEN + 2, lit_count, lit_expand_count, |
1054 | code_list); | |
224ce89b | 1055 | |
f91f0fd5 TL |
1056 | set_codes(dist_code, DIST_LEN + 2, dist_count); |
1057 | ||
1058 | make_inflate_huff_code_lit_len(&state->lit_huff_code, lit_code, LIT_LEN_ELEMS, | |
1059 | lit_count, code_list, multisym); | |
1060 | ||
1061 | if (state->hist_bits && state->hist_bits < 15) | |
1062 | max_dist = 2 * state->hist_bits; | |
1063 | ||
1064 | make_inflate_huff_code_dist(&state->dist_huff_code, dist_code, DIST_LEN + 2, | |
1065 | dist_count, max_dist); | |
1066 | #endif | |
224ce89b WB |
1067 | state->block_state = ISAL_BLOCK_CODED; |
1068 | ||
1069 | return 0; | |
1070 | } | |
1071 | ||
1072 | /* Decodes the next symbol symbol in in_buffer using the huff code defined by | |
f91f0fd5 TL |
1073 | * huff_code and returns the value in next_lits and sym_count */ |
1074 | static void inline decode_next_lit_len(uint32_t * next_lits, uint32_t * sym_count, | |
1075 | struct inflate_state *state, | |
1076 | struct inflate_huff_code_large *huff_code) | |
224ce89b | 1077 | { |
f91f0fd5 TL |
1078 | uint32_t next_bits; |
1079 | uint32_t next_sym; | |
224ce89b WB |
1080 | uint32_t bit_count; |
1081 | uint32_t bit_mask; | |
1082 | ||
1083 | if (state->read_in_length <= ISAL_DEF_MAX_CODE_LEN) | |
1084 | inflate_in_load(state, 0); | |
1085 | ||
1086 | next_bits = state->read_in & ((1 << ISAL_DECODE_LONG_BITS) - 1); | |
1087 | ||
1088 | /* next_sym is a possible symbol decoded from next_bits. If bit 15 is 0, | |
1089 | * next_code is a symbol. Bits 9:0 represent the symbol, and bits 14:10 | |
1090 | * represent the length of that symbols huffman code. If next_sym is not | |
1091 | * a symbol, it provides a hint of where the large symbols containin | |
1092 | * this code are located. Note the hint is at largest the location the | |
1093 | * first actual symbol in the long code list.*/ | |
1094 | next_sym = huff_code->short_code_lookup[next_bits]; | |
1095 | ||
f91f0fd5 | 1096 | if ((next_sym & LARGE_FLAG_BIT) == 0) { |
224ce89b WB |
1097 | /* Return symbol found if next_code is a complete huffman code |
1098 | * and shift in buffer over by the length of the next_code */ | |
f91f0fd5 | 1099 | bit_count = next_sym >> LARGE_SHORT_CODE_LEN_OFFSET; |
224ce89b WB |
1100 | state->read_in >>= bit_count; |
1101 | state->read_in_length -= bit_count; | |
1102 | ||
1103 | if (bit_count == 0) | |
f91f0fd5 | 1104 | next_sym = INVALID_SYMBOL; |
224ce89b | 1105 | |
f91f0fd5 TL |
1106 | *sym_count = (next_sym >> LARGE_SYM_COUNT_OFFSET) & LARGE_SYM_COUNT_MASK; |
1107 | *next_lits = next_sym & LARGE_SHORT_SYM_MASK; | |
224ce89b WB |
1108 | |
1109 | } else { | |
f91f0fd5 | 1110 | /* If a symbol is not found, do a lookup in the long code |
224ce89b | 1111 | * list starting from the hint in next_sym */ |
f91f0fd5 | 1112 | bit_mask = next_sym >> LARGE_SHORT_MAX_LEN_OFFSET; |
224ce89b WB |
1113 | bit_mask = (1 << bit_mask) - 1; |
1114 | next_bits = state->read_in & bit_mask; | |
1115 | next_sym = | |
f91f0fd5 | 1116 | huff_code->long_code_lookup[(next_sym & LARGE_SHORT_SYM_MASK) + |
224ce89b | 1117 | (next_bits >> ISAL_DECODE_LONG_BITS)]; |
f91f0fd5 | 1118 | bit_count = next_sym >> LARGE_LONG_CODE_LEN_OFFSET; |
224ce89b WB |
1119 | state->read_in >>= bit_count; |
1120 | state->read_in_length -= bit_count; | |
1121 | ||
1122 | if (bit_count == 0) | |
f91f0fd5 | 1123 | next_sym = INVALID_SYMBOL; |
224ce89b | 1124 | |
f91f0fd5 TL |
1125 | *sym_count = 1; |
1126 | *next_lits = next_sym & LARGE_LONG_SYM_MASK; | |
224ce89b WB |
1127 | } |
1128 | } | |
1129 | ||
f91f0fd5 TL |
1130 | static uint16_t inline decode_next_dist(struct inflate_state *state, |
1131 | struct inflate_huff_code_small *huff_code) | |
224ce89b WB |
1132 | { |
1133 | uint16_t next_bits; | |
1134 | uint16_t next_sym; | |
1135 | uint32_t bit_count; | |
1136 | uint32_t bit_mask; | |
1137 | ||
1138 | if (state->read_in_length <= ISAL_DEF_MAX_CODE_LEN) | |
1139 | inflate_in_load(state, 0); | |
1140 | ||
1141 | next_bits = state->read_in & ((1 << ISAL_DECODE_SHORT_BITS) - 1); | |
1142 | ||
1143 | /* next_sym is a possible symbol decoded from next_bits. If bit 15 is 0, | |
1144 | * next_code is a symbol. Bits 9:0 represent the symbol, and bits 14:10 | |
1145 | * represent the length of that symbols huffman code. If next_sym is not | |
1146 | * a symbol, it provides a hint of where the large symbols containin | |
1147 | * this code are located. Note the hint is at largest the location the | |
1148 | * first actual symbol in the long code list.*/ | |
1149 | next_sym = huff_code->short_code_lookup[next_bits]; | |
1150 | ||
f91f0fd5 | 1151 | if ((next_sym & SMALL_FLAG_BIT) == 0) { |
224ce89b WB |
1152 | /* Return symbol found if next_code is a complete huffman code |
1153 | * and shift in buffer over by the length of the next_code */ | |
f91f0fd5 | 1154 | bit_count = next_sym >> SMALL_SHORT_CODE_LEN_OFFSET; |
224ce89b WB |
1155 | state->read_in >>= bit_count; |
1156 | state->read_in_length -= bit_count; | |
1157 | ||
f91f0fd5 TL |
1158 | if (bit_count == 0) { |
1159 | state->read_in_length -= next_sym; | |
1160 | next_sym = INVALID_SYMBOL; | |
1161 | } | |
224ce89b | 1162 | |
f91f0fd5 | 1163 | return next_sym & DIST_SYM_MASK; |
224ce89b WB |
1164 | |
1165 | } else { | |
1166 | /* If a symbol is not found, perform a linear search of the long code | |
1167 | * list starting from the hint in next_sym */ | |
f91f0fd5 | 1168 | bit_mask = (next_sym - SMALL_FLAG_BIT) >> SMALL_SHORT_CODE_LEN_OFFSET; |
224ce89b WB |
1169 | bit_mask = (1 << bit_mask) - 1; |
1170 | next_bits = state->read_in & bit_mask; | |
1171 | next_sym = | |
f91f0fd5 | 1172 | huff_code->long_code_lookup[(next_sym & SMALL_SHORT_SYM_MASK) + |
224ce89b | 1173 | (next_bits >> ISAL_DECODE_SHORT_BITS)]; |
f91f0fd5 | 1174 | bit_count = next_sym >> SMALL_LONG_CODE_LEN_OFFSET; |
224ce89b WB |
1175 | state->read_in >>= bit_count; |
1176 | state->read_in_length -= bit_count; | |
224ce89b | 1177 | |
f91f0fd5 TL |
1178 | if (bit_count == 0) { |
1179 | state->read_in_length -= next_sym; | |
1180 | next_sym = INVALID_SYMBOL; | |
1181 | } | |
1182 | ||
1183 | return next_sym & DIST_SYM_MASK; | |
224ce89b WB |
1184 | } |
1185 | } | |
1186 | ||
f91f0fd5 TL |
1187 | static uint16_t inline decode_next_header(struct inflate_state *state, |
1188 | struct inflate_huff_code_small *huff_code) | |
224ce89b | 1189 | { |
f91f0fd5 TL |
1190 | uint16_t next_bits; |
1191 | uint16_t next_sym; | |
1192 | uint32_t bit_count; | |
1193 | uint32_t bit_mask; | |
224ce89b | 1194 | |
f91f0fd5 TL |
1195 | if (state->read_in_length <= ISAL_DEF_MAX_CODE_LEN) |
1196 | inflate_in_load(state, 0); | |
1197 | ||
1198 | next_bits = state->read_in & ((1 << ISAL_DECODE_SHORT_BITS) - 1); | |
1199 | ||
1200 | /* next_sym is a possible symbol decoded from next_bits. If bit 15 is 0, | |
1201 | * next_code is a symbol. Bits 9:0 represent the symbol, and bits 14:10 | |
1202 | * represent the length of that symbols huffman code. If next_sym is not | |
1203 | * a symbol, it provides a hint of where the large symbols containin | |
1204 | * this code are located. Note the hint is at largest the location the | |
1205 | * first actual symbol in the long code list.*/ | |
1206 | next_sym = huff_code->short_code_lookup[next_bits]; | |
1207 | ||
1208 | if ((next_sym & SMALL_FLAG_BIT) == 0) { | |
1209 | /* Return symbol found if next_code is a complete huffman code | |
1210 | * and shift in buffer over by the length of the next_code */ | |
1211 | bit_count = next_sym >> SMALL_SHORT_CODE_LEN_OFFSET; | |
1212 | state->read_in >>= bit_count; | |
1213 | state->read_in_length -= bit_count; | |
1214 | ||
1215 | if (bit_count == 0) | |
1216 | next_sym = INVALID_SYMBOL; | |
1217 | ||
1218 | return next_sym & SMALL_SHORT_SYM_MASK; | |
1219 | ||
1220 | } else { | |
1221 | /* If a symbol is not found, perform a linear search of the long code | |
1222 | * list starting from the hint in next_sym */ | |
1223 | bit_mask = (next_sym - SMALL_FLAG_BIT) >> SMALL_SHORT_CODE_LEN_OFFSET; | |
1224 | bit_mask = (1 << bit_mask) - 1; | |
1225 | next_bits = state->read_in & bit_mask; | |
1226 | next_sym = | |
1227 | huff_code->long_code_lookup[(next_sym & SMALL_SHORT_SYM_MASK) + | |
1228 | (next_bits >> ISAL_DECODE_SHORT_BITS)]; | |
1229 | bit_count = next_sym >> SMALL_LONG_CODE_LEN_OFFSET; | |
1230 | state->read_in >>= bit_count; | |
1231 | state->read_in_length -= bit_count; | |
1232 | return next_sym & SMALL_LONG_SYM_MASK; | |
1233 | ||
1234 | } | |
1235 | } | |
1236 | ||
1237 | /* Reads data from the in_buffer and sets the huff code corresponding to that | |
1238 | * data */ | |
1239 | static int inline setup_dynamic_header(struct inflate_state *state) | |
1240 | { | |
1241 | int i, j; | |
1242 | struct huff_code code_huff[CODE_LEN_CODES]; | |
1243 | struct huff_code lit_and_dist_huff[LIT_LEN_ELEMS]; | |
1244 | struct huff_code *previous = NULL, *current, *end, rep_code; | |
1245 | struct inflate_huff_code_small inflate_code_huff; | |
1246 | uint64_t hclen, hdist, hlit; | |
1247 | uint16_t code_count[16], lit_count[MAX_LIT_LEN_COUNT], | |
1248 | lit_expand_count[MAX_LIT_LEN_COUNT], dist_count[16]; | |
1249 | uint16_t *count; | |
1250 | uint16_t symbol; | |
1251 | uint32_t multisym = DEFAULT_SYM_FLAG, length, max_dist = DIST_LEN; | |
1252 | struct huff_code *code; | |
1253 | uint64_t flag = 0; | |
1254 | ||
1255 | int extra_count; | |
1256 | uint32_t code_list[LIT_LEN_ELEMS + 2]; /* The +2 is for the extra codes in the static header */ | |
1257 | ||
1258 | /* This order is defined in RFC 1951 page 13 */ | |
1259 | const uint8_t code_length_order[CODE_LEN_CODES] = { | |
224ce89b | 1260 | 0x10, 0x11, 0x12, 0x00, 0x08, 0x07, 0x09, 0x06, |
f91f0fd5 | 1261 | 0x0a, 0x05, 0x0b, 0x04, 0x0c, 0x03, 0x0d, 0x02, 0x0e, 0x01, 0x0f |
224ce89b WB |
1262 | }; |
1263 | ||
20effc67 TL |
1264 | /* If you are given a whole header and it matches the pregen header */ |
1265 | if (state->avail_in > (hufftables_default.deflate_hdr_count + sizeof(uint64_t)) | |
1266 | && header_matches_pregen(state)) | |
1267 | return setup_pregen_header(state); | |
1268 | ||
f91f0fd5 TL |
1269 | if (state->bfinal && state->avail_in <= SINGLE_SYM_THRESH) { |
1270 | multisym = SINGLE_SYM_FLAG; | |
1271 | } else if (state->bfinal && state->avail_in <= DOUBLE_SYM_THRESH) { | |
1272 | multisym = DOUBLE_SYM_FLAG; | |
1273 | } | |
1274 | ||
224ce89b WB |
1275 | memset(code_count, 0, sizeof(code_count)); |
1276 | memset(lit_count, 0, sizeof(lit_count)); | |
f91f0fd5 | 1277 | memset(lit_expand_count, 0, sizeof(lit_expand_count)); |
224ce89b WB |
1278 | memset(dist_count, 0, sizeof(dist_count)); |
1279 | memset(code_huff, 0, sizeof(code_huff)); | |
1280 | memset(lit_and_dist_huff, 0, sizeof(lit_and_dist_huff)); | |
1281 | ||
1282 | /* These variables are defined in the deflate standard, RFC 1951 */ | |
f91f0fd5 TL |
1283 | inflate_in_load(state, 0); |
1284 | if (state->read_in_length < 14) | |
1285 | return ISAL_END_INPUT; | |
1286 | ||
1287 | hlit = inflate_in_read_bits_unsafe(state, 5); | |
1288 | hdist = inflate_in_read_bits_unsafe(state, 5); | |
1289 | hclen = inflate_in_read_bits_unsafe(state, 4); | |
224ce89b WB |
1290 | |
1291 | if (hlit > 29 || hdist > 29 || hclen > 15) | |
1292 | return ISAL_INVALID_BLOCK; | |
1293 | ||
1294 | /* Create the code huffman code for decoding the lit/len and dist huffman codes */ | |
f91f0fd5 TL |
1295 | for (i = 0; i < 4; i++) { |
1296 | code = &code_huff[code_length_order[i]]; | |
1297 | length = inflate_in_read_bits_unsafe(state, 3); | |
1298 | write_huff_code(code, 0, length); | |
1299 | code_count[length] += 1; | |
1300 | flag |= length; | |
224ce89b WB |
1301 | } |
1302 | ||
f91f0fd5 TL |
1303 | inflate_in_load(state, 0); |
1304 | ||
1305 | for (i = 4; i < hclen + 4; i++) { | |
1306 | code = &code_huff[code_length_order[i]]; | |
1307 | length = inflate_in_read_bits_unsafe(state, 3); | |
1308 | write_huff_code(code, 0, length); | |
1309 | code_count[length] += 1; | |
1310 | flag |= length; | |
224ce89b WB |
1311 | } |
1312 | ||
1313 | if (state->read_in_length < 0) | |
1314 | return ISAL_END_INPUT; | |
1315 | ||
f91f0fd5 | 1316 | if (!flag || set_codes(code_huff, CODE_LEN_CODES, code_count)) |
224ce89b WB |
1317 | return ISAL_INVALID_BLOCK; |
1318 | ||
f91f0fd5 TL |
1319 | make_inflate_huff_code_header(&inflate_code_huff, code_huff, CODE_LEN_CODES, |
1320 | code_count, CODE_LEN_CODES); | |
224ce89b WB |
1321 | |
1322 | /* Decode the lit/len and dist huffman codes using the code huffman code */ | |
1323 | count = lit_count; | |
1324 | current = lit_and_dist_huff; | |
1325 | end = lit_and_dist_huff + LIT_LEN + hdist + 1; | |
1326 | ||
1327 | while (current < end) { | |
f91f0fd5 | 1328 | symbol = decode_next_header(state, &inflate_code_huff); |
224ce89b WB |
1329 | |
1330 | if (state->read_in_length < 0) { | |
1331 | if (current > &lit_and_dist_huff[256] | |
1332 | && lit_and_dist_huff[256].length <= 0) | |
1333 | return ISAL_INVALID_BLOCK; | |
1334 | return ISAL_END_INPUT; | |
1335 | } | |
1336 | ||
1337 | if (symbol < 16) { | |
1338 | /* If a length is found, update the current lit/len/dist | |
1339 | * to have length symbol */ | |
f91f0fd5 TL |
1340 | if (current == lit_and_dist_huff + LIT_TABLE_SIZE + hlit) { |
1341 | /* Switch code upon completion of lit_len table */ | |
1342 | current = lit_and_dist_huff + LIT_LEN; | |
1343 | count = dist_count; | |
1344 | } | |
224ce89b | 1345 | count[symbol]++; |
f91f0fd5 | 1346 | write_huff_code(current, 0, symbol); |
224ce89b WB |
1347 | previous = current; |
1348 | current++; | |
1349 | ||
f91f0fd5 TL |
1350 | if (symbol == 0 // No symbol |
1351 | || (previous >= lit_and_dist_huff + LIT_TABLE_SIZE + hlit) // Dist table | |
1352 | || (previous < lit_and_dist_huff + 264)) // Lit/Len with no extra bits | |
1353 | continue; | |
1354 | ||
1355 | extra_count = | |
1356 | rfc_lookup_table.len_extra_bit_count[previous - LIT_TABLE_SIZE - | |
1357 | lit_and_dist_huff]; | |
1358 | lit_expand_count[symbol]--; | |
1359 | lit_expand_count[symbol + extra_count] += (1 << extra_count); | |
1360 | ||
224ce89b WB |
1361 | } else if (symbol == 16) { |
1362 | /* If a repeat length is found, update the next repeat | |
1363 | * length lit/len/dist elements to have the value of the | |
1364 | * repeated length */ | |
224ce89b WB |
1365 | |
1366 | i = 3 + inflate_in_read_bits(state, 2); | |
1367 | ||
f91f0fd5 | 1368 | if (current + i > end || previous == NULL) |
224ce89b WB |
1369 | return ISAL_INVALID_BLOCK; |
1370 | ||
f91f0fd5 | 1371 | rep_code = *previous; |
224ce89b | 1372 | for (j = 0; j < i; j++) { |
f91f0fd5 TL |
1373 | if (current == lit_and_dist_huff + LIT_TABLE_SIZE + hlit) { |
1374 | /* Switch code upon completion of lit_len table */ | |
224ce89b WB |
1375 | current = lit_and_dist_huff + LIT_LEN; |
1376 | count = dist_count; | |
f91f0fd5 | 1377 | } |
224ce89b | 1378 | |
f91f0fd5 TL |
1379 | *current = rep_code; |
1380 | count[rep_code.length]++; | |
1381 | previous = current; | |
1382 | current++; | |
1383 | ||
1384 | if (rep_code.length == 0 // No symbol | |
1385 | || (previous >= lit_and_dist_huff + LIT_TABLE_SIZE + hlit) // Dist table | |
1386 | || (previous < lit_and_dist_huff + 264)) // Lit/Len with no extra | |
1387 | continue; | |
1388 | ||
1389 | extra_count = | |
1390 | rfc_lookup_table.len_extra_bit_count | |
1391 | [previous - lit_and_dist_huff - LIT_TABLE_SIZE]; | |
1392 | lit_expand_count[rep_code.length]--; | |
1393 | lit_expand_count[rep_code.length + | |
1394 | extra_count] += (1 << extra_count); | |
224ce89b | 1395 | |
f91f0fd5 | 1396 | } |
224ce89b WB |
1397 | } else if (symbol == 17) { |
1398 | /* If a repeat zeroes if found, update then next | |
1399 | * repeated zeroes length lit/len/dist elements to have | |
1400 | * length 0. */ | |
1401 | i = 3 + inflate_in_read_bits(state, 3); | |
1402 | ||
f91f0fd5 TL |
1403 | current = current + i; |
1404 | previous = current - 1; | |
224ce89b | 1405 | |
f91f0fd5 TL |
1406 | if (count != dist_count |
1407 | && current > lit_and_dist_huff + LIT_TABLE_SIZE + hlit) { | |
1408 | /* Switch code upon completion of lit_len table */ | |
1409 | current += LIT_LEN - LIT_TABLE_SIZE - hlit; | |
1410 | count = dist_count; | |
1411 | if (current > lit_and_dist_huff + LIT_LEN) | |
1412 | previous = current - 1; | |
224ce89b WB |
1413 | } |
1414 | ||
1415 | } else if (symbol == 18) { | |
1416 | /* If a repeat zeroes if found, update then next | |
1417 | * repeated zeroes length lit/len/dist elements to have | |
1418 | * length 0. */ | |
1419 | i = 11 + inflate_in_read_bits(state, 7); | |
1420 | ||
f91f0fd5 TL |
1421 | current = current + i; |
1422 | previous = current - 1; | |
224ce89b | 1423 | |
f91f0fd5 TL |
1424 | if (count != dist_count |
1425 | && current > lit_and_dist_huff + LIT_TABLE_SIZE + hlit) { | |
1426 | /* Switch code upon completion of lit_len table */ | |
1427 | current += LIT_LEN - LIT_TABLE_SIZE - hlit; | |
1428 | count = dist_count; | |
1429 | if (current > lit_and_dist_huff + LIT_LEN) | |
1430 | previous = current - 1; | |
224ce89b | 1431 | } |
f91f0fd5 | 1432 | |
224ce89b WB |
1433 | } else |
1434 | return ISAL_INVALID_BLOCK; | |
1435 | ||
1436 | } | |
1437 | ||
1438 | if (current > end || lit_and_dist_huff[256].length <= 0) | |
1439 | return ISAL_INVALID_BLOCK; | |
1440 | ||
1441 | if (state->read_in_length < 0) | |
1442 | return ISAL_END_INPUT; | |
1443 | ||
f91f0fd5 TL |
1444 | if (set_codes(&lit_and_dist_huff[LIT_LEN], DIST_LEN, dist_count)) |
1445 | return ISAL_INVALID_BLOCK; | |
1446 | ||
1447 | if (state->hist_bits && state->hist_bits < 15) | |
1448 | max_dist = 2 * state->hist_bits; | |
1449 | ||
1450 | make_inflate_huff_code_dist(&state->dist_huff_code, &lit_and_dist_huff[LIT_LEN], | |
1451 | DIST_LEN, dist_count, max_dist); | |
1452 | ||
1453 | if (set_and_expand_lit_len_huffcode | |
1454 | (lit_and_dist_huff, LIT_LEN, lit_count, lit_expand_count, code_list)) | |
1455 | return ISAL_INVALID_BLOCK; | |
1456 | ||
1457 | make_inflate_huff_code_lit_len(&state->lit_huff_code, lit_and_dist_huff, LIT_LEN_ELEMS, | |
1458 | lit_count, code_list, multisym); | |
224ce89b WB |
1459 | |
1460 | state->block_state = ISAL_BLOCK_CODED; | |
1461 | ||
1462 | return 0; | |
1463 | } | |
1464 | ||
1465 | /* Reads in the header pointed to by in_stream and sets up state to reflect that | |
1466 | * header information*/ | |
f91f0fd5 | 1467 | static int read_header(struct inflate_state *state) |
224ce89b WB |
1468 | { |
1469 | uint8_t bytes; | |
1470 | uint32_t btype; | |
1471 | uint16_t len, nlen; | |
1472 | int ret = 0; | |
1473 | ||
1474 | /* btype and bfinal are defined in RFC 1951, bfinal represents whether | |
1475 | * the current block is the end of block, and btype represents the | |
1476 | * encoding method on the current block. */ | |
1477 | ||
1478 | state->bfinal = inflate_in_read_bits(state, 1); | |
1479 | btype = inflate_in_read_bits(state, 2); | |
1480 | ||
1481 | if (state->read_in_length < 0) | |
1482 | ret = ISAL_END_INPUT; | |
1483 | ||
1484 | else if (btype == 0) { | |
1485 | inflate_in_load(state, 40); | |
1486 | bytes = state->read_in_length / 8; | |
1487 | ||
1488 | if (bytes < 4) | |
1489 | return ISAL_END_INPUT; | |
1490 | ||
1491 | state->read_in >>= state->read_in_length % 8; | |
1492 | state->read_in_length = bytes * 8; | |
1493 | ||
1494 | len = state->read_in & 0xFFFF; | |
1495 | state->read_in >>= 16; | |
1496 | nlen = state->read_in & 0xFFFF; | |
1497 | state->read_in >>= 16; | |
1498 | state->read_in_length -= 32; | |
1499 | ||
224ce89b WB |
1500 | /* Check if len and nlen match */ |
1501 | if (len != (~nlen & 0xffff)) | |
1502 | return ISAL_INVALID_BLOCK; | |
1503 | ||
1504 | state->type0_block_len = len; | |
1505 | state->block_state = ISAL_BLOCK_TYPE0; | |
1506 | ||
1507 | ret = 0; | |
1508 | ||
1509 | } else if (btype == 1) | |
1510 | ret = setup_static_header(state); | |
1511 | ||
1512 | else if (btype == 2) | |
1513 | ret = setup_dynamic_header(state); | |
1514 | ||
1515 | else | |
1516 | ret = ISAL_INVALID_BLOCK; | |
1517 | ||
1518 | return ret; | |
1519 | } | |
1520 | ||
1521 | /* Reads in the header pointed to by in_stream and sets up state to reflect that | |
1522 | * header information*/ | |
f91f0fd5 | 1523 | static int read_header_stateful(struct inflate_state *state) |
224ce89b WB |
1524 | { |
1525 | uint64_t read_in_start = state->read_in; | |
1526 | int32_t read_in_length_start = state->read_in_length; | |
1527 | uint8_t *next_in_start = state->next_in; | |
1528 | uint32_t avail_in_start = state->avail_in; | |
1529 | int block_state_start = state->block_state; | |
1530 | int ret; | |
1531 | int copy_size; | |
1532 | int bytes_read; | |
1533 | ||
1534 | if (block_state_start == ISAL_BLOCK_HDR) { | |
1535 | /* Setup so read_header decodes data in tmp_in_buffer */ | |
1536 | copy_size = ISAL_DEF_MAX_HDR_SIZE - state->tmp_in_size; | |
1537 | if (copy_size > state->avail_in) | |
1538 | copy_size = state->avail_in; | |
1539 | ||
1540 | memcpy(&state->tmp_in_buffer[state->tmp_in_size], state->next_in, copy_size); | |
1541 | state->next_in = state->tmp_in_buffer; | |
1542 | state->avail_in = state->tmp_in_size + copy_size; | |
1543 | } | |
1544 | ||
1545 | ret = read_header(state); | |
1546 | ||
1547 | if (block_state_start == ISAL_BLOCK_HDR) { | |
1548 | /* Setup so state is restored to a valid state */ | |
1549 | bytes_read = state->next_in - state->tmp_in_buffer - state->tmp_in_size; | |
1550 | if (bytes_read < 0) | |
1551 | bytes_read = 0; | |
1552 | state->next_in = next_in_start + bytes_read; | |
1553 | state->avail_in = avail_in_start - bytes_read; | |
1554 | } | |
1555 | ||
1556 | if (ret == ISAL_END_INPUT) { | |
1557 | /* Save off data so header can be decoded again with more data */ | |
1558 | state->read_in = read_in_start; | |
1559 | state->read_in_length = read_in_length_start; | |
1560 | memcpy(&state->tmp_in_buffer[state->tmp_in_size], next_in_start, | |
1561 | avail_in_start); | |
1562 | state->tmp_in_size += avail_in_start; | |
1563 | state->avail_in = 0; | |
1564 | state->next_in = next_in_start + avail_in_start; | |
1565 | state->block_state = ISAL_BLOCK_HDR; | |
1566 | } else | |
1567 | state->tmp_in_size = 0; | |
1568 | ||
1569 | return ret; | |
1570 | ||
1571 | } | |
1572 | ||
1573 | static int inline decode_literal_block(struct inflate_state *state) | |
1574 | { | |
1575 | uint32_t len = state->type0_block_len; | |
f91f0fd5 | 1576 | uint32_t bytes = state->read_in_length / 8; |
224ce89b WB |
1577 | /* If the block is uncompressed, perform a memcopy while |
1578 | * updating state data */ | |
f91f0fd5 | 1579 | state->block_state = state->bfinal ? ISAL_BLOCK_INPUT_DONE : ISAL_BLOCK_NEW_HDR; |
224ce89b WB |
1580 | |
1581 | if (state->avail_out < len) { | |
1582 | len = state->avail_out; | |
1583 | state->block_state = ISAL_BLOCK_TYPE0; | |
1584 | } | |
1585 | ||
f91f0fd5 TL |
1586 | if (state->avail_in + bytes < len) { |
1587 | len = state->avail_in + bytes; | |
224ce89b WB |
1588 | state->block_state = ISAL_BLOCK_TYPE0; |
1589 | } | |
f91f0fd5 TL |
1590 | if (state->read_in_length) { |
1591 | if (len >= bytes) { | |
1592 | memcpy(state->next_out, &state->read_in, bytes); | |
1593 | ||
1594 | state->next_out += bytes; | |
1595 | state->avail_out -= bytes; | |
1596 | state->total_out += bytes; | |
1597 | state->type0_block_len -= bytes; | |
1598 | ||
1599 | state->read_in = 0; | |
1600 | state->read_in_length = 0; | |
1601 | len -= bytes; | |
1602 | bytes = 0; | |
1603 | ||
1604 | } else { | |
1605 | memcpy(state->next_out, &state->read_in, len); | |
1606 | ||
1607 | state->next_out += len; | |
1608 | state->avail_out -= len; | |
1609 | state->total_out += len; | |
1610 | state->type0_block_len -= len; | |
1611 | ||
1612 | state->read_in >>= 8 * len; | |
1613 | state->read_in_length -= 8 * len; | |
1614 | bytes -= len; | |
1615 | len = 0; | |
1616 | } | |
1617 | } | |
224ce89b WB |
1618 | memcpy(state->next_out, state->next_in, len); |
1619 | ||
1620 | state->next_out += len; | |
1621 | state->avail_out -= len; | |
1622 | state->total_out += len; | |
1623 | state->next_in += len; | |
1624 | state->avail_in -= len; | |
1625 | state->type0_block_len -= len; | |
1626 | ||
f91f0fd5 | 1627 | if (state->avail_in + bytes == 0 && state->block_state != ISAL_BLOCK_INPUT_DONE) |
224ce89b WB |
1628 | return ISAL_END_INPUT; |
1629 | ||
1630 | if (state->avail_out == 0 && state->type0_block_len > 0) | |
1631 | return ISAL_OUT_OVERFLOW; | |
1632 | ||
1633 | return 0; | |
1634 | ||
1635 | } | |
1636 | ||
1637 | /* Decodes the next block if it was encoded using a huffman code */ | |
f91f0fd5 | 1638 | int decode_huffman_code_block_stateless_base(struct inflate_state *state, uint8_t * start_out) |
224ce89b WB |
1639 | { |
1640 | uint16_t next_lit; | |
1641 | uint8_t next_dist; | |
1642 | uint32_t repeat_length; | |
1643 | uint32_t look_back_dist; | |
1644 | uint64_t read_in_tmp; | |
1645 | int32_t read_in_length_tmp; | |
f91f0fd5 TL |
1646 | uint8_t *next_in_tmp, *next_out_tmp; |
1647 | uint32_t avail_in_tmp, avail_out_tmp, total_out_tmp; | |
1648 | uint32_t next_lits, sym_count; | |
1649 | struct rfc1951_tables *rfc = &rfc_lookup_table; | |
224ce89b WB |
1650 | |
1651 | state->copy_overflow_length = 0; | |
1652 | state->copy_overflow_distance = 0; | |
1653 | ||
1654 | while (state->block_state == ISAL_BLOCK_CODED) { | |
1655 | /* While not at the end of block, decode the next | |
1656 | * symbol */ | |
1657 | inflate_in_load(state, 0); | |
1658 | ||
1659 | read_in_tmp = state->read_in; | |
1660 | read_in_length_tmp = state->read_in_length; | |
1661 | next_in_tmp = state->next_in; | |
1662 | avail_in_tmp = state->avail_in; | |
f91f0fd5 TL |
1663 | next_out_tmp = state->next_out; |
1664 | avail_out_tmp = state->avail_out; | |
1665 | total_out_tmp = state->total_out; | |
224ce89b | 1666 | |
f91f0fd5 TL |
1667 | decode_next_lit_len(&next_lits, &sym_count, state, &state->lit_huff_code); |
1668 | ||
1669 | if (sym_count == 0) | |
1670 | return ISAL_INVALID_SYMBOL; | |
224ce89b WB |
1671 | |
1672 | if (state->read_in_length < 0) { | |
1673 | state->read_in = read_in_tmp; | |
1674 | state->read_in_length = read_in_length_tmp; | |
1675 | state->next_in = next_in_tmp; | |
1676 | state->avail_in = avail_in_tmp; | |
1677 | return ISAL_END_INPUT; | |
1678 | } | |
1679 | ||
f91f0fd5 TL |
1680 | while (sym_count > 0) { |
1681 | next_lit = next_lits & 0xffff; | |
1682 | if (next_lit < 256 || sym_count > 1) { | |
1683 | /* If the next symbol is a literal, | |
1684 | * write out the symbol and update state | |
1685 | * data accordingly. */ | |
1686 | if (state->avail_out < 1) { | |
1687 | state->write_overflow_lits = next_lits; | |
1688 | state->write_overflow_len = sym_count; | |
1689 | next_lits = next_lits >> (8 * (sym_count - 1)); | |
1690 | sym_count = 1; | |
1691 | ||
1692 | if (next_lits < 256) | |
1693 | return ISAL_OUT_OVERFLOW; | |
1694 | else if (next_lits == 256) { | |
1695 | state->write_overflow_len -= 1; | |
1696 | state->block_state = state->bfinal ? | |
1697 | ISAL_BLOCK_INPUT_DONE : ISAL_BLOCK_NEW_HDR; | |
1698 | return ISAL_OUT_OVERFLOW; | |
1699 | } else { | |
1700 | state->write_overflow_len -= 1; | |
1701 | continue; | |
1702 | } | |
1703 | } | |
224ce89b | 1704 | |
f91f0fd5 TL |
1705 | *state->next_out = next_lit; |
1706 | state->next_out++; | |
1707 | state->avail_out--; | |
1708 | state->total_out++; | |
1709 | ||
1710 | } else if (next_lit == 256) { | |
1711 | /* If the next symbol is the end of | |
1712 | * block, update the state data | |
1713 | * accordingly */ | |
1714 | state->block_state = state->bfinal ? | |
1715 | ISAL_BLOCK_INPUT_DONE : ISAL_BLOCK_NEW_HDR; | |
1716 | ||
1717 | } else if (next_lit <= MAX_LIT_LEN_SYM) { | |
1718 | /* Else if the next symbol is a repeat | |
1719 | * length, read in the length extra | |
1720 | * bits, the distance code, the distance | |
1721 | * extra bits. Then write out the | |
1722 | * corresponding data and update the | |
1723 | * state data accordingly*/ | |
1724 | repeat_length = next_lit - 254; | |
1725 | next_dist = decode_next_dist(state, &state->dist_huff_code); | |
1726 | ||
1727 | if (state->read_in_length >= 0) { | |
1728 | if (next_dist >= DIST_LEN) | |
1729 | return ISAL_INVALID_SYMBOL; | |
1730 | ||
1731 | look_back_dist = rfc->dist_start[next_dist] + | |
1732 | inflate_in_read_bits(state, | |
1733 | rfc->dist_extra_bit_count | |
1734 | [next_dist]); | |
1735 | } | |
224ce89b | 1736 | |
f91f0fd5 TL |
1737 | if (state->read_in_length < 0) { |
1738 | state->read_in = read_in_tmp; | |
1739 | state->read_in_length = read_in_length_tmp; | |
1740 | state->next_in = next_in_tmp; | |
1741 | state->avail_in = avail_in_tmp; | |
1742 | state->next_out = next_out_tmp; | |
1743 | state->avail_out = avail_out_tmp; | |
1744 | state->total_out = total_out_tmp; | |
1745 | state->write_overflow_lits = 0; | |
1746 | state->write_overflow_len = 0; | |
1747 | return ISAL_END_INPUT; | |
1748 | } | |
224ce89b | 1749 | |
f91f0fd5 TL |
1750 | if (state->next_out - look_back_dist < start_out) |
1751 | return ISAL_INVALID_LOOKBACK; | |
224ce89b | 1752 | |
f91f0fd5 TL |
1753 | if (state->avail_out < repeat_length) { |
1754 | state->copy_overflow_length = | |
1755 | repeat_length - state->avail_out; | |
1756 | state->copy_overflow_distance = look_back_dist; | |
1757 | repeat_length = state->avail_out; | |
1758 | } | |
224ce89b | 1759 | |
f91f0fd5 TL |
1760 | if (look_back_dist > repeat_length) |
1761 | memcpy(state->next_out, | |
1762 | state->next_out - look_back_dist, | |
1763 | repeat_length); | |
1764 | else | |
1765 | byte_copy(state->next_out, look_back_dist, | |
1766 | repeat_length); | |
1767 | ||
1768 | state->next_out += repeat_length; | |
1769 | state->avail_out -= repeat_length; | |
1770 | state->total_out += repeat_length; | |
1771 | ||
1772 | if (state->copy_overflow_length > 0) | |
1773 | return ISAL_OUT_OVERFLOW; | |
1774 | } else | |
1775 | /* Else the read in bits do not | |
1776 | * correspond to any valid symbol */ | |
1777 | return ISAL_INVALID_SYMBOL; | |
224ce89b | 1778 | |
f91f0fd5 TL |
1779 | next_lits >>= 8; |
1780 | sym_count--; | |
1781 | } | |
224ce89b | 1782 | |
224ce89b WB |
1783 | } |
1784 | return 0; | |
1785 | } | |
1786 | ||
1787 | void isal_inflate_init(struct inflate_state *state) | |
1788 | { | |
1789 | ||
1790 | state->read_in = 0; | |
1791 | state->read_in_length = 0; | |
1792 | state->next_in = NULL; | |
1793 | state->avail_in = 0; | |
1794 | state->next_out = NULL; | |
1795 | state->avail_out = 0; | |
1796 | state->total_out = 0; | |
f91f0fd5 | 1797 | state->dict_length = 0; |
224ce89b WB |
1798 | state->block_state = ISAL_BLOCK_NEW_HDR; |
1799 | state->bfinal = 0; | |
1800 | state->crc_flag = 0; | |
1801 | state->crc = 0; | |
f91f0fd5 | 1802 | state->hist_bits = 0; |
224ce89b | 1803 | state->type0_block_len = 0; |
f91f0fd5 TL |
1804 | state->write_overflow_lits = 0; |
1805 | state->write_overflow_len = 0; | |
224ce89b WB |
1806 | state->copy_overflow_length = 0; |
1807 | state->copy_overflow_distance = 0; | |
f91f0fd5 | 1808 | state->wrapper_flag = 0; |
224ce89b WB |
1809 | state->tmp_in_size = 0; |
1810 | state->tmp_out_processed = 0; | |
1811 | state->tmp_out_valid = 0; | |
1812 | } | |
1813 | ||
f91f0fd5 TL |
1814 | void isal_inflate_reset(struct inflate_state *state) |
1815 | { | |
1816 | state->read_in = 0; | |
1817 | state->read_in_length = 0; | |
1818 | state->total_out = 0; | |
1819 | state->dict_length = 0; | |
1820 | state->block_state = ISAL_BLOCK_NEW_HDR; | |
1821 | state->bfinal = 0; | |
1822 | state->crc = 0; | |
1823 | state->type0_block_len = 0; | |
1824 | state->write_overflow_lits = 0; | |
1825 | state->write_overflow_len = 0; | |
1826 | state->copy_overflow_length = 0; | |
1827 | state->copy_overflow_distance = 0; | |
20effc67 | 1828 | state->wrapper_flag = 0; |
f91f0fd5 TL |
1829 | state->tmp_in_size = 0; |
1830 | state->tmp_out_processed = 0; | |
1831 | state->tmp_out_valid = 0; | |
1832 | } | |
1833 | ||
1834 | static inline uint32_t fixed_size_read(struct inflate_state *state, | |
1835 | uint8_t ** read_buf, int read_size) | |
1836 | { | |
1837 | uint32_t tmp_in_size = state->tmp_in_size; | |
1838 | ||
1839 | if (state->avail_in + tmp_in_size < read_size) { | |
1840 | memcpy(state->tmp_in_buffer + tmp_in_size, state->next_in, state->avail_in); | |
1841 | tmp_in_size += state->avail_in; | |
1842 | state->tmp_in_size = tmp_in_size; | |
1843 | state->next_in += state->avail_in; | |
1844 | state->avail_in = 0; | |
1845 | ||
1846 | return ISAL_END_INPUT; | |
1847 | } | |
1848 | ||
1849 | *read_buf = state->next_in; | |
1850 | if (tmp_in_size) { | |
1851 | memcpy(state->tmp_in_buffer + tmp_in_size, state->next_in, | |
1852 | read_size - tmp_in_size); | |
1853 | *read_buf = state->tmp_in_buffer; | |
1854 | state->tmp_in_size = 0; | |
1855 | } | |
1856 | ||
1857 | state->next_in += read_size - tmp_in_size; | |
1858 | state->avail_in -= read_size - tmp_in_size; | |
1859 | tmp_in_size = 0; | |
1860 | ||
1861 | return 0; | |
1862 | ||
1863 | } | |
1864 | ||
1865 | static inline uint32_t buffer_header_copy(struct inflate_state *state, uint32_t in_len, | |
20effc67 TL |
1866 | uint8_t * buf, uint32_t buffer_len, uint32_t offset, |
1867 | uint32_t buf_error) | |
f91f0fd5 TL |
1868 | { |
1869 | uint32_t len = in_len; | |
20effc67 TL |
1870 | uint32_t buf_len = buffer_len - offset; |
1871 | ||
f91f0fd5 TL |
1872 | if (len > state->avail_in) |
1873 | len = state->avail_in; | |
1874 | ||
1875 | if (buf != NULL && buf_len < len) { | |
20effc67 | 1876 | memcpy(&buf[offset], state->next_in, buf_len); |
f91f0fd5 TL |
1877 | state->next_in += buf_len; |
1878 | state->avail_in -= buf_len; | |
1879 | state->count = in_len - buf_len; | |
1880 | return buf_error; | |
1881 | } else { | |
1882 | if (buf != NULL) | |
20effc67 | 1883 | memcpy(&buf[offset], state->next_in, len); |
f91f0fd5 TL |
1884 | state->next_in += len; |
1885 | state->avail_in -= len; | |
1886 | state->count = in_len - len; | |
1887 | ||
1888 | if (len == in_len) | |
1889 | return 0; | |
1890 | else | |
1891 | return ISAL_END_INPUT; | |
1892 | } | |
1893 | } | |
1894 | ||
1895 | static inline uint32_t string_header_copy(struct inflate_state *state, | |
20effc67 TL |
1896 | char *str_buf, uint32_t str_len, |
1897 | uint32_t offset, uint32_t str_error) | |
f91f0fd5 | 1898 | { |
20effc67 | 1899 | uint32_t len, max_len = str_len - offset; |
f91f0fd5 TL |
1900 | |
1901 | if (max_len > state->avail_in || str_buf == NULL) | |
1902 | max_len = state->avail_in; | |
1903 | ||
1904 | len = strnlen((char *)state->next_in, max_len); | |
1905 | ||
1906 | if (str_buf != NULL) | |
20effc67 | 1907 | memcpy(&str_buf[offset], state->next_in, len); |
f91f0fd5 TL |
1908 | |
1909 | state->next_in += len; | |
1910 | state->avail_in -= len; | |
1911 | state->count += len; | |
1912 | ||
20effc67 | 1913 | if (str_buf != NULL && len == (str_len - offset)) |
f91f0fd5 TL |
1914 | return str_error; |
1915 | else if (state->avail_in <= 0) | |
1916 | return ISAL_END_INPUT; | |
1917 | else { | |
1918 | state->next_in++; | |
1919 | state->avail_in--; | |
1920 | state->count = 0; | |
1921 | if (str_buf != NULL) | |
1922 | str_buf[len] = 0; | |
1923 | } | |
1924 | ||
1925 | return 0; | |
1926 | } | |
1927 | ||
1928 | static int check_gzip_checksum(struct inflate_state *state) | |
1929 | { | |
1930 | uint64_t trailer, crc, total_out; | |
1931 | uint8_t *next_in; | |
1932 | uint32_t byte_count, offset, tmp_in_size = state->tmp_in_size; | |
1933 | int ret; | |
1934 | ||
1935 | if (state->read_in_length >= 8 * GZIP_TRAILER_LEN) { | |
1936 | /* The following is unecessary as state->read_in_length == 64 */ | |
1937 | /* bit_count = state->read_in_length % 8; */ | |
1938 | /* state->read_in >>= bit_count; */ | |
1939 | /* state->read_in_length -= bit_count; */ | |
1940 | ||
1941 | trailer = state->read_in; | |
1942 | state->read_in_length = 0; | |
1943 | state->read_in = 0; | |
1944 | } else { | |
1945 | if (state->read_in_length >= 8) { | |
1946 | byte_count = state->read_in_length / 8; | |
1947 | offset = state->read_in_length % 8; | |
1948 | ||
1949 | store_u64(state->tmp_in_buffer + tmp_in_size, | |
1950 | state->read_in >> offset); | |
1951 | state->read_in = 0; | |
1952 | state->read_in_length = 0; | |
1953 | ||
1954 | tmp_in_size += byte_count; | |
1955 | state->tmp_in_size = tmp_in_size; | |
1956 | } | |
1957 | ||
1958 | ret = fixed_size_read(state, &next_in, GZIP_TRAILER_LEN); | |
1959 | if (ret) { | |
1960 | state->block_state = ISAL_CHECKSUM_CHECK; | |
1961 | return ret; | |
1962 | } | |
1963 | ||
1964 | trailer = load_u64(next_in); | |
1965 | } | |
1966 | ||
1967 | state->block_state = ISAL_BLOCK_FINISH; | |
1968 | ||
1969 | crc = state->crc; | |
1970 | total_out = state->total_out; | |
1971 | ||
1972 | if (trailer != (crc | (total_out << 32))) | |
1973 | return ISAL_INCORRECT_CHECKSUM; | |
1974 | else | |
1975 | return ISAL_DECOMP_OK; | |
1976 | } | |
1977 | ||
1978 | static int check_zlib_checksum(struct inflate_state *state) | |
1979 | { | |
1980 | ||
1981 | uint32_t trailer; | |
1982 | uint8_t *next_in; | |
1983 | uint32_t byte_count, offset, tmp_in_size = state->tmp_in_size; | |
1984 | int ret, bit_count; | |
1985 | ||
1986 | if (state->read_in_length >= 8 * ZLIB_TRAILER_LEN) { | |
1987 | bit_count = state->read_in_length % 8; | |
1988 | state->read_in >>= bit_count; | |
1989 | state->read_in_length -= bit_count; | |
1990 | ||
1991 | trailer = state->read_in; | |
1992 | ||
1993 | state->read_in_length -= 8 * ZLIB_TRAILER_LEN; | |
1994 | state->read_in >>= 8 * ZLIB_TRAILER_LEN; | |
1995 | } else { | |
1996 | if (state->read_in_length >= 8) { | |
1997 | byte_count = state->read_in_length / 8; | |
1998 | offset = state->read_in_length % 8; | |
1999 | ||
2000 | store_u64(state->tmp_in_buffer + tmp_in_size, | |
2001 | state->read_in >> offset); | |
2002 | state->read_in = 0; | |
2003 | state->read_in_length = 0; | |
2004 | ||
2005 | tmp_in_size += byte_count; | |
2006 | state->tmp_in_size = tmp_in_size; | |
2007 | } | |
2008 | ||
2009 | ret = fixed_size_read(state, &next_in, ZLIB_TRAILER_LEN); | |
2010 | if (ret) { | |
2011 | state->block_state = ISAL_CHECKSUM_CHECK; | |
2012 | return ret; | |
2013 | } | |
2014 | ||
2015 | trailer = load_u32(next_in); | |
2016 | } | |
2017 | ||
2018 | state->block_state = ISAL_BLOCK_FINISH; | |
2019 | ||
2020 | if (bswap_32(trailer) != state->crc) | |
2021 | return ISAL_INCORRECT_CHECKSUM; | |
2022 | else | |
2023 | return ISAL_DECOMP_OK; | |
2024 | } | |
2025 | ||
2026 | int isal_read_gzip_header(struct inflate_state *state, struct isal_gzip_header *gz_hdr) | |
2027 | { | |
2028 | int cm, flags = gz_hdr->flags, id1, id2; | |
2029 | uint16_t xlen = gz_hdr->extra_len; | |
2030 | uint32_t block_state = state->block_state; | |
2031 | uint8_t *start_in = state->next_in, *next_in; | |
2032 | uint32_t tmp_in_size = state->tmp_in_size; | |
2033 | uint32_t count = state->count, offset; | |
2034 | uint32_t hcrc = gz_hdr->hcrc; | |
2035 | int ret = 0; | |
2036 | ||
2037 | /* This switch is a jump table into the function so that decoding the | |
2038 | * header can continue where it stopped on the last call */ | |
2039 | switch (block_state) { | |
2040 | case ISAL_BLOCK_NEW_HDR: | |
2041 | state->count = 0; | |
2042 | flags = UNDEFINED_FLAG; | |
2043 | if (tmp_in_size == 0) | |
2044 | hcrc = 0; | |
2045 | ||
2046 | ret = fixed_size_read(state, &next_in, GZIP_HDR_BASE); | |
2047 | if (ret) | |
2048 | break; | |
2049 | ||
2050 | id1 = next_in[0]; | |
2051 | id2 = next_in[1]; | |
2052 | cm = next_in[2]; | |
2053 | flags = next_in[3]; | |
2054 | gz_hdr->time = load_u32(next_in + 4); | |
2055 | gz_hdr->xflags = *(next_in + 8); | |
2056 | gz_hdr->os = *(next_in + 9); | |
2057 | ||
2058 | if (id1 != 0x1f || id2 != 0x8b) | |
2059 | return ISAL_INVALID_WRAPPER; | |
2060 | ||
2061 | if (cm != DEFLATE_METHOD) | |
2062 | return ISAL_UNSUPPORTED_METHOD; | |
2063 | ||
2064 | gz_hdr->text = 0; | |
2065 | if (flags & TEXT_FLAG) | |
2066 | gz_hdr->text = 1; | |
2067 | ||
2068 | gz_hdr->flags = flags; | |
2069 | ||
2070 | if (flags & EXTRA_FLAG) { | |
2071 | case ISAL_GZIP_EXTRA_LEN: | |
2072 | ret = fixed_size_read(state, &next_in, GZIP_EXTRA_LEN); | |
2073 | if (ret) { | |
2074 | state->block_state = ISAL_GZIP_EXTRA_LEN; | |
2075 | break; | |
2076 | } | |
2077 | ||
2078 | xlen = load_u16(next_in); | |
2079 | count = xlen; | |
2080 | ||
2081 | gz_hdr->extra_len = xlen; | |
2082 | ||
2083 | case ISAL_GZIP_EXTRA: | |
2084 | offset = gz_hdr->extra_len - count; | |
2085 | ret = | |
20effc67 TL |
2086 | buffer_header_copy(state, count, gz_hdr->extra, |
2087 | gz_hdr->extra_buf_len, | |
2088 | offset, ISAL_EXTRA_OVERFLOW); | |
f91f0fd5 TL |
2089 | |
2090 | if (ret) { | |
2091 | state->block_state = ISAL_GZIP_EXTRA; | |
2092 | break; | |
2093 | } | |
2094 | } else { | |
2095 | gz_hdr->extra_len = 0; | |
2096 | } | |
2097 | ||
2098 | if (flags & NAME_FLAG) { | |
2099 | case ISAL_GZIP_NAME: | |
2100 | offset = state->count; | |
20effc67 TL |
2101 | ret = string_header_copy(state, gz_hdr->name, |
2102 | gz_hdr->name_buf_len, | |
2103 | offset, ISAL_NAME_OVERFLOW); | |
f91f0fd5 TL |
2104 | if (ret) { |
2105 | state->block_state = ISAL_GZIP_NAME; | |
2106 | break; | |
2107 | } | |
2108 | } | |
2109 | ||
2110 | if (flags & COMMENT_FLAG) { | |
2111 | case ISAL_GZIP_COMMENT: | |
2112 | offset = state->count; | |
20effc67 TL |
2113 | ret = string_header_copy(state, gz_hdr->comment, |
2114 | gz_hdr->comment_buf_len, | |
2115 | offset, ISAL_COMMENT_OVERFLOW); | |
f91f0fd5 TL |
2116 | if (ret) { |
2117 | state->block_state = ISAL_GZIP_COMMENT; | |
2118 | break; | |
2119 | } | |
2120 | } | |
2121 | ||
2122 | if (flags & HCRC_FLAG) { | |
2123 | hcrc = crc32_gzip_refl(hcrc, start_in, state->next_in - start_in); | |
2124 | gz_hdr->hcrc = hcrc; | |
2125 | ||
2126 | case ISAL_GZIP_HCRC: | |
2127 | ret = fixed_size_read(state, &next_in, GZIP_HCRC_LEN); | |
2128 | if (ret) { | |
2129 | state->block_state = ISAL_GZIP_HCRC; | |
2130 | return ret; | |
2131 | } | |
2132 | ||
2133 | if ((hcrc & 0xffff) != load_u16(next_in)) | |
2134 | return ISAL_INCORRECT_CHECKSUM; | |
2135 | } | |
2136 | ||
2137 | state->wrapper_flag = 1; | |
2138 | state->block_state = ISAL_BLOCK_NEW_HDR; | |
2139 | return ISAL_DECOMP_OK; | |
2140 | } | |
2141 | ||
2142 | if (flags & HCRC_FLAG) | |
2143 | gz_hdr->hcrc = crc32_gzip_refl(hcrc, start_in, state->next_in - start_in); | |
2144 | ||
2145 | return ret; | |
2146 | } | |
2147 | ||
2148 | int isal_read_zlib_header(struct inflate_state *state, struct isal_zlib_header *zlib_hdr) | |
2149 | { | |
2150 | int cmf, method, flags; | |
2151 | uint32_t block_state = state->block_state; | |
2152 | uint8_t *next_in; | |
2153 | int ret = 0; | |
2154 | ||
2155 | switch (block_state) { | |
2156 | case ISAL_BLOCK_NEW_HDR: | |
2157 | zlib_hdr->dict_flag = 0; | |
2158 | ret = fixed_size_read(state, &next_in, ZLIB_HDR_BASE); | |
2159 | if (ret) | |
2160 | break; | |
2161 | ||
2162 | cmf = *next_in; | |
2163 | method = cmf & 0xf; | |
2164 | flags = *(next_in + 1); | |
2165 | ||
2166 | zlib_hdr->info = cmf >> ZLIB_INFO_OFFSET; | |
2167 | zlib_hdr->dict_flag = (flags & ZLIB_DICT_FLAG) ? 1 : 0; | |
2168 | zlib_hdr->level = flags >> ZLIB_LEVEL_OFFSET; | |
2169 | ||
2170 | if (method != DEFLATE_METHOD) | |
2171 | return ISAL_UNSUPPORTED_METHOD; | |
2172 | ||
2173 | if ((256 * cmf + flags) % 31 != 0) | |
2174 | return ISAL_INCORRECT_CHECKSUM; | |
2175 | ||
2176 | if (zlib_hdr->dict_flag) { | |
2177 | case ISAL_ZLIB_DICT: | |
2178 | ret = fixed_size_read(state, &next_in, ZLIB_DICT_LEN); | |
2179 | if (ret) { | |
2180 | state->block_state = ISAL_ZLIB_DICT; | |
2181 | break; | |
2182 | } | |
2183 | ||
2184 | zlib_hdr->dict_id = load_u32(next_in); | |
2185 | } | |
2186 | ||
2187 | state->wrapper_flag = 1; | |
2188 | state->block_state = ISAL_BLOCK_NEW_HDR; | |
2189 | } | |
2190 | ||
2191 | return ret; | |
2192 | } | |
2193 | ||
2194 | int isal_inflate_set_dict(struct inflate_state *state, uint8_t * dict, uint32_t dict_len) | |
2195 | { | |
2196 | ||
2197 | if (state->block_state != ISAL_BLOCK_NEW_HDR | |
2198 | || state->tmp_out_processed != state->tmp_out_valid) | |
2199 | return ISAL_INVALID_STATE; | |
2200 | ||
2201 | if (dict_len > IGZIP_HIST_SIZE) { | |
2202 | dict = dict + dict_len - IGZIP_HIST_SIZE; | |
2203 | dict_len = IGZIP_HIST_SIZE; | |
2204 | } | |
2205 | ||
2206 | memcpy(state->tmp_out_buffer, dict, dict_len); | |
2207 | state->tmp_out_processed = dict_len; | |
2208 | state->tmp_out_valid = dict_len; | |
2209 | state->dict_length = dict_len; | |
2210 | ||
2211 | return COMP_OK; | |
2212 | } | |
2213 | ||
224ce89b WB |
2214 | int isal_inflate_stateless(struct inflate_state *state) |
2215 | { | |
2216 | uint32_t ret = 0; | |
2217 | uint8_t *start_out = state->next_out; | |
2218 | ||
2219 | state->read_in = 0; | |
2220 | state->read_in_length = 0; | |
2221 | state->block_state = ISAL_BLOCK_NEW_HDR; | |
f91f0fd5 | 2222 | state->dict_length = 0; |
224ce89b WB |
2223 | state->bfinal = 0; |
2224 | state->crc = 0; | |
2225 | state->total_out = 0; | |
f91f0fd5 TL |
2226 | state->hist_bits = 0; |
2227 | state->tmp_in_size = 0; | |
2228 | ||
2229 | if (state->crc_flag == IGZIP_GZIP) { | |
2230 | struct isal_gzip_header gz_hdr; | |
20effc67 | 2231 | isal_gzip_header_init(&gz_hdr); |
f91f0fd5 TL |
2232 | ret = isal_read_gzip_header(state, &gz_hdr); |
2233 | if (ret) | |
2234 | return ret; | |
2235 | } else if (state->crc_flag == IGZIP_ZLIB) { | |
20effc67 | 2236 | struct isal_zlib_header z_hdr = { 0 }; |
f91f0fd5 TL |
2237 | ret = isal_read_zlib_header(state, &z_hdr); |
2238 | if (ret) | |
2239 | return ret; | |
2240 | if (z_hdr.dict_flag) | |
2241 | return ISAL_NEED_DICT; | |
2242 | ||
2243 | } | |
224ce89b WB |
2244 | |
2245 | while (state->block_state != ISAL_BLOCK_FINISH) { | |
2246 | if (state->block_state == ISAL_BLOCK_NEW_HDR) { | |
2247 | ret = read_header(state); | |
2248 | ||
2249 | if (ret) | |
2250 | break; | |
2251 | } | |
2252 | ||
2253 | if (state->block_state == ISAL_BLOCK_TYPE0) | |
2254 | ret = decode_literal_block(state); | |
2255 | else | |
f91f0fd5 | 2256 | ret = decode_huffman_code_block_stateless(state, start_out); |
224ce89b WB |
2257 | |
2258 | if (ret) | |
2259 | break; | |
f91f0fd5 | 2260 | if (state->block_state == ISAL_BLOCK_INPUT_DONE) |
224ce89b WB |
2261 | state->block_state = ISAL_BLOCK_FINISH; |
2262 | } | |
2263 | ||
224ce89b WB |
2264 | /* Undo count stuff of bytes read into the read buffer */ |
2265 | state->next_in -= state->read_in_length / 8; | |
2266 | state->avail_in += state->read_in_length / 8; | |
f91f0fd5 TL |
2267 | state->read_in_length = 0; |
2268 | state->read_in = 0; | |
2269 | ||
2270 | if (!ret && state->crc_flag) { | |
2271 | update_checksum(state, start_out, state->next_out - start_out); | |
2272 | switch (state->crc_flag) { | |
2273 | case ISAL_ZLIB: | |
2274 | case ISAL_ZLIB_NO_HDR_VER: | |
2275 | finalize_adler32(state); | |
2276 | ret = check_zlib_checksum(state); | |
2277 | break; | |
2278 | ||
2279 | case ISAL_ZLIB_NO_HDR: | |
2280 | finalize_adler32(state); | |
2281 | break; | |
2282 | ||
2283 | case ISAL_GZIP: | |
2284 | case ISAL_GZIP_NO_HDR_VER: | |
2285 | ret = check_gzip_checksum(state); | |
2286 | break; | |
2287 | } | |
2288 | } | |
224ce89b WB |
2289 | |
2290 | return ret; | |
2291 | } | |
2292 | ||
2293 | int isal_inflate(struct inflate_state *state) | |
2294 | { | |
2295 | ||
2296 | uint8_t *start_out = state->next_out; | |
2297 | uint32_t avail_out = state->avail_out; | |
2298 | uint32_t copy_size = 0; | |
2299 | int32_t shift_size = 0; | |
2300 | int ret = 0; | |
2301 | ||
f91f0fd5 TL |
2302 | if (!state->wrapper_flag && state->crc_flag == IGZIP_GZIP) { |
2303 | struct isal_gzip_header gz_hdr; | |
20effc67 | 2304 | isal_gzip_header_init(&gz_hdr); |
f91f0fd5 TL |
2305 | ret = isal_read_gzip_header(state, &gz_hdr); |
2306 | if (ret < 0) | |
2307 | return ret; | |
2308 | else if (ret > 0) | |
2309 | return ISAL_DECOMP_OK; | |
2310 | } else if (!state->wrapper_flag && state->crc_flag == IGZIP_ZLIB) { | |
20effc67 | 2311 | struct isal_zlib_header z_hdr = { 0 }; |
f91f0fd5 TL |
2312 | ret = isal_read_zlib_header(state, &z_hdr); |
2313 | if (ret < 0) | |
2314 | return ret; | |
2315 | else if (ret > 0) | |
2316 | return ISAL_DECOMP_OK; | |
2317 | ||
2318 | if (z_hdr.dict_flag) { | |
2319 | state->dict_id = z_hdr.dict_id; | |
2320 | return ISAL_NEED_DICT; | |
2321 | } | |
2322 | } else if (state->block_state == ISAL_CHECKSUM_CHECK) { | |
2323 | switch (state->crc_flag) { | |
2324 | case ISAL_ZLIB: | |
2325 | case ISAL_ZLIB_NO_HDR_VER: | |
2326 | ret = check_zlib_checksum(state); | |
2327 | break; | |
2328 | case ISAL_GZIP: | |
2329 | case ISAL_GZIP_NO_HDR_VER: | |
2330 | ret = check_gzip_checksum(state); | |
2331 | break; | |
2332 | } | |
2333 | ||
2334 | return (ret > 0) ? ISAL_DECOMP_OK : ret; | |
2335 | } | |
2336 | ||
224ce89b | 2337 | if (state->block_state != ISAL_BLOCK_FINISH) { |
f91f0fd5 | 2338 | state->total_out += state->tmp_out_valid - state->tmp_out_processed; |
224ce89b WB |
2339 | /* If space in tmp_out buffer, decompress into the tmp_out_buffer */ |
2340 | if (state->tmp_out_valid < 2 * ISAL_DEF_HIST_SIZE) { | |
2341 | /* Setup to start decoding into temp buffer */ | |
2342 | state->next_out = &state->tmp_out_buffer[state->tmp_out_valid]; | |
2343 | state->avail_out = | |
2344 | sizeof(state->tmp_out_buffer) - ISAL_LOOK_AHEAD - | |
2345 | state->tmp_out_valid; | |
2346 | ||
2347 | if ((int32_t) state->avail_out < 0) | |
2348 | state->avail_out = 0; | |
2349 | ||
2350 | /* Decode into internal buffer until exit */ | |
2351 | while (state->block_state != ISAL_BLOCK_INPUT_DONE) { | |
2352 | if (state->block_state == ISAL_BLOCK_NEW_HDR | |
2353 | || state->block_state == ISAL_BLOCK_HDR) { | |
2354 | ret = read_header_stateful(state); | |
2355 | ||
2356 | if (ret) | |
2357 | break; | |
2358 | } | |
2359 | ||
2360 | if (state->block_state == ISAL_BLOCK_TYPE0) { | |
2361 | ret = decode_literal_block(state); | |
f91f0fd5 TL |
2362 | } else { |
2363 | uint8_t *tmp = state->tmp_out_buffer; | |
2364 | ret = decode_huffman_code_block_stateless(state, tmp); | |
2365 | } | |
224ce89b WB |
2366 | |
2367 | if (ret) | |
2368 | break; | |
224ce89b WB |
2369 | } |
2370 | ||
2371 | /* Copy valid data from internal buffer into out_buffer */ | |
f91f0fd5 TL |
2372 | if (state->write_overflow_len != 0) { |
2373 | store_u32(state->next_out, state->write_overflow_lits); | |
2374 | state->next_out += state->write_overflow_len; | |
2375 | state->total_out += state->write_overflow_len; | |
2376 | state->write_overflow_lits = 0; | |
2377 | state->write_overflow_len = 0; | |
2378 | } | |
2379 | ||
224ce89b WB |
2380 | if (state->copy_overflow_length != 0) { |
2381 | byte_copy(state->next_out, state->copy_overflow_distance, | |
2382 | state->copy_overflow_length); | |
2383 | state->tmp_out_valid += state->copy_overflow_length; | |
2384 | state->next_out += state->copy_overflow_length; | |
2385 | state->total_out += state->copy_overflow_length; | |
2386 | state->copy_overflow_distance = 0; | |
2387 | state->copy_overflow_length = 0; | |
2388 | } | |
2389 | ||
2390 | state->tmp_out_valid = state->next_out - state->tmp_out_buffer; | |
2391 | ||
2392 | /* Setup state for decompressing into out_buffer */ | |
2393 | state->next_out = start_out; | |
2394 | state->avail_out = avail_out; | |
2395 | } | |
2396 | ||
2397 | /* Copy data from tmp_out buffer into out_buffer */ | |
2398 | copy_size = state->tmp_out_valid - state->tmp_out_processed; | |
2399 | if (copy_size > avail_out) | |
2400 | copy_size = avail_out; | |
2401 | ||
2402 | memcpy(state->next_out, | |
2403 | &state->tmp_out_buffer[state->tmp_out_processed], copy_size); | |
2404 | ||
2405 | state->tmp_out_processed += copy_size; | |
2406 | state->avail_out -= copy_size; | |
2407 | state->next_out += copy_size; | |
2408 | ||
2409 | if (ret == ISAL_INVALID_LOOKBACK || ret == ISAL_INVALID_BLOCK | |
2410 | || ret == ISAL_INVALID_SYMBOL) { | |
2411 | /* Set total_out to not count data in tmp_out_buffer */ | |
2412 | state->total_out -= state->tmp_out_valid - state->tmp_out_processed; | |
2413 | if (state->crc_flag) | |
f91f0fd5 | 2414 | update_checksum(state, start_out, state->next_out - start_out); |
224ce89b WB |
2415 | return ret; |
2416 | } | |
2417 | ||
2418 | /* If all data from tmp_out buffer has been processed, start | |
2419 | * decompressing into the out buffer */ | |
2420 | if (state->tmp_out_processed == state->tmp_out_valid) { | |
2421 | while (state->block_state != ISAL_BLOCK_INPUT_DONE) { | |
2422 | if (state->block_state == ISAL_BLOCK_NEW_HDR | |
2423 | || state->block_state == ISAL_BLOCK_HDR) { | |
2424 | ret = read_header_stateful(state); | |
2425 | if (ret) | |
2426 | break; | |
2427 | } | |
2428 | ||
2429 | if (state->block_state == ISAL_BLOCK_TYPE0) | |
2430 | ret = decode_literal_block(state); | |
2431 | else | |
f91f0fd5 TL |
2432 | ret = |
2433 | decode_huffman_code_block_stateless(state, | |
2434 | start_out); | |
224ce89b WB |
2435 | if (ret) |
2436 | break; | |
224ce89b WB |
2437 | } |
2438 | } | |
2439 | ||
2440 | if (state->crc_flag) | |
f91f0fd5 | 2441 | update_checksum(state, start_out, state->next_out - start_out); |
224ce89b | 2442 | |
f91f0fd5 TL |
2443 | if (state->block_state != ISAL_BLOCK_INPUT_DONE |
2444 | || state->copy_overflow_length + state->write_overflow_len + | |
2445 | state->tmp_out_valid > sizeof(state->tmp_out_buffer)) { | |
224ce89b WB |
2446 | /* Save decompression history in tmp_out buffer */ |
2447 | if (state->tmp_out_valid == state->tmp_out_processed | |
2448 | && avail_out - state->avail_out >= ISAL_DEF_HIST_SIZE) { | |
2449 | memcpy(state->tmp_out_buffer, | |
2450 | state->next_out - ISAL_DEF_HIST_SIZE, | |
2451 | ISAL_DEF_HIST_SIZE); | |
2452 | state->tmp_out_valid = ISAL_DEF_HIST_SIZE; | |
2453 | state->tmp_out_processed = ISAL_DEF_HIST_SIZE; | |
2454 | ||
2455 | } else if (state->tmp_out_processed >= ISAL_DEF_HIST_SIZE) { | |
2456 | shift_size = state->tmp_out_valid - ISAL_DEF_HIST_SIZE; | |
2457 | if (shift_size > state->tmp_out_processed) | |
2458 | shift_size = state->tmp_out_processed; | |
2459 | ||
2460 | memmove(state->tmp_out_buffer, | |
2461 | &state->tmp_out_buffer[shift_size], | |
2462 | state->tmp_out_valid - shift_size); | |
2463 | state->tmp_out_valid -= shift_size; | |
2464 | state->tmp_out_processed -= shift_size; | |
2465 | ||
2466 | } | |
f91f0fd5 | 2467 | } |
224ce89b | 2468 | |
f91f0fd5 TL |
2469 | /* Write overflow data into tmp buffer */ |
2470 | if (state->write_overflow_len != 0) { | |
2471 | store_u32(&state->tmp_out_buffer[state->tmp_out_valid], | |
2472 | state->write_overflow_lits); | |
2473 | state->tmp_out_valid += state->write_overflow_len; | |
2474 | state->total_out += state->write_overflow_len; | |
2475 | state->write_overflow_lits = 0; | |
2476 | state->write_overflow_len = 0; | |
2477 | } | |
224ce89b | 2478 | |
f91f0fd5 TL |
2479 | if (state->copy_overflow_length != 0) { |
2480 | byte_copy(&state->tmp_out_buffer[state->tmp_out_valid], | |
2481 | state->copy_overflow_distance, state->copy_overflow_length); | |
2482 | state->tmp_out_valid += state->copy_overflow_length; | |
2483 | state->total_out += state->copy_overflow_length; | |
2484 | state->copy_overflow_distance = 0; | |
2485 | state->copy_overflow_length = 0; | |
2486 | } | |
2487 | ||
2488 | if (ret == ISAL_INVALID_LOOKBACK || ret == ISAL_INVALID_BLOCK | |
2489 | || ret == ISAL_INVALID_SYMBOL) { | |
2490 | state->total_out -= state->tmp_out_valid - state->tmp_out_processed; | |
2491 | return ret; | |
2492 | } | |
224ce89b | 2493 | |
f91f0fd5 TL |
2494 | if (state->block_state == ISAL_BLOCK_INPUT_DONE |
2495 | && state->tmp_out_valid == state->tmp_out_processed) { | |
224ce89b | 2496 | state->block_state = ISAL_BLOCK_FINISH; |
f91f0fd5 TL |
2497 | |
2498 | switch (state->crc_flag) { | |
2499 | case ISAL_ZLIB: | |
2500 | case ISAL_ZLIB_NO_HDR_VER: | |
2501 | finalize_adler32(state); | |
2502 | ret = check_zlib_checksum(state); | |
2503 | break; | |
2504 | ||
2505 | case ISAL_ZLIB_NO_HDR: | |
2506 | finalize_adler32(state); | |
2507 | break; | |
2508 | ||
2509 | case ISAL_GZIP: | |
2510 | case ISAL_GZIP_NO_HDR_VER: | |
2511 | ret = check_gzip_checksum(state); | |
2512 | break; | |
2513 | } | |
2514 | } | |
2515 | ||
2516 | state->total_out -= state->tmp_out_valid - state->tmp_out_processed; | |
224ce89b WB |
2517 | } |
2518 | ||
f91f0fd5 | 2519 | return (ret > 0) ? ISAL_DECOMP_OK : ret; |
224ce89b | 2520 | } |