File Coverage

infback.c
Criterion Covered Total %
statement 0 270 0.0
branch 0 216 0.0
condition n/a
subroutine n/a
pod n/a
total 0 486 0.0


line stmt bran cond sub pod time code
1             /* infback.c -- inflate using a call-back interface
2             * Copyright (C) 1995-2026 Mark Adler
3             * For conditions of distribution and use, see copyright notice in zlib.h
4             */
5              
6             /*
7             This code is largely copied from inflate.c. Normally either infback.o or
8             inflate.o would be linked into an application--not both. The interface
9             with inffast.c is retained so that optimized assembler-coded versions of
10             inflate_fast() can be used with either inflate.c or infback.c.
11             */
12              
13             #include "zutil.h"
14             #include "inftrees.h"
15             #include "inflate.h"
16             #include "inffast.h"
17              
18             /*
19             strm provides memory allocation functions in zalloc and zfree, or
20             Z_NULL to use the library memory allocation functions.
21              
22             windowBits is in the range 8..15, and window is a user-supplied
23             window and output buffer that is 2**windowBits bytes.
24             */
25 0           int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits,
26             unsigned char FAR *window, const char *version,
27             int stream_size) {
28             struct inflate_state FAR *state;
29              
30 0 0         if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
    0          
    0          
31             stream_size != (int)(sizeof(z_stream)))
32 0           return Z_VERSION_ERROR;
33 0 0         if (strm == Z_NULL || window == Z_NULL ||
    0          
    0          
34 0 0         windowBits < 8 || windowBits > 15)
35 0           return Z_STREAM_ERROR;
36 0           strm->msg = Z_NULL; /* in case we return an error */
37 0 0         if (strm->zalloc == (alloc_func)0) {
38             #ifdef Z_SOLO
39 0           return Z_STREAM_ERROR;
40             #else
41             strm->zalloc = zcalloc;
42             strm->opaque = (voidpf)0;
43             #endif
44             }
45 0 0         if (strm->zfree == (free_func)0)
46             #ifdef Z_SOLO
47 0           return Z_STREAM_ERROR;
48             #else
49             strm->zfree = zcfree;
50             #endif
51 0           state = (struct inflate_state FAR *)ZALLOC(strm, 1,
52             sizeof(struct inflate_state));
53 0 0         if (state == Z_NULL) return Z_MEM_ERROR;
54             Tracev((stderr, "inflate: allocated\n"));
55 0           strm->state = (struct internal_state FAR *)state;
56 0           state->dmax = 32768U;
57 0           state->wbits = (uInt)windowBits;
58 0           state->wsize = 1U << windowBits;
59 0           state->window = window;
60 0           state->wnext = 0;
61 0           state->whave = 0;
62 0           state->sane = 1;
63 0           return Z_OK;
64             }
65              
66             /* Macros for inflateBack(): */
67              
68             /* Load returned state from inflate_fast() */
69             #define LOAD() \
70             do { \
71             put = strm->next_out; \
72             left = strm->avail_out; \
73             next = strm->next_in; \
74             have = strm->avail_in; \
75             hold = state->hold; \
76             bits = state->bits; \
77             } while (0)
78              
79             /* Set state from registers for inflate_fast() */
80             #define RESTORE() \
81             do { \
82             strm->next_out = put; \
83             strm->avail_out = left; \
84             strm->next_in = next; \
85             strm->avail_in = have; \
86             state->hold = hold; \
87             state->bits = bits; \
88             } while (0)
89              
90             /* Clear the input bit accumulator */
91             #define INITBITS() \
92             do { \
93             hold = 0; \
94             bits = 0; \
95             } while (0)
96              
97             /* Assure that some input is available. If input is requested, but denied,
98             then return a Z_BUF_ERROR from inflateBack(). */
99             #define PULL() \
100             do { \
101             if (have == 0) { \
102             have = in(in_desc, &next); \
103             if (have == 0) { \
104             next = Z_NULL; \
105             ret = Z_BUF_ERROR; \
106             goto inf_leave; \
107             } \
108             } \
109             } while (0)
110              
111             /* Get a byte of input into the bit accumulator, or return from inflateBack()
112             with an error if there is no input available. */
113             #define PULLBYTE() \
114             do { \
115             PULL(); \
116             have--; \
117             hold += (unsigned long)(*next++) << bits; \
118             bits += 8; \
119             } while (0)
120              
121             /* Assure that there are at least n bits in the bit accumulator. If there is
122             not enough available input to do that, then return from inflateBack() with
123             an error. */
124             #define NEEDBITS(n) \
125             do { \
126             while (bits < (unsigned)(n)) \
127             PULLBYTE(); \
128             } while (0)
129              
130             /* Return the low n bits of the bit accumulator (n < 16) */
131             #define BITS(n) \
132             ((unsigned)hold & ((1U << (n)) - 1))
133              
134             /* Remove n bits from the bit accumulator */
135             #define DROPBITS(n) \
136             do { \
137             hold >>= (n); \
138             bits -= (unsigned)(n); \
139             } while (0)
140              
141             /* Remove zero to seven bits as needed to go to a byte boundary */
142             #define BYTEBITS() \
143             do { \
144             hold >>= bits & 7; \
145             bits -= bits & 7; \
146             } while (0)
147              
148             /* Assure that some output space is available, by writing out the window
149             if it's full. If the write fails, return from inflateBack() with a
150             Z_BUF_ERROR. */
151             #define ROOM() \
152             do { \
153             if (left == 0) { \
154             put = state->window; \
155             left = state->wsize; \
156             state->whave = left; \
157             if (out(out_desc, put, left)) { \
158             ret = Z_BUF_ERROR; \
159             goto inf_leave; \
160             } \
161             } \
162             } while (0)
163              
164             /*
165             strm provides the memory allocation functions and window buffer on input,
166             and provides information on the unused input on return. For Z_DATA_ERROR
167             returns, strm will also provide an error message.
168              
169             in() and out() are the call-back input and output functions. When
170             inflateBack() needs more input, it calls in(). When inflateBack() has
171             filled the window with output, or when it completes with data in the
172             window, it calls out() to write out the data. The application must not
173             change the provided input until in() is called again or inflateBack()
174             returns. The application must not change the window/output buffer until
175             inflateBack() returns.
176              
177             in() and out() are called with a descriptor parameter provided in the
178             inflateBack() call. This parameter can be a structure that provides the
179             information required to do the read or write, as well as accumulated
180             information on the input and output such as totals and check values.
181              
182             in() should return zero on failure. out() should return non-zero on
183             failure. If either in() or out() fails, than inflateBack() returns a
184             Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
185             was in() or out() that caused in the error. Otherwise, inflateBack()
186             returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
187             error, or Z_MEM_ERROR if it could not allocate memory for the state.
188             inflateBack() can also return Z_STREAM_ERROR if the input parameters
189             are not correct, i.e. strm is Z_NULL or the state was not initialized.
190             */
191 0           int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc,
192             out_func out, void FAR *out_desc) {
193             struct inflate_state FAR *state;
194             z_const unsigned char FAR *next; /* next input */
195             unsigned char FAR *put; /* next output */
196             unsigned have, left; /* available input and output */
197             unsigned long hold; /* bit buffer */
198             unsigned bits; /* bits in bit buffer */
199             unsigned copy; /* number of stored or match bytes to copy */
200             unsigned char FAR *from; /* where to copy match bytes from */
201             code here; /* current decoding table entry */
202             code last; /* parent table entry */
203             unsigned len; /* length to copy for repeats, bits to drop */
204             int ret; /* return code */
205             static const unsigned short order[19] = /* permutation of code lengths */
206             {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
207              
208             /* Check that the strm exists and that the state was initialized */
209 0 0         if (strm == Z_NULL || strm->state == Z_NULL)
    0          
210 0           return Z_STREAM_ERROR;
211 0           state = (struct inflate_state FAR *)strm->state;
212              
213             /* Reset the state */
214 0           strm->msg = Z_NULL;
215 0           state->mode = TYPE;
216 0           state->last = 0;
217 0           state->whave = 0;
218 0           next = strm->next_in;
219 0 0         have = next != Z_NULL ? strm->avail_in : 0;
220 0           hold = 0;
221 0           bits = 0;
222 0           put = state->window;
223 0           left = state->wsize;
224              
225             /* Inflate until end of block marked as last */
226             for (;;)
227 0           switch (state->mode) {
228 0           case TYPE:
229             /* determine and dispatch block type */
230 0 0         if (state->last) {
231 0           BYTEBITS();
232 0           state->mode = DONE;
233 0           break;
234             }
235 0 0         NEEDBITS(3);
    0          
    0          
236 0           state->last = BITS(1);
237 0           DROPBITS(1);
238 0           switch (BITS(2)) {
239 0           case 0: /* stored block */
240             Tracev((stderr, "inflate: stored block%s\n",
241             state->last ? " (last)" : ""));
242 0           state->mode = STORED;
243 0           break;
244 0           case 1: /* fixed block */
245 0           inflate_fixed(state);
246             Tracev((stderr, "inflate: fixed codes block%s\n",
247             state->last ? " (last)" : ""));
248 0           state->mode = LEN; /* decode codes */
249 0           break;
250 0           case 2: /* dynamic block */
251             Tracev((stderr, "inflate: dynamic codes block%s\n",
252             state->last ? " (last)" : ""));
253 0           state->mode = TABLE;
254 0           break;
255 0           default:
256 0           strm->msg = (z_const char *)"invalid block type";
257 0           state->mode = BAD;
258             }
259 0           DROPBITS(2);
260 0           break;
261              
262 0           case STORED:
263             /* get and verify stored block length */
264 0           BYTEBITS(); /* go to byte boundary */
265 0 0         NEEDBITS(32);
    0          
    0          
266 0 0         if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
267 0           strm->msg = (z_const char *)"invalid stored block lengths";
268 0           state->mode = BAD;
269 0           break;
270             }
271 0           state->length = (unsigned)hold & 0xffff;
272             Tracev((stderr, "inflate: stored length %u\n",
273             state->length));
274 0           INITBITS();
275              
276             /* copy stored block from input to output */
277 0 0         while (state->length != 0) {
278 0           copy = state->length;
279 0 0         PULL();
    0          
280 0 0         ROOM();
    0          
281 0 0         if (copy > have) copy = have;
282 0 0         if (copy > left) copy = left;
283 0           zmemcpy(put, next, copy);
284 0           have -= copy;
285 0           next += copy;
286 0           left -= copy;
287 0           put += copy;
288 0           state->length -= copy;
289             }
290             Tracev((stderr, "inflate: stored end\n"));
291 0           state->mode = TYPE;
292 0           break;
293              
294 0           case TABLE:
295             /* get dynamic table entries descriptor */
296 0 0         NEEDBITS(14);
    0          
    0          
297 0           state->nlen = BITS(5) + 257;
298 0           DROPBITS(5);
299 0           state->ndist = BITS(5) + 1;
300 0           DROPBITS(5);
301 0           state->ncode = BITS(4) + 4;
302 0           DROPBITS(4);
303             #ifndef PKZIP_BUG_WORKAROUND
304 0 0         if (state->nlen > 286 || state->ndist > 30) {
    0          
305 0           strm->msg = (z_const char *)
306             "too many length or distance symbols";
307 0           state->mode = BAD;
308 0           break;
309             }
310             #endif
311             Tracev((stderr, "inflate: table sizes ok\n"));
312              
313             /* get code length code lengths (not a typo) */
314 0           state->have = 0;
315 0 0         while (state->have < state->ncode) {
316 0 0         NEEDBITS(3);
    0          
    0          
317 0           state->lens[order[state->have++]] = (unsigned short)BITS(3);
318 0           DROPBITS(3);
319             }
320 0 0         while (state->have < 19)
321 0           state->lens[order[state->have++]] = 0;
322 0           state->next = state->codes;
323 0           state->lencode = (code const FAR *)(state->next);
324 0           state->lenbits = 7;
325 0           ret = inflate_table(CODES, state->lens, 19, &(state->next),
326 0           &(state->lenbits), state->work);
327 0 0         if (ret) {
328 0           strm->msg = (z_const char *)"invalid code lengths set";
329 0           state->mode = BAD;
330 0           break;
331             }
332             Tracev((stderr, "inflate: code lengths ok\n"));
333              
334             /* get length and distance code code lengths */
335 0           state->have = 0;
336 0 0         while (state->have < state->nlen + state->ndist) {
337             for (;;) {
338 0           here = state->lencode[BITS(state->lenbits)];
339 0 0         if ((unsigned)(here.bits) <= bits) break;
340 0 0         PULLBYTE();
    0          
341             }
342 0 0         if (here.val < 16) {
343 0           DROPBITS(here.bits);
344 0           state->lens[state->have++] = here.val;
345             }
346             else {
347 0 0         if (here.val == 16) {
348 0 0         NEEDBITS(here.bits + 2);
    0          
    0          
349 0           DROPBITS(here.bits);
350 0 0         if (state->have == 0) {
351 0           strm->msg = (z_const char *)
352             "invalid bit length repeat";
353 0           state->mode = BAD;
354 0           break;
355             }
356 0           len = (unsigned)(state->lens[state->have - 1]);
357 0           copy = 3 + BITS(2);
358 0           DROPBITS(2);
359             }
360 0 0         else if (here.val == 17) {
361 0 0         NEEDBITS(here.bits + 3);
    0          
    0          
362 0           DROPBITS(here.bits);
363 0           len = 0;
364 0           copy = 3 + BITS(3);
365 0           DROPBITS(3);
366             }
367             else {
368 0 0         NEEDBITS(here.bits + 7);
    0          
    0          
369 0           DROPBITS(here.bits);
370 0           len = 0;
371 0           copy = 11 + BITS(7);
372 0           DROPBITS(7);
373             }
374 0 0         if (state->have + copy > state->nlen + state->ndist) {
375 0           strm->msg = (z_const char *)
376             "invalid bit length repeat";
377 0           state->mode = BAD;
378 0           break;
379             }
380 0 0         while (copy--)
381 0           state->lens[state->have++] = (unsigned short)len;
382             }
383             }
384              
385             /* handle error breaks in while */
386 0 0         if (state->mode == BAD) break;
387              
388             /* check for end-of-block code (better have one) */
389 0 0         if (state->lens[256] == 0) {
390 0           strm->msg = (z_const char *)
391             "invalid code -- missing end-of-block";
392 0           state->mode = BAD;
393 0           break;
394             }
395              
396             /* build code tables -- note: do not change the lenbits or distbits
397             values here (9 and 6) without reading the comments in inftrees.h
398             concerning the ENOUGH constants, which depend on those values */
399 0           state->next = state->codes;
400 0           state->lencode = (code const FAR *)(state->next);
401 0           state->lenbits = 9;
402 0           ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
403 0           &(state->lenbits), state->work);
404 0 0         if (ret) {
405 0           strm->msg = (z_const char *)"invalid literal/lengths set";
406 0           state->mode = BAD;
407 0           break;
408             }
409 0           state->distcode = (code const FAR *)(state->next);
410 0           state->distbits = 6;
411 0           ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
412 0           &(state->next), &(state->distbits), state->work);
413 0 0         if (ret) {
414 0           strm->msg = (z_const char *)"invalid distances set";
415 0           state->mode = BAD;
416 0           break;
417             }
418             Tracev((stderr, "inflate: codes ok\n"));
419 0           state->mode = LEN;
420             /* fallthrough */
421              
422 0           case LEN:
423             /* use inflate_fast() if we have enough input and output */
424 0 0         if (have >= 6 && left >= 258) {
    0          
425 0           RESTORE();
426 0 0         if (state->whave < state->wsize)
427 0           state->whave = state->wsize - left;
428 0           inflate_fast(strm, state->wsize);
429 0           LOAD();
430 0           break;
431             }
432              
433             /* get a literal, length, or end-of-block code */
434             for (;;) {
435 0           here = state->lencode[BITS(state->lenbits)];
436 0 0         if ((unsigned)(here.bits) <= bits) break;
437 0 0         PULLBYTE();
    0          
438             }
439 0 0         if (here.op && (here.op & 0xf0) == 0) {
    0          
440 0           last = here;
441             for (;;) {
442 0           here = state->lencode[last.val +
443 0           (BITS(last.bits + last.op) >> last.bits)];
444 0 0         if ((unsigned)(last.bits + here.bits) <= bits) break;
445 0 0         PULLBYTE();
    0          
446             }
447 0           DROPBITS(last.bits);
448             }
449 0           DROPBITS(here.bits);
450 0           state->length = (unsigned)here.val;
451              
452             /* process literal */
453 0 0         if (here.op == 0) {
454             Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
455             "inflate: literal '%c'\n" :
456             "inflate: literal 0x%02x\n", here.val));
457 0 0         ROOM();
    0          
458 0           *put++ = (unsigned char)(state->length);
459 0           left--;
460 0           state->mode = LEN;
461 0           break;
462             }
463              
464             /* process end of block */
465 0 0         if (here.op & 32) {
466             Tracevv((stderr, "inflate: end of block\n"));
467 0           state->mode = TYPE;
468 0           break;
469             }
470              
471             /* invalid code */
472 0 0         if (here.op & 64) {
473 0           strm->msg = (z_const char *)"invalid literal/length code";
474 0           state->mode = BAD;
475 0           break;
476             }
477              
478             /* length code -- get extra bits, if any */
479 0           state->extra = (unsigned)(here.op) & 15;
480 0 0         if (state->extra != 0) {
481 0 0         NEEDBITS(state->extra);
    0          
    0          
482 0           state->length += BITS(state->extra);
483 0           DROPBITS(state->extra);
484             }
485             Tracevv((stderr, "inflate: length %u\n", state->length));
486              
487             /* get distance code */
488             for (;;) {
489 0           here = state->distcode[BITS(state->distbits)];
490 0 0         if ((unsigned)(here.bits) <= bits) break;
491 0 0         PULLBYTE();
    0          
492             }
493 0 0         if ((here.op & 0xf0) == 0) {
494 0           last = here;
495             for (;;) {
496 0           here = state->distcode[last.val +
497 0           (BITS(last.bits + last.op) >> last.bits)];
498 0 0         if ((unsigned)(last.bits + here.bits) <= bits) break;
499 0 0         PULLBYTE();
    0          
500             }
501 0           DROPBITS(last.bits);
502             }
503 0           DROPBITS(here.bits);
504 0 0         if (here.op & 64) {
505 0           strm->msg = (z_const char *)"invalid distance code";
506 0           state->mode = BAD;
507 0           break;
508             }
509 0           state->offset = (unsigned)here.val;
510              
511             /* get distance extra bits, if any */
512 0           state->extra = (unsigned)(here.op) & 15;
513 0 0         if (state->extra != 0) {
514 0 0         NEEDBITS(state->extra);
    0          
    0          
515 0           state->offset += BITS(state->extra);
516 0           DROPBITS(state->extra);
517             }
518 0 0         if (state->offset > state->wsize - (state->whave < state->wsize ?
519 0 0         left : 0)) {
520 0           strm->msg = (z_const char *)"invalid distance too far back";
521 0           state->mode = BAD;
522 0           break;
523             }
524             Tracevv((stderr, "inflate: distance %u\n", state->offset));
525              
526             /* copy match from window to output */
527             do {
528 0 0         ROOM();
    0          
529 0           copy = state->wsize - state->offset;
530 0 0         if (copy < left) {
531 0           from = put + copy;
532 0           copy = left - copy;
533             }
534             else {
535 0           from = put - state->offset;
536 0           copy = left;
537             }
538 0 0         if (copy > state->length) copy = state->length;
539 0           state->length -= copy;
540 0           left -= copy;
541             do {
542 0           *put++ = *from++;
543 0 0         } while (--copy);
544 0 0         } while (state->length != 0);
545 0           break;
546              
547 0           case DONE:
548             /* inflate stream terminated properly */
549 0           ret = Z_STREAM_END;
550 0           goto inf_leave;
551              
552 0           case BAD:
553 0           ret = Z_DATA_ERROR;
554 0           goto inf_leave;
555              
556 0           default:
557             /* can't happen, but makes compilers happy */
558 0           ret = Z_STREAM_ERROR;
559 0           goto inf_leave;
560             }
561              
562             /* Write leftover output and return unused input */
563 0           inf_leave:
564 0 0         if (left < state->wsize) {
565 0 0         if (out(out_desc, state->window, state->wsize - left) &&
    0          
566             ret == Z_STREAM_END)
567 0           ret = Z_BUF_ERROR;
568             }
569 0           strm->next_in = next;
570 0           strm->avail_in = have;
571 0           return ret;
572             }
573              
574 0           int ZEXPORT inflateBackEnd(z_streamp strm) {
575 0 0         if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
    0          
    0          
576 0           return Z_STREAM_ERROR;
577 0           ZFREE(strm, strm->state);
578 0           strm->state = Z_NULL;
579             Tracev((stderr, "inflate: end\n"));
580 0           return Z_OK;
581             }