source: mainline/boot/generic/src/inflate.c@ f1bed857

Last change on this file since f1bed857 was d7f7a4a, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 3 years ago

Replace some license headers with SPDX identifier

Headers are replaced using tools/transorm-copyright.sh only
when it can be matched verbatim with the license header used
throughout most of the codebase.

  • Property mode set to 100644
File size: 16.1 KB
Line 
1/*
2 * SPDX-FileCopyrightText: 2010 Mark Adler
3 * SPDX-FileCopyrightText: 2010 Martin Decky
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8/** @file
9 * @brief Implementation of inflate decompression
10 *
11 * A simple inflate implementation (decompression of `deflate' stream as
12 * described by RFC 1951) based on puff.c by Mark Adler. It is not optimized
13 * for speed but for readability as it is used as part of the bootloader and
14 * any miss-optimization might be hard to debug.
15 *
16 * All dynamically allocated memory memory is taken from the stack. The
17 * stack usage should be typically bounded by 2 KB.
18 *
19 * Original copyright notice:
20 *
21 * Copyright (C) 2002-2010 Mark Adler, all rights reserved
22 * version 2.1, 4 Apr 2010
23 *
24 * This software is provided 'as-is', without any express or implied
25 * warranty. In no event will the author be held liable for any damages
26 * arising from the use of this software.
27 *
28 * Permission is granted to anyone to use this software for any purpose,
29 * including commercial applications, and to alter it and redistribute it
30 * freely, subject to the following restrictions:
31 *
32 * 1. The origin of this software must not be misrepresented; you must not
33 * claim that you wrote the original software. If you use this software
34 * in a product, an acknowledgment in the product documentation would be
35 * appreciated but is not required.
36 * 2. Altered source versions must be plainly marked as such, and must not
37 * be misrepresented as being the original software.
38 * 3. This notice may not be removed or altered from any source
39 * distribution.
40 *
41 * Mark Adler <madler@alumni.caltech.edu>
42 *
43 */
44
45#include <stdbool.h>
46#include <stddef.h>
47#include <stdint.h>
48#include <errno.h>
49#include <memstr.h>
50#include <inflate.h>
51
52/** Maximum bits in the Huffman code */
53#define MAX_HUFFMAN_BIT 15
54
55/** Number of length codes */
56#define MAX_LEN 29
57/** Number of distance codes */
58#define MAX_DIST 30
59/** Number of order codes */
60#define MAX_ORDER 19
61/** Number of literal/length codes */
62#define MAX_LITLEN 286
63/** Number of fixed literal/length codes */
64#define MAX_FIXED_LITLEN 288
65
66/** Number of all codes */
67#define MAX_CODE (MAX_LITLEN + MAX_DIST)
68
69/** Check for input buffer overrun condition */
70#define CHECK_OVERRUN(state) \
71 do { \
72 if ((state).overrun) \
73 return ELIMIT; \
74 } while (false)
75
76/** Inflate algorithm state
77 *
78 */
79typedef struct {
80 uint8_t *dest; /**< Output buffer */
81 size_t destlen; /**< Output buffer size */
82 size_t destcnt; /**< Position in the output buffer */
83
84 const uint8_t *src; /**< Input buffer */
85 size_t srclen; /**< Input buffer size */
86 size_t srccnt; /**< Position in the input buffer */
87
88 uint16_t bitbuf; /**< Bit buffer */
89 size_t bitlen; /**< Number of bits in the bit buffer */
90
91 bool overrun; /**< Overrun condition */
92} inflate_state_t;
93
94/** Huffman code description
95 *
96 */
97typedef struct {
98 uint16_t *count; /**< Array of symbol counts */
99 uint16_t *symbol; /**< Array of symbols */
100} huffman_t;
101
102/** Length codes
103 *
104 */
105static const uint16_t lens[MAX_LEN] = {
106 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
107 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
108};
109
110/** Extended length codes
111 *
112 */
113static const uint16_t lens_ext[MAX_LEN] = {
114 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
115 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
116};
117
118/** Distance codes
119 *
120 */
121static const uint16_t dists[MAX_DIST] = {
122 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
123 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
124 8193, 12289, 16385, 24577
125};
126
127/** Extended distance codes
128 *
129 */
130static const uint16_t dists_ext[MAX_DIST] = {
131 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
132 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
133 12, 12, 13, 13
134};
135
136/** Order codes
137 *
138 */
139static const short order[MAX_ORDER] = {
140 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
141};
142
143/** Static length symbol counts
144 *
145 */
146static uint16_t len_count[MAX_HUFFMAN_BIT + 1] = {
147 0, 0, 0, 0, 0, 0, 0, 24, 152, 112, 0, 0, 0, 0, 0, 0
148};
149
150/** Static length symbols
151 *
152 */
153static uint16_t len_symbol[MAX_FIXED_LITLEN] = {
154 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268,
155 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 0, 1, 2,
156 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
157 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
158 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
159 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
160 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
161 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
162 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
163 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
164 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
165 140, 141, 142, 143, 280, 281, 282, 283, 284, 285, 286, 287, 144,
166 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
167 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170,
168 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
169 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
170 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
171 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222,
172 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235,
173 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
174 249, 250, 251, 252, 253, 254, 255
175};
176
177/** Static distance symbol counts
178 *
179 */
180static uint16_t dist_count[MAX_HUFFMAN_BIT + 1] = {
181 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
182};
183
184/** Static distance symbols
185 *
186 */
187static uint16_t dist_symbol[MAX_DIST] = {
188 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
189 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
190};
191
192/** Huffman code for lengths
193 *
194 */
195static huffman_t len_code = {
196 .count = len_count,
197 .symbol = len_symbol
198};
199
200/** Huffman code for distances
201 *
202 */
203static huffman_t dist_code = {
204 .count = dist_count,
205 .symbol = dist_symbol
206};
207
208/** Get bits from the bit buffer
209 *
210 * @param state Inflate state.
211 * @param cnt Number of bits to return (at most 16).
212 *
213 * @return Returned bits.
214 *
215 */
216static inline uint16_t get_bits(inflate_state_t *state, size_t cnt)
217{
218 /* Bit accumulator for at least 20 bits */
219 uint32_t val = state->bitbuf;
220
221 while (state->bitlen < cnt) {
222 if (state->srccnt == state->srclen) {
223 state->overrun = true;
224 return 0;
225 }
226
227 /* Load 8 more bits */
228 val |= ((uint32_t) state->src[state->srccnt]) << state->bitlen;
229 state->srccnt++;
230 state->bitlen += 8;
231 }
232
233 /* Update bits in the buffer */
234 state->bitbuf = (uint16_t) (val >> cnt);
235 state->bitlen -= cnt;
236
237 return ((uint16_t) (val & ((1 << cnt) - 1)));
238}
239
240/** Decode `stored' block
241 *
242 * @param state Inflate state.
243 *
244 * @return EOK on success.
245 * @return ELIMIT on input buffer overrun.
246 * @return ENOMEM on output buffer overrun.
247 * @return EINVAL on invalid data.
248 *
249 */
250static int inflate_stored(inflate_state_t *state)
251{
252 /* Discard bits in the bit buffer */
253 state->bitbuf = 0;
254 state->bitlen = 0;
255
256 if (state->srccnt + 4 > state->srclen)
257 return ELIMIT;
258
259 uint16_t len =
260 state->src[state->srccnt] | (state->src[state->srccnt + 1] << 8);
261 uint16_t len_compl =
262 state->src[state->srccnt + 2] | (state->src[state->srccnt + 3] << 8);
263
264 /* Check block length and its complement */
265 if (((int16_t) len) != ~((int16_t) len_compl))
266 return EINVAL;
267
268 state->srccnt += 4;
269
270 /* Check input buffer size */
271 if (state->srccnt + len > state->srclen)
272 return ELIMIT;
273
274 /* Check output buffer size */
275 if (state->destcnt + len > state->destlen)
276 return ENOMEM;
277
278 /* Copy data */
279 memcpy(state->dest + state->destcnt, state->src + state->srccnt, len);
280 state->srccnt += len;
281 state->destcnt += len;
282
283 return EOK;
284}
285
286/** Decode a symbol using the Huffman code
287 *
288 * @param state Inflate state.
289 * @param huffman Huffman code.
290 * @param symbol Decoded symbol.
291 *
292 * @param EOK on success.
293 * @param EINVAL on invalid Huffman code.
294 *
295 */
296static int huffman_decode(inflate_state_t *state, huffman_t *huffman,
297 uint16_t *symbol)
298{
299 /* Decode bits */
300 uint16_t code = 0;
301
302 /* First code of the given length */
303 size_t first = 0;
304
305 /*
306 * Index of the first code of the given length
307 * in the symbol table
308 */
309 size_t index = 0;
310
311 /* Current number of bits in the code */
312 size_t len;
313
314 for (len = 1; len <= MAX_HUFFMAN_BIT; len++) {
315 /* Get next bit */
316 code |= get_bits(state, 1);
317 CHECK_OVERRUN(*state);
318
319 uint16_t count = huffman->count[len];
320 if (code < first + count) {
321 /* Return decoded symbol */
322 *symbol = huffman->symbol[index + code - first];
323 return EOK;
324 }
325
326 /* Update for next length */
327 index += count;
328 first += count;
329 first <<= 1;
330 code <<= 1;
331 }
332
333 return EINVAL;
334}
335
336/** Construct Huffman tables from canonical Huffman code
337 *
338 * @param huffman Constructed Huffman tables.
339 * @param length Lengths of the canonical Huffman code.
340 * @param n Number of lengths.
341 *
342 * @return 0 if the Huffman code set is complete.
343 * @return Negative value for an over-subscribed code set.
344 * @return Positive value for an incomplete code set.
345 *
346 */
347static int16_t huffman_construct(huffman_t *huffman, uint16_t *length, size_t n)
348{
349 /* Count number of codes for each length */
350 size_t len;
351 for (len = 0; len <= MAX_HUFFMAN_BIT; len++)
352 huffman->count[len] = 0;
353
354 /* We assume that the lengths are within bounds */
355 size_t symbol;
356 for (symbol = 0; symbol < n; symbol++)
357 huffman->count[length[symbol]]++;
358
359 if (huffman->count[0] == n) {
360 /* The code is complete, but decoding will fail */
361 return 0;
362 }
363
364 /* Check for an over-subscribed or incomplete set of lengths */
365 int16_t left = 1;
366 for (len = 1; len <= MAX_HUFFMAN_BIT; len++) {
367 left <<= 1;
368 left -= huffman->count[len];
369 if (left < 0) {
370 /* Over-subscribed */
371 return left;
372 }
373 }
374
375 /* Generate offsets into symbol table */
376 uint16_t offs[MAX_HUFFMAN_BIT + 1];
377
378 offs[1] = 0;
379 for (len = 1; len < MAX_HUFFMAN_BIT; len++)
380 offs[len + 1] = offs[len] + huffman->count[len];
381
382 for (symbol = 0; symbol < n; symbol++) {
383 if (length[symbol] != 0) {
384 huffman->symbol[offs[length[symbol]]] = symbol;
385 offs[length[symbol]]++;
386 }
387 }
388
389 return left;
390}
391
392/** Decode literal/length and distance codes
393 *
394 * Decode until end-of-block code.
395 *
396 * @param state Inflate state.
397 * @param len_code Huffman code for literal/length.
398 * @param dist_code Huffman code for distance.
399 *
400 * @return EOK on success.
401 * @return ENOENT on distance too large.
402 * @return EINVAL on invalid Huffman code.
403 * @return ELIMIT on input buffer overrun.
404 * @return ENOMEM on output buffer overrun.
405 *
406 */
407static int inflate_codes(inflate_state_t *state, huffman_t *len_code,
408 huffman_t *dist_code)
409{
410 uint16_t symbol;
411
412 do {
413 int err = huffman_decode(state, len_code, &symbol);
414 if (err != EOK) {
415 /* Error decoding */
416 return err;
417 }
418
419 if (symbol < 256) {
420 /* Write out literal */
421 if (state->destcnt == state->destlen)
422 return ENOMEM;
423
424 state->dest[state->destcnt] = (uint8_t) symbol;
425 state->destcnt++;
426 } else if (symbol > 256) {
427 /* Compute length */
428 symbol -= 257;
429 if (symbol >= 29)
430 return EINVAL;
431
432 size_t len = lens[symbol] + get_bits(state, lens_ext[symbol]);
433 CHECK_OVERRUN(*state);
434
435 /* Get distance */
436 err = huffman_decode(state, dist_code, &symbol);
437 if (err != EOK)
438 return err;
439
440 size_t dist = dists[symbol] + get_bits(state, dists_ext[symbol]);
441 if (dist > state->destcnt)
442 return ENOENT;
443
444 if (state->destcnt + len > state->destlen)
445 return ENOMEM;
446
447 while (len > 0) {
448 /* Copy len bytes from distance bytes back */
449 state->dest[state->destcnt] =
450 state->dest[state->destcnt - dist];
451 state->destcnt++;
452 len--;
453 }
454 }
455 } while (symbol != 256);
456
457 return EOK;
458}
459
460/** Decode `fixed codes' block
461 *
462 * @param state Inflate state.
463 * @param len_code Huffman code for literal/length.
464 * @param dist_code Huffman code for distance.
465 *
466 * @return EOK on success.
467 * @return ENOENT on distance too large.
468 * @return EINVAL on invalid Huffman code.
469 * @return ELIMIT on input buffer overrun.
470 * @return ENOMEM on output buffer overrun.
471 *
472 */
473static int inflate_fixed(inflate_state_t *state, huffman_t *len_code,
474 huffman_t *dist_code)
475{
476 return inflate_codes(state, len_code, dist_code);
477}
478
479/** Decode `dynamic codes' block
480 *
481 * @param state Inflate state.
482 *
483 * @return EOK on success.
484 * @return ENOENT on distance too large.
485 * @return EINVAL on invalid Huffman code.
486 * @return ELIMIT on input buffer overrun.
487 * @return ENOMEM on output buffer overrun.
488 *
489 */
490static int inflate_dynamic(inflate_state_t *state)
491{
492 uint16_t length[MAX_CODE];
493 uint16_t dyn_len_count[MAX_HUFFMAN_BIT + 1];
494 uint16_t dyn_len_symbol[MAX_LITLEN];
495 uint16_t dyn_dist_count[MAX_HUFFMAN_BIT + 1];
496 uint16_t dyn_dist_symbol[MAX_DIST];
497 huffman_t dyn_len_code;
498 huffman_t dyn_dist_code;
499
500 dyn_len_code.count = dyn_len_count;
501 dyn_len_code.symbol = dyn_len_symbol;
502
503 dyn_dist_code.count = dyn_dist_count;
504 dyn_dist_code.symbol = dyn_dist_symbol;
505
506 /* Get number of bits in each table */
507 uint16_t nlen = get_bits(state, 5) + 257;
508 CHECK_OVERRUN(*state);
509
510 uint16_t ndist = get_bits(state, 5) + 1;
511 CHECK_OVERRUN(*state);
512
513 uint16_t ncode = get_bits(state, 4) + 4;
514 CHECK_OVERRUN(*state);
515
516 if ((nlen > MAX_LITLEN) || (ndist > MAX_DIST) ||
517 (ncode > MAX_ORDER))
518 return EINVAL;
519
520 /* Read code length code lengths */
521 uint16_t index;
522 for (index = 0; index < ncode; index++) {
523 length[order[index]] = get_bits(state, 3);
524 CHECK_OVERRUN(*state);
525 }
526
527 /* Set missing lengths to zero */
528 for (index = ncode; index < MAX_ORDER; index++)
529 length[order[index]] = 0;
530
531 /* Build Huffman code */
532 int16_t rc = huffman_construct(&dyn_len_code, length, MAX_ORDER);
533 if (rc != 0)
534 return EINVAL;
535
536 /* Read length/literal and distance code length tables */
537 index = 0;
538 while (index < nlen + ndist) {
539 uint16_t symbol;
540 int err = huffman_decode(state, &dyn_len_code, &symbol);
541 if (err != EOK)
542 return EOK;
543
544 if (symbol < 16) {
545 length[index] = symbol;
546 index++;
547 } else {
548 uint16_t len = 0;
549
550 if (symbol == 16) {
551 if (index == 0)
552 return EINVAL;
553
554 len = length[index - 1];
555 symbol = get_bits(state, 2) + 3;
556 CHECK_OVERRUN(*state);
557 } else if (symbol == 17) {
558 symbol = get_bits(state, 3) + 3;
559 CHECK_OVERRUN(*state);
560 } else {
561 symbol = get_bits(state, 7) + 11;
562 CHECK_OVERRUN(*state);
563 }
564
565 if (index + symbol > nlen + ndist)
566 return EINVAL;
567
568 while (symbol > 0) {
569 length[index] = len;
570 index++;
571 symbol--;
572 }
573 }
574 }
575
576 /* Check for end-of-block code */
577 if (length[256] == 0)
578 return EINVAL;
579
580 /* Build Huffman tables for literal/length codes */
581 rc = huffman_construct(&dyn_len_code, length, nlen);
582 if ((rc < 0) || ((rc > 0) && (dyn_len_code.count[0] + 1 != nlen)))
583 return EINVAL;
584
585 /* Build Huffman tables for distance codes */
586 rc = huffman_construct(&dyn_dist_code, length + nlen, ndist);
587 if ((rc < 0) || ((rc > 0) && (dyn_dist_code.count[0] + 1 != ndist)))
588 return EINVAL;
589
590 return inflate_codes(state, &dyn_len_code, &dyn_dist_code);
591}
592
593/** Inflate data
594 *
595 * @param src Source data buffer.
596 * @param srclen Source buffer size (bytes).
597 * @param dest Destination data buffer.
598 * @param destlen Destination buffer size (bytes).
599 *
600 * @return EOK on success.
601 * @return ENOENT on distance too large.
602 * @return EINVAL on invalid Huffman code or invalid deflate data.
603 * @return ELIMIT on input buffer overrun.
604 * @return ENOMEM on output buffer overrun.
605 *
606 */
607int inflate(const void *src, size_t srclen, void *dest, size_t destlen)
608{
609 /* Initialize the state */
610 inflate_state_t state;
611
612 state.dest = (uint8_t *) dest;
613 state.destlen = destlen;
614 state.destcnt = 0;
615
616 state.src = (const uint8_t *) src;
617 state.srclen = srclen;
618 state.srccnt = 0;
619
620 state.bitbuf = 0;
621 state.bitlen = 0;
622
623 state.overrun = false;
624
625 uint16_t last;
626 int ret = 0;
627
628 do {
629 /* Last block is indicated by a non-zero bit */
630 last = get_bits(&state, 1);
631 CHECK_OVERRUN(state);
632
633 /* Block type */
634 uint16_t type = get_bits(&state, 2);
635 CHECK_OVERRUN(state);
636
637 switch (type) {
638 case 0:
639 ret = inflate_stored(&state);
640 break;
641 case 1:
642 ret = inflate_fixed(&state, &len_code, &dist_code);
643 break;
644 case 2:
645 ret = inflate_dynamic(&state);
646 break;
647 default:
648 ret = EINVAL;
649 }
650 } while ((!last) && (ret == 0));
651
652 return ret;
653}
Note: See TracBrowser for help on using the repository browser.