DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
inflate.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file inflate.cpp
6 * @brief Bounded RFC 1951 DEFLATE decompressor - implementation.
7 *
8 * A compact canonical-Huffman INFLATE (the classic count[]/symbol[] decode, as
9 * in Mark Adler's "puff" reference) written from RFC 1951. Decoding is bit by
10 * bit - small and deterministic rather than fast, which suits the small messages
11 * this serves. All state is on the stack plus a caller-supplied table scratch;
12 * the output buffer doubles as the LZ77 window (see inflate.h).
13 */
14
15#include "inflate.h"
16
17#if DETWS_ENABLE_WS_DEFLATE
18
19#include <string.h>
20
21namespace
22{
23constexpr int MAXBITS = 15; // max bits in a Huffman code
24constexpr int MAXLCODES = 288; // max literal/length codes
25constexpr int MAXDCODES = 32; // max distance codes (30 used; 32 for safety)
26
27// Huffman decoding table: count[len] = #codes of that length, symbol[] = symbols
28// in canonical order. Both point into the caller's table scratch.
29struct Huffman
30{
31 short *count;
32 short *symbol;
33};
34
35// All the table memory inflate_raw() needs, laid over the caller's scratch.
36struct Tables
37{
38 short lcount[MAXBITS + 1];
39 short lsym[MAXLCODES];
40 short dcount[MAXBITS + 1];
41 short dsym[MAXDCODES];
42 short lengths[MAXLCODES + MAXDCODES]; // code lengths during construction
43};
44static_assert(sizeof(Tables) <= INFLATE_SCRATCH_SIZE, "bump INFLATE_SCRATCH_SIZE");
45
46// Decoder state.
47struct State
48{
49 uint8_t *out; // output buffer (also the back-reference window)
50 size_t outcap; // capacity
51 size_t outcnt; // bytes written
52 const uint8_t *in; // input
53 size_t inlen;
54 size_t incnt; // bytes consumed
55 int bitbuf; // bit accumulator (LSB first)
56 int bitcnt; // bits available in bitbuf
57 bool err; // ran out of input mid-element
58};
59
60// Length code base values and extra bits (RFC 1951 sec 3.2.5), codes 257..285.
61const short LEN_BASE[29] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27,
62 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
63const short LEN_EXTRA[29] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
64
65// Distance code base values and extra bits, codes 0..29.
66const short DIST_BASE[30] = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129,
67 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577};
68const short DIST_EXTRA[30] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6,
69 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
70
71// Pull @p need bits (LSB first). On end-of-input sets s->err and returns 0.
72int bits(State *s, int need)
73{
74 long val = s->bitbuf;
75 while (s->bitcnt < need)
76 {
77 if (s->incnt >= s->inlen)
78 {
79 s->err = true;
80 return 0;
81 }
82 val |= (long)(s->in[s->incnt++]) << s->bitcnt;
83 s->bitcnt += 8;
84 }
85 s->bitbuf = (int)(val >> need);
86 s->bitcnt -= need;
87 return (int)(val & ((1L << need) - 1));
88}
89
90// Decode one symbol using the canonical Huffman table. Returns the symbol, or -1
91// on end-of-input / an invalid code.
92int decode(State *s, const Huffman *h)
93{
94 int code = 0;
95 int first = 0;
96 int index = 0;
97 for (int len = 1; len <= MAXBITS; len++)
98 {
99 code |= bits(s, 1);
100 if (s->err)
101 return -1;
102 int count = h->count[len];
103 if (code - count < first) // length len codes start at 'first'
104 return h->symbol[index + (code - first)];
105 index += count;
106 first += count;
107 first <<= 1;
108 code <<= 1;
109 }
110 return -1; // ran past MAXBITS without a match
111}
112
113// Build a Huffman table from code lengths. Returns 0 if complete, >0 if
114// incomplete (left-over codes), <0 if over-subscribed.
115int construct(Huffman *h, const short *lengths, int n)
116{
117 for (int len = 0; len <= MAXBITS; len++)
118 h->count[len] = 0;
119 for (int sym = 0; sym < n; sym++)
120 h->count[lengths[sym]]++;
121 if (h->count[0] == n)
122 return 0; // no codes at all -> complete (empty)
123
124 int left = 1;
125 for (int len = 1; len <= MAXBITS; len++)
126 {
127 left <<= 1;
128 left -= h->count[len];
129 if (left < 0)
130 return left; // over-subscribed
131 }
132
133 short offs[MAXBITS + 1];
134 offs[1] = 0;
135 for (int len = 1; len < MAXBITS; len++)
136 offs[len + 1] = offs[len] + h->count[len];
137 for (int sym = 0; sym < n; sym++)
138 if (lengths[sym] != 0)
139 h->symbol[offs[lengths[sym]]++] = (short)sym;
140
141 return left; // 0 = complete, >0 = incomplete
142}
143
144// Decode literal/length + distance codes into the output. Returns 0 on the
145// end-of-block symbol, InflateResult::INFLATE_ERR_MALFORMED, or InflateResult::INFLATE_ERR_OVERFLOW.
146InflateResult codes(State *s, const Huffman *lencode, const Huffman *distcode)
147{
148 int symbol;
149 do
150 {
151 symbol = decode(s, lencode);
152 if (symbol < 0)
153 return InflateResult::INFLATE_ERR_MALFORMED;
154 if (symbol < 256)
155 {
156 if (s->outcnt >= s->outcap)
157 return InflateResult::INFLATE_ERR_OVERFLOW;
158 s->out[s->outcnt++] = (uint8_t)symbol;
159 }
160 else if (symbol > 256)
161 {
162 symbol -= 257;
163 if (symbol >= 29)
164 return InflateResult::INFLATE_ERR_MALFORMED; // invalid length code (286/287)
165 int len = LEN_BASE[symbol] + bits(s, LEN_EXTRA[symbol]);
166 if (s->err)
167 return InflateResult::INFLATE_ERR_MALFORMED;
168
169 symbol = decode(s, distcode);
170 if (symbol < 0 || symbol >= 30)
171 return InflateResult::INFLATE_ERR_MALFORMED;
172 size_t dist = (size_t)(DIST_BASE[symbol] + bits(s, DIST_EXTRA[symbol]));
173 if (s->err)
174 return InflateResult::INFLATE_ERR_MALFORMED;
175 if (dist > s->outcnt)
176 return InflateResult::INFLATE_ERR_MALFORMED; // reference before start of output
177 if (len > (int)(s->outcap - s->outcnt))
178 return InflateResult::INFLATE_ERR_OVERFLOW;
179 for (int k = 0; k < len; k++)
180 {
181 s->out[s->outcnt] = s->out[s->outcnt - dist];
182 s->outcnt++;
183 }
184 }
185 } while (symbol != 256); // 256 = end of block
186 return InflateResult::INFLATE_OK;
187}
188
189// Uncompressed (stored) block: byte-align, read LEN/NLEN, copy LEN bytes.
190InflateResult stored(State *s)
191{
192 s->bitbuf = 0;
193 s->bitcnt = 0; // discard bits to the next byte boundary
194 if (s->incnt + 4 > s->inlen)
195 return InflateResult::INFLATE_ERR_MALFORMED;
196 int len = s->in[s->incnt] | (s->in[s->incnt + 1] << 8);
197 int nlen = s->in[s->incnt + 2] | (s->in[s->incnt + 3] << 8);
198 s->incnt += 4;
199 if ((len ^ nlen) != 0xFFFF)
200 return InflateResult::INFLATE_ERR_MALFORMED; // NLEN must be ones-complement of LEN
201 if (s->incnt + (size_t)len > s->inlen)
202 return InflateResult::INFLATE_ERR_MALFORMED;
203 if ((size_t)len > s->outcap - s->outcnt)
204 return InflateResult::INFLATE_ERR_OVERFLOW;
205 memcpy(s->out + s->outcnt, s->in + s->incnt, (size_t)len);
206 s->incnt += (size_t)len;
207 s->outcnt += (size_t)len;
208 return InflateResult::INFLATE_OK;
209}
210
211// Fixed-Huffman block (RFC 1951 sec 3.2.6).
212InflateResult fixed(State *s, Huffman *lencode, Huffman *distcode, short *lengths)
213{
214 int sym = 0;
215 for (; sym < 144; sym++)
216 lengths[sym] = 8;
217 for (; sym < 256; sym++)
218 lengths[sym] = 9;
219 for (; sym < 280; sym++)
220 lengths[sym] = 7;
221 for (; sym < 288; sym++)
222 lengths[sym] = 8;
223 construct(lencode, lengths, 288);
224 for (sym = 0; sym < 30; sym++)
225 lengths[sym] = 5;
226 construct(distcode, lengths, 30);
227 return codes(s, lencode, distcode);
228}
229
230// Dynamic-Huffman block (RFC 1951 sec 3.2.7).
231InflateResult dynamic(State *s, Huffman *lencode, Huffman *distcode, short *lengths)
232{
233 static const short ORDER[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
234
235 int nlen = bits(s, 5) + 257;
236 int ndist = bits(s, 5) + 1;
237 int ncode = bits(s, 4) + 4;
238 if (s->err)
239 return InflateResult::INFLATE_ERR_MALFORMED;
240 // GCOVR_EXCL_LINE HLIT/HDIST are 5-bit, so nlen<=288==MAXLCODES and ndist<=32==MAXDCODES; the bound can never
241 // exceed
242 if (nlen > MAXLCODES || ndist > MAXDCODES)
243 return InflateResult::INFLATE_ERR_MALFORMED; // GCOVR_EXCL_LINE unreachable: nlen/ndist bounded to the maxes by
244 // the 5-bit fields
245
246 // Code-length code lengths, in the permuted order.
247 int index;
248 for (index = 0; index < ncode; index++)
249 lengths[ORDER[index]] = (short)bits(s, 3);
250 if (s->err)
251 return InflateResult::INFLATE_ERR_MALFORMED;
252 for (; index < 19; index++)
253 lengths[ORDER[index]] = 0;
254
255 // Build the code-length code (reuse lencode temporarily); it must be complete.
256 if (construct(lencode, lengths, 19) != 0)
257 return InflateResult::INFLATE_ERR_MALFORMED;
258
259 // Read the literal/length and distance code lengths.
260 index = 0;
261 while (index < nlen + ndist)
262 {
263 int symbol = decode(s, lencode);
264 if (symbol < 0)
265 return InflateResult::INFLATE_ERR_MALFORMED;
266 if (symbol < 16)
267 {
268 lengths[index++] = (short)symbol;
269 continue;
270 }
271 int repeat_len = 0;
272 int repeat;
273 if (symbol == 16)
274 {
275 if (index == 0)
276 return InflateResult::INFLATE_ERR_MALFORMED; // no previous length to repeat
277 repeat_len = lengths[index - 1];
278 repeat = 3 + bits(s, 2);
279 }
280 else if (symbol == 17)
281 {
282 repeat = 3 + bits(s, 3);
283 }
284 else // symbol == 18
285 {
286 repeat = 11 + bits(s, 7);
287 }
288 if (s->err)
289 return InflateResult::INFLATE_ERR_MALFORMED;
290 if (index + repeat > nlen + ndist)
291 return InflateResult::INFLATE_ERR_MALFORMED; // repeat past the end
292 while (repeat--)
293 lengths[index++] = (short)repeat_len;
294 }
295
296 if (lengths[256] == 0)
297 return InflateResult::INFLATE_ERR_MALFORMED; // no end-of-block code
298
299 // Build the literal/length and distance tables.
300 int err = construct(lencode, lengths, nlen);
301 if (err && (err < 0 || nlen != lencode->count[0] + lencode->count[1]))
302 return InflateResult::INFLATE_ERR_MALFORMED;
303 err = construct(distcode, lengths + nlen, ndist);
304 if (err && (err < 0 || ndist != distcode->count[0] + distcode->count[1]))
305 return InflateResult::INFLATE_ERR_MALFORMED; // incomplete distance code (ok only for 0/1 codes)
306
307 return codes(s, lencode, distcode);
308}
309} // namespace
310
311InflateResult inflate_raw(const uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_cap, size_t *out_len,
312 void *scratch, size_t scratch_len)
313{
314 if (scratch_len < INFLATE_SCRATCH_SIZE)
315 return InflateResult::INFLATE_ERR_SCRATCH;
316
317 Tables *t = (Tables *)scratch;
318 Huffman lencode = {t->lcount, t->lsym};
319 Huffman distcode = {t->dcount, t->dsym};
320
321 State s;
322 s.out = dst;
323 s.outcap = dst_cap;
324 s.outcnt = 0;
325 s.in = src;
326 s.inlen = src_len;
327 s.incnt = 0;
328 s.bitbuf = 0;
329 s.bitcnt = 0;
330 s.err = false;
331
332 int last = 0;
333 do
334 {
335 // Clean end-of-input at a block boundary: permessage-deflate streams have
336 // no final block, so this (not BFINAL) is the normal termination.
337 if (s.incnt >= s.inlen && s.bitcnt == 0)
338 break;
339
340 last = bits(&s, 1);
341 int type = bits(&s, 2);
342 if (s.err)
343 return InflateResult::INFLATE_ERR_MALFORMED;
344
345 InflateResult rc;
346 if (type == 0)
347 rc = stored(&s);
348 else if (type == 1)
349 rc = fixed(&s, &lencode, &distcode, t->lengths);
350 else if (type == 2)
351 rc = dynamic(&s, &lencode, &distcode, t->lengths);
352 else
353 return InflateResult::INFLATE_ERR_MALFORMED; // type 3 is reserved
354
355 if (rc != InflateResult::INFLATE_OK)
356 return rc;
357 } while (!last);
358
359 *out_len = s.outcnt;
360 return InflateResult::INFLATE_OK;
361}
362
363#endif // DETWS_ENABLE_WS_DEFLATE
Bounded RFC 1951 DEFLATE decompressor (INFLATE) - no heap.