xref: /illumos-gate/usr/src/contrib/zlib/inflate.c (revision 148fd93e)
1b8382935SToomas Soome /* inflate.c -- zlib decompression
2*148fd93eSToomas Soome  * Copyright (C) 1995-2022 Mark Adler
3b8382935SToomas Soome  * For conditions of distribution and use, see copyright notice in zlib.h
4b8382935SToomas Soome  */
5b8382935SToomas Soome 
6b8382935SToomas Soome /*
7b8382935SToomas Soome  * Change history:
8b8382935SToomas Soome  *
9b8382935SToomas Soome  * 1.2.beta0    24 Nov 2002
10b8382935SToomas Soome  * - First version -- complete rewrite of inflate to simplify code, avoid
11b8382935SToomas Soome  *   creation of window when not needed, minimize use of window when it is
12b8382935SToomas Soome  *   needed, make inffast.c even faster, implement gzip decoding, and to
13b8382935SToomas Soome  *   improve code readability and style over the previous zlib inflate code
14b8382935SToomas Soome  *
15b8382935SToomas Soome  * 1.2.beta1    25 Nov 2002
16b8382935SToomas Soome  * - Use pointers for available input and output checking in inffast.c
17b8382935SToomas Soome  * - Remove input and output counters in inffast.c
18b8382935SToomas Soome  * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
19b8382935SToomas Soome  * - Remove unnecessary second byte pull from length extra in inffast.c
20b8382935SToomas Soome  * - Unroll direct copy to three copies per loop in inffast.c
21b8382935SToomas Soome  *
22b8382935SToomas Soome  * 1.2.beta2    4 Dec 2002
23b8382935SToomas Soome  * - Change external routine names to reduce potential conflicts
24b8382935SToomas Soome  * - Correct filename to inffixed.h for fixed tables in inflate.c
25b8382935SToomas Soome  * - Make hbuf[] unsigned char to match parameter type in inflate.c
26b8382935SToomas Soome  * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
27b8382935SToomas Soome  *   to avoid negation problem on Alphas (64 bit) in inflate.c
28b8382935SToomas Soome  *
29b8382935SToomas Soome  * 1.2.beta3    22 Dec 2002
30b8382935SToomas Soome  * - Add comments on state->bits assertion in inffast.c
31b8382935SToomas Soome  * - Add comments on op field in inftrees.h
32b8382935SToomas Soome  * - Fix bug in reuse of allocated window after inflateReset()
33b8382935SToomas Soome  * - Remove bit fields--back to byte structure for speed
34b8382935SToomas Soome  * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
35b8382935SToomas Soome  * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
36b8382935SToomas Soome  * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
37b8382935SToomas Soome  * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
38b8382935SToomas Soome  * - Use local copies of stream next and avail values, as well as local bit
39b8382935SToomas Soome  *   buffer and bit count in inflate()--for speed when inflate_fast() not used
40b8382935SToomas Soome  *
41b8382935SToomas Soome  * 1.2.beta4    1 Jan 2003
42b8382935SToomas Soome  * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
43b8382935SToomas Soome  * - Move a comment on output buffer sizes from inffast.c to inflate.c
44b8382935SToomas Soome  * - Add comments in inffast.c to introduce the inflate_fast() routine
45b8382935SToomas Soome  * - Rearrange window copies in inflate_fast() for speed and simplification
46b8382935SToomas Soome  * - Unroll last copy for window match in inflate_fast()
47b8382935SToomas Soome  * - Use local copies of window variables in inflate_fast() for speed
48b8382935SToomas Soome  * - Pull out common wnext == 0 case for speed in inflate_fast()
49b8382935SToomas Soome  * - Make op and len in inflate_fast() unsigned for consistency
50b8382935SToomas Soome  * - Add FAR to lcode and dcode declarations in inflate_fast()
51b8382935SToomas Soome  * - Simplified bad distance check in inflate_fast()
52b8382935SToomas Soome  * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
53b8382935SToomas Soome  *   source file infback.c to provide a call-back interface to inflate for
54b8382935SToomas Soome  *   programs like gzip and unzip -- uses window as output buffer to avoid
55b8382935SToomas Soome  *   window copying
56b8382935SToomas Soome  *
57b8382935SToomas Soome  * 1.2.beta5    1 Jan 2003
58b8382935SToomas Soome  * - Improved inflateBack() interface to allow the caller to provide initial
59b8382935SToomas Soome  *   input in strm.
60b8382935SToomas Soome  * - Fixed stored blocks bug in inflateBack()
61b8382935SToomas Soome  *
62b8382935SToomas Soome  * 1.2.beta6    4 Jan 2003
63b8382935SToomas Soome  * - Added comments in inffast.c on effectiveness of POSTINC
64b8382935SToomas Soome  * - Typecasting all around to reduce compiler warnings
65b8382935SToomas Soome  * - Changed loops from while (1) or do {} while (1) to for (;;), again to
66b8382935SToomas Soome  *   make compilers happy
67b8382935SToomas Soome  * - Changed type of window in inflateBackInit() to unsigned char *
68b8382935SToomas Soome  *
69b8382935SToomas Soome  * 1.2.beta7    27 Jan 2003
70b8382935SToomas Soome  * - Changed many types to unsigned or unsigned short to avoid warnings
71b8382935SToomas Soome  * - Added inflateCopy() function
72b8382935SToomas Soome  *
73b8382935SToomas Soome  * 1.2.0        9 Mar 2003
74b8382935SToomas Soome  * - Changed inflateBack() interface to provide separate opaque descriptors
75b8382935SToomas Soome  *   for the in() and out() functions
76b8382935SToomas Soome  * - Changed inflateBack() argument and in_func typedef to swap the length
77b8382935SToomas Soome  *   and buffer address return values for the input function
78b8382935SToomas Soome  * - Check next_in and next_out for Z_NULL on entry to inflate()
79b8382935SToomas Soome  *
80b8382935SToomas Soome  * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
81b8382935SToomas Soome  */
82b8382935SToomas Soome 
83b8382935SToomas Soome #include "zutil.h"
84b8382935SToomas Soome #include "inftrees.h"
85b8382935SToomas Soome #include "inflate.h"
86b8382935SToomas Soome #include "inffast.h"
87b8382935SToomas Soome 
88b8382935SToomas Soome #ifdef MAKEFIXED
89b8382935SToomas Soome #  ifndef BUILDFIXED
90b8382935SToomas Soome #    define BUILDFIXED
91b8382935SToomas Soome #  endif
92b8382935SToomas Soome #endif
93b8382935SToomas Soome 
94b8382935SToomas Soome /* function prototypes */
95b8382935SToomas Soome local int inflateStateCheck OF((z_streamp strm));
96b8382935SToomas Soome local void fixedtables OF((struct inflate_state FAR *state));
97b8382935SToomas Soome local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
98b8382935SToomas Soome                            unsigned copy));
99b8382935SToomas Soome #ifdef BUILDFIXED
100b8382935SToomas Soome    void makefixed OF((void));
101b8382935SToomas Soome #endif
102b8382935SToomas Soome local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
103b8382935SToomas Soome                               unsigned len));
104b8382935SToomas Soome 
inflateStateCheck(z_streamp strm)105b8382935SToomas Soome local int inflateStateCheck(z_streamp strm)
106b8382935SToomas Soome {
107b8382935SToomas Soome     struct inflate_state FAR *state;
108b8382935SToomas Soome     if (strm == Z_NULL ||
109b8382935SToomas Soome         strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
110b8382935SToomas Soome         return 1;
111b8382935SToomas Soome     state = (struct inflate_state FAR *)strm->state;
112b8382935SToomas Soome     if (state == Z_NULL || state->strm != strm ||
113b8382935SToomas Soome         state->mode < HEAD || state->mode > SYNC)
114b8382935SToomas Soome         return 1;
115b8382935SToomas Soome     return 0;
116b8382935SToomas Soome }
117b8382935SToomas Soome 
inflateResetKeep(z_streamp strm)118b8382935SToomas Soome int ZEXPORT inflateResetKeep(z_streamp strm)
119b8382935SToomas Soome {
120b8382935SToomas Soome     struct inflate_state FAR *state;
121b8382935SToomas Soome 
122b8382935SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
123b8382935SToomas Soome     state = (struct inflate_state FAR *)strm->state;
124b8382935SToomas Soome     strm->total_in = strm->total_out = state->total = 0;
125b8382935SToomas Soome     strm->msg = Z_NULL;
126b8382935SToomas Soome     if (state->wrap)        /* to support ill-conceived Java test suite */
127b8382935SToomas Soome         strm->adler = state->wrap & 1;
128b8382935SToomas Soome     state->mode = HEAD;
129b8382935SToomas Soome     state->last = 0;
130b8382935SToomas Soome     state->havedict = 0;
131*148fd93eSToomas Soome     state->flags = -1;
132b8382935SToomas Soome     state->dmax = 32768U;
133b8382935SToomas Soome     state->head = Z_NULL;
134b8382935SToomas Soome     state->hold = 0;
135b8382935SToomas Soome     state->bits = 0;
136b8382935SToomas Soome     state->lencode = state->distcode = state->next = state->codes;
137b8382935SToomas Soome     state->sane = 1;
138b8382935SToomas Soome     state->back = -1;
139b8382935SToomas Soome     Tracev((stderr, "inflate: reset\n"));
140b8382935SToomas Soome     return Z_OK;
141b8382935SToomas Soome }
142b8382935SToomas Soome 
inflateReset(z_streamp strm)143b8382935SToomas Soome int ZEXPORT inflateReset(z_streamp strm)
144b8382935SToomas Soome {
145b8382935SToomas Soome     struct inflate_state FAR *state;
146b8382935SToomas Soome 
147b8382935SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
148b8382935SToomas Soome     state = (struct inflate_state FAR *)strm->state;
149b8382935SToomas Soome     state->wsize = 0;
150b8382935SToomas Soome     state->whave = 0;
151b8382935SToomas Soome     state->wnext = 0;
152b8382935SToomas Soome     return inflateResetKeep(strm);
153b8382935SToomas Soome }
154b8382935SToomas Soome 
inflateReset2(z_streamp strm,int windowBits)155b8382935SToomas Soome int ZEXPORT inflateReset2(z_streamp strm, int windowBits)
156b8382935SToomas Soome {
157b8382935SToomas Soome     int wrap;
158b8382935SToomas Soome     struct inflate_state FAR *state;
159b8382935SToomas Soome 
160b8382935SToomas Soome     /* get the state */
161b8382935SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
162b8382935SToomas Soome     state = (struct inflate_state FAR *)strm->state;
163b8382935SToomas Soome 
164b8382935SToomas Soome     /* extract wrap request from windowBits parameter */
165b8382935SToomas Soome     if (windowBits < 0) {
166b8382935SToomas Soome         wrap = 0;
167b8382935SToomas Soome         windowBits = -windowBits;
168b8382935SToomas Soome     }
169b8382935SToomas Soome     else {
170b8382935SToomas Soome         wrap = (windowBits >> 4) + 5;
171b8382935SToomas Soome #ifdef GUNZIP
172b8382935SToomas Soome         if (windowBits < 48)
173b8382935SToomas Soome             windowBits &= 15;
174b8382935SToomas Soome #endif
175b8382935SToomas Soome     }
176b8382935SToomas Soome 
177b8382935SToomas Soome     /* set number of window bits, free window if different */
178b8382935SToomas Soome     if (windowBits && (windowBits < 8 || windowBits > 15))
179b8382935SToomas Soome         return Z_STREAM_ERROR;
180b8382935SToomas Soome     if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
181b8382935SToomas Soome         ZFREE(strm, state->window);
182b8382935SToomas Soome         state->window = Z_NULL;
183b8382935SToomas Soome     }
184b8382935SToomas Soome 
185b8382935SToomas Soome     /* update state and reset the rest of it */
186b8382935SToomas Soome     state->wrap = wrap;
187b8382935SToomas Soome     state->wbits = (unsigned)windowBits;
188b8382935SToomas Soome     return inflateReset(strm);
189b8382935SToomas Soome }
190b8382935SToomas Soome 
inflateInit2_(z_streamp strm,int windowBits,const char * version,int stream_size)191b8382935SToomas Soome int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version,
192b8382935SToomas Soome     int stream_size)
193b8382935SToomas Soome {
194b8382935SToomas Soome     int ret;
195b8382935SToomas Soome     struct inflate_state FAR *state;
196b8382935SToomas Soome 
197b8382935SToomas Soome     if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
198b8382935SToomas Soome         stream_size != (int)(sizeof(z_stream)))
199b8382935SToomas Soome         return Z_VERSION_ERROR;
200b8382935SToomas Soome     if (strm == Z_NULL) return Z_STREAM_ERROR;
201b8382935SToomas Soome     strm->msg = Z_NULL;                 /* in case we return an error */
202b8382935SToomas Soome     if (strm->zalloc == (alloc_func)0) {
203b8382935SToomas Soome #ifdef Z_SOLO
204b8382935SToomas Soome         return Z_STREAM_ERROR;
205b8382935SToomas Soome #else
206b8382935SToomas Soome         strm->zalloc = zcalloc;
207b8382935SToomas Soome         strm->opaque = (voidpf)0;
208b8382935SToomas Soome #endif
209b8382935SToomas Soome     }
210b8382935SToomas Soome     if (strm->zfree == (free_func)0)
211b8382935SToomas Soome #ifdef Z_SOLO
212b8382935SToomas Soome         return Z_STREAM_ERROR;
213b8382935SToomas Soome #else
214b8382935SToomas Soome         strm->zfree = zcfree;
215b8382935SToomas Soome #endif
216b8382935SToomas Soome     state = (struct inflate_state FAR *)
217b8382935SToomas Soome             ZALLOC(strm, 1, sizeof(struct inflate_state));
218b8382935SToomas Soome     if (state == Z_NULL) return Z_MEM_ERROR;
219b8382935SToomas Soome     Tracev((stderr, "inflate: allocated\n"));
220b8382935SToomas Soome     strm->state = (struct internal_state FAR *)state;
221b8382935SToomas Soome     state->strm = strm;
222b8382935SToomas Soome     state->window = Z_NULL;
223b8382935SToomas Soome     state->mode = HEAD;     /* to pass state test in inflateReset2() */
224b8382935SToomas Soome     ret = inflateReset2(strm, windowBits);
225b8382935SToomas Soome     if (ret != Z_OK) {
226b8382935SToomas Soome         ZFREE(strm, state);
227b8382935SToomas Soome         strm->state = Z_NULL;
228b8382935SToomas Soome     }
229b8382935SToomas Soome     return ret;
230b8382935SToomas Soome }
231b8382935SToomas Soome 
inflateInit_(z_streamp strm,const char * version,int stream_size)232b8382935SToomas Soome int ZEXPORT inflateInit_(z_streamp strm, const char *version, int stream_size)
233b8382935SToomas Soome {
234b8382935SToomas Soome     return inflateInit2_(strm, DEF_WBITS, version, stream_size);
235b8382935SToomas Soome }
236b8382935SToomas Soome 
inflatePrime(z_streamp strm,int bits,int value)237b8382935SToomas Soome int ZEXPORT inflatePrime(z_streamp strm, int bits, int value)
238b8382935SToomas Soome {
239b8382935SToomas Soome     struct inflate_state FAR *state;
240b8382935SToomas Soome 
241b8382935SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
242b8382935SToomas Soome     state = (struct inflate_state FAR *)strm->state;
243b8382935SToomas Soome     if (bits < 0) {
244b8382935SToomas Soome         state->hold = 0;
245b8382935SToomas Soome         state->bits = 0;
246b8382935SToomas Soome         return Z_OK;
247b8382935SToomas Soome     }
248b8382935SToomas Soome     if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;
249b8382935SToomas Soome     value &= (1L << bits) - 1;
250b8382935SToomas Soome     state->hold += (unsigned)value << state->bits;
251b8382935SToomas Soome     state->bits += (uInt)bits;
252b8382935SToomas Soome     return Z_OK;
253b8382935SToomas Soome }
254b8382935SToomas Soome 
255b8382935SToomas Soome /*
256b8382935SToomas Soome    Return state with length and distance decoding tables and index sizes set to
257b8382935SToomas Soome    fixed code decoding.  Normally this returns fixed tables from inffixed.h.
258b8382935SToomas Soome    If BUILDFIXED is defined, then instead this routine builds the tables the
259b8382935SToomas Soome    first time it's called, and returns those tables the first time and
260b8382935SToomas Soome    thereafter.  This reduces the size of the code by about 2K bytes, in
261b8382935SToomas Soome    exchange for a little execution time.  However, BUILDFIXED should not be
262b8382935SToomas Soome    used for threaded applications, since the rewriting of the tables and virgin
263b8382935SToomas Soome    may not be thread-safe.
264b8382935SToomas Soome  */
fixedtables(struct inflate_state FAR * state)265b8382935SToomas Soome local void fixedtables(struct inflate_state FAR *state)
266b8382935SToomas Soome {
267b8382935SToomas Soome #ifdef BUILDFIXED
268b8382935SToomas Soome     static int virgin = 1;
269b8382935SToomas Soome     static code *lenfix, *distfix;
270b8382935SToomas Soome     static code fixed[544];
271b8382935SToomas Soome 
272b8382935SToomas Soome     /* build fixed huffman tables if first call (may not be thread safe) */
273b8382935SToomas Soome     if (virgin) {
274b8382935SToomas Soome         unsigned sym, bits;
275b8382935SToomas Soome         static code *next;
276b8382935SToomas Soome 
277b8382935SToomas Soome         /* literal/length table */
278b8382935SToomas Soome         sym = 0;
279b8382935SToomas Soome         while (sym < 144) state->lens[sym++] = 8;
280b8382935SToomas Soome         while (sym < 256) state->lens[sym++] = 9;
281b8382935SToomas Soome         while (sym < 280) state->lens[sym++] = 7;
282b8382935SToomas Soome         while (sym < 288) state->lens[sym++] = 8;
283b8382935SToomas Soome         next = fixed;
284b8382935SToomas Soome         lenfix = next;
285b8382935SToomas Soome         bits = 9;
286b8382935SToomas Soome         inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
287b8382935SToomas Soome 
288b8382935SToomas Soome         /* distance table */
289b8382935SToomas Soome         sym = 0;
290b8382935SToomas Soome         while (sym < 32) state->lens[sym++] = 5;
291b8382935SToomas Soome         distfix = next;
292b8382935SToomas Soome         bits = 5;
293b8382935SToomas Soome         inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
294b8382935SToomas Soome 
295b8382935SToomas Soome         /* do this just once */
296b8382935SToomas Soome         virgin = 0;
297b8382935SToomas Soome     }
298b8382935SToomas Soome #else /* !BUILDFIXED */
299b8382935SToomas Soome #   include "inffixed.h"
300b8382935SToomas Soome #endif /* BUILDFIXED */
301b8382935SToomas Soome     state->lencode = lenfix;
302b8382935SToomas Soome     state->lenbits = 9;
303b8382935SToomas Soome     state->distcode = distfix;
304b8382935SToomas Soome     state->distbits = 5;
305b8382935SToomas Soome }
306b8382935SToomas Soome 
307b8382935SToomas Soome #ifdef MAKEFIXED
308b8382935SToomas Soome #include <stdio.h>
309b8382935SToomas Soome 
310b8382935SToomas Soome /*
311b8382935SToomas Soome    Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
312b8382935SToomas Soome    defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
313b8382935SToomas Soome    those tables to stdout, which would be piped to inffixed.h.  A small program
314b8382935SToomas Soome    can simply call makefixed to do this:
315b8382935SToomas Soome 
316b8382935SToomas Soome     void makefixed(void);
317b8382935SToomas Soome 
318b8382935SToomas Soome     int main(void)
319b8382935SToomas Soome     {
320b8382935SToomas Soome         makefixed();
321b8382935SToomas Soome         return 0;
322b8382935SToomas Soome     }
323b8382935SToomas Soome 
324b8382935SToomas Soome    Then that can be linked with zlib built with MAKEFIXED defined and run:
325b8382935SToomas Soome 
326b8382935SToomas Soome     a.out > inffixed.h
327b8382935SToomas Soome  */
makefixed(void)328b8382935SToomas Soome void makefixed(void)
329b8382935SToomas Soome {
330b8382935SToomas Soome     unsigned low, size;
331b8382935SToomas Soome     struct inflate_state state;
332b8382935SToomas Soome 
333b8382935SToomas Soome     fixedtables(&state);
334b8382935SToomas Soome     puts("    /* inffixed.h -- table for decoding fixed codes");
335b8382935SToomas Soome     puts("     * Generated automatically by makefixed().");
336b8382935SToomas Soome     puts("     */");
337b8382935SToomas Soome     puts("");
338b8382935SToomas Soome     puts("    /* WARNING: this file should *not* be used by applications.");
339b8382935SToomas Soome     puts("       It is part of the implementation of this library and is");
340b8382935SToomas Soome     puts("       subject to change. Applications should only use zlib.h.");
341b8382935SToomas Soome     puts("     */");
342b8382935SToomas Soome     puts("");
343b8382935SToomas Soome     size = 1U << 9;
344b8382935SToomas Soome     printf("    static const code lenfix[%u] = {", size);
345b8382935SToomas Soome     low = 0;
346b8382935SToomas Soome     for (;;) {
347b8382935SToomas Soome         if ((low % 7) == 0) printf("\n        ");
348b8382935SToomas Soome         printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
349b8382935SToomas Soome                state.lencode[low].bits, state.lencode[low].val);
350b8382935SToomas Soome         if (++low == size) break;
351b8382935SToomas Soome         putchar(',');
352b8382935SToomas Soome     }
353b8382935SToomas Soome     puts("\n    };");
354b8382935SToomas Soome     size = 1U << 5;
355b8382935SToomas Soome     printf("\n    static const code distfix[%u] = {", size);
356b8382935SToomas Soome     low = 0;
357b8382935SToomas Soome     for (;;) {
358b8382935SToomas Soome         if ((low % 6) == 0) printf("\n        ");
359b8382935SToomas Soome         printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
360b8382935SToomas Soome                state.distcode[low].val);
361b8382935SToomas Soome         if (++low == size) break;
362b8382935SToomas Soome         putchar(',');
363b8382935SToomas Soome     }
364b8382935SToomas Soome     puts("\n    };");
365b8382935SToomas Soome }
366b8382935SToomas Soome #endif /* MAKEFIXED */
367b8382935SToomas Soome 
368b8382935SToomas Soome /*
369b8382935SToomas Soome    Update the window with the last wsize (normally 32K) bytes written before
370b8382935SToomas Soome    returning.  If window does not exist yet, create it.  This is only called
371b8382935SToomas Soome    when a window is already in use, or when output has been written during this
372b8382935SToomas Soome    inflate call, but the end of the deflate stream has not been reached yet.
373b8382935SToomas Soome    It is also called to create a window for dictionary data when a dictionary
374b8382935SToomas Soome    is loaded.
375b8382935SToomas Soome 
376b8382935SToomas Soome    Providing output buffers larger than 32K to inflate() should provide a speed
377b8382935SToomas Soome    advantage, since only the last 32K of output is copied to the sliding window
378b8382935SToomas Soome    upon return from inflate(), and since all distances after the first 32K of
379b8382935SToomas Soome    output will fall in the output data, making match copies simpler and faster.
380b8382935SToomas Soome    The advantage may be dependent on the size of the processor's data caches.
381b8382935SToomas Soome  */
updatewindow(z_streamp strm,const Bytef * end,unsigned copy)382b8382935SToomas Soome local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy)
383b8382935SToomas Soome {
384b8382935SToomas Soome     struct inflate_state FAR *state;
385b8382935SToomas Soome     unsigned dist;
386b8382935SToomas Soome 
387b8382935SToomas Soome     state = (struct inflate_state FAR *)strm->state;
388b8382935SToomas Soome 
389b8382935SToomas Soome     /* if it hasn't been done already, allocate space for the window */
390b8382935SToomas Soome     if (state->window == Z_NULL) {
391b8382935SToomas Soome         state->window = (unsigned char FAR *)
392b8382935SToomas Soome                         ZALLOC(strm, 1U << state->wbits,
393b8382935SToomas Soome                                sizeof(unsigned char));
394b8382935SToomas Soome         if (state->window == Z_NULL) return 1;
395b8382935SToomas Soome     }
396b8382935SToomas Soome 
397b8382935SToomas Soome     /* if window not in use yet, initialize */
398b8382935SToomas Soome     if (state->wsize == 0) {
399b8382935SToomas Soome         state->wsize = 1U << state->wbits;
400b8382935SToomas Soome         state->wnext = 0;
401b8382935SToomas Soome         state->whave = 0;
402b8382935SToomas Soome     }
403b8382935SToomas Soome 
404b8382935SToomas Soome     /* copy state->wsize or less output bytes into the circular window */
405b8382935SToomas Soome     if (copy >= state->wsize) {
406b8382935SToomas Soome         zmemcpy(state->window, end - state->wsize, state->wsize);
407b8382935SToomas Soome         state->wnext = 0;
408b8382935SToomas Soome         state->whave = state->wsize;
409b8382935SToomas Soome     }
410b8382935SToomas Soome     else {
411b8382935SToomas Soome         dist = state->wsize - state->wnext;
412b8382935SToomas Soome         if (dist > copy) dist = copy;
413b8382935SToomas Soome         zmemcpy(state->window + state->wnext, end - copy, dist);
414b8382935SToomas Soome         copy -= dist;
415b8382935SToomas Soome         if (copy) {
416b8382935SToomas Soome             zmemcpy(state->window, end - copy, copy);
417b8382935SToomas Soome             state->wnext = copy;
418b8382935SToomas Soome             state->whave = state->wsize;
419b8382935SToomas Soome         }
420b8382935SToomas Soome         else {
421b8382935SToomas Soome             state->wnext += dist;
422b8382935SToomas Soome             if (state->wnext == state->wsize) state->wnext = 0;
423b8382935SToomas Soome             if (state->whave < state->wsize) state->whave += dist;
424b8382935SToomas Soome         }
425b8382935SToomas Soome     }
426b8382935SToomas Soome     return 0;
427b8382935SToomas Soome }
428b8382935SToomas Soome 
429b8382935SToomas Soome /* Macros for inflate(): */
430b8382935SToomas Soome 
431b8382935SToomas Soome /* check function to use adler32() for zlib or crc32() for gzip */
432b8382935SToomas Soome #ifdef GUNZIP
433*148fd93eSToomas Soome #  define UPDATE_CHECK(check, buf, len) \
434b8382935SToomas Soome     (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
435b8382935SToomas Soome #else
436*148fd93eSToomas Soome #  define UPDATE_CHECK(check, buf, len) adler32(check, buf, len)
437b8382935SToomas Soome #endif
438b8382935SToomas Soome 
439b8382935SToomas Soome /* check macros for header crc */
440b8382935SToomas Soome #ifdef GUNZIP
441b8382935SToomas Soome #  define CRC2(check, word) \
442b8382935SToomas Soome     do { \
443b8382935SToomas Soome         hbuf[0] = (unsigned char)(word); \
444b8382935SToomas Soome         hbuf[1] = (unsigned char)((word) >> 8); \
445b8382935SToomas Soome         check = crc32(check, hbuf, 2); \
446b8382935SToomas Soome     } while (0)
447b8382935SToomas Soome 
448b8382935SToomas Soome #  define CRC4(check, word) \
449b8382935SToomas Soome     do { \
450b8382935SToomas Soome         hbuf[0] = (unsigned char)(word); \
451b8382935SToomas Soome         hbuf[1] = (unsigned char)((word) >> 8); \
452b8382935SToomas Soome         hbuf[2] = (unsigned char)((word) >> 16); \
453b8382935SToomas Soome         hbuf[3] = (unsigned char)((word) >> 24); \
454b8382935SToomas Soome         check = crc32(check, hbuf, 4); \
455b8382935SToomas Soome     } while (0)
456b8382935SToomas Soome #endif
457b8382935SToomas Soome 
458b8382935SToomas Soome /* Load registers with state in inflate() for speed */
459b8382935SToomas Soome #define LOAD() \
460b8382935SToomas Soome     do { \
461b8382935SToomas Soome         put = strm->next_out; \
462b8382935SToomas Soome         left = strm->avail_out; \
463b8382935SToomas Soome         next = strm->next_in; \
464b8382935SToomas Soome         have = strm->avail_in; \
465b8382935SToomas Soome         hold = state->hold; \
466b8382935SToomas Soome         bits = state->bits; \
467b8382935SToomas Soome     } while (0)
468b8382935SToomas Soome 
469b8382935SToomas Soome /* Restore state from registers in inflate() */
470b8382935SToomas Soome #define RESTORE() \
471b8382935SToomas Soome     do { \
472b8382935SToomas Soome         strm->next_out = put; \
473b8382935SToomas Soome         strm->avail_out = left; \
474b8382935SToomas Soome         strm->next_in = next; \
475b8382935SToomas Soome         strm->avail_in = have; \
476b8382935SToomas Soome         state->hold = hold; \
477b8382935SToomas Soome         state->bits = bits; \
478b8382935SToomas Soome     } while (0)
479b8382935SToomas Soome 
480b8382935SToomas Soome /* Clear the input bit accumulator */
481b8382935SToomas Soome #define INITBITS() \
482b8382935SToomas Soome     do { \
483b8382935SToomas Soome         hold = 0; \
484b8382935SToomas Soome         bits = 0; \
485b8382935SToomas Soome     } while (0)
486b8382935SToomas Soome 
487b8382935SToomas Soome /* Get a byte of input into the bit accumulator, or return from inflate()
488b8382935SToomas Soome    if there is no input available. */
489b8382935SToomas Soome #define PULLBYTE() \
490b8382935SToomas Soome     do { \
491b8382935SToomas Soome         if (have == 0) goto inf_leave; \
492b8382935SToomas Soome         have--; \
493b8382935SToomas Soome         hold += (unsigned long)(*next++) << bits; \
494b8382935SToomas Soome         bits += 8; \
495b8382935SToomas Soome     } while (0)
496b8382935SToomas Soome 
497b8382935SToomas Soome /* Assure that there are at least n bits in the bit accumulator.  If there is
498b8382935SToomas Soome    not enough available input to do that, then return from inflate(). */
499b8382935SToomas Soome #define NEEDBITS(n) \
500b8382935SToomas Soome     do { \
501b8382935SToomas Soome         while (bits < (unsigned)(n)) \
502b8382935SToomas Soome             PULLBYTE(); \
503b8382935SToomas Soome     } while (0)
504b8382935SToomas Soome 
505b8382935SToomas Soome /* Return the low n bits of the bit accumulator (n < 16) */
506b8382935SToomas Soome #define BITS(n) \
507b8382935SToomas Soome     ((unsigned)hold & ((1U << (n)) - 1))
508b8382935SToomas Soome 
509b8382935SToomas Soome /* Remove n bits from the bit accumulator */
510b8382935SToomas Soome #define DROPBITS(n) \
511b8382935SToomas Soome     do { \
512b8382935SToomas Soome         hold >>= (n); \
513b8382935SToomas Soome         bits -= (unsigned)(n); \
514b8382935SToomas Soome     } while (0)
515b8382935SToomas Soome 
516b8382935SToomas Soome /* Remove zero to seven bits as needed to go to a byte boundary */
517b8382935SToomas Soome #define BYTEBITS() \
518b8382935SToomas Soome     do { \
519b8382935SToomas Soome         hold >>= bits & 7; \
520b8382935SToomas Soome         bits -= bits & 7; \
521b8382935SToomas Soome     } while (0)
522b8382935SToomas Soome 
523b8382935SToomas Soome /*
524b8382935SToomas Soome    inflate() uses a state machine to process as much input data and generate as
525b8382935SToomas Soome    much output data as possible before returning.  The state machine is
526b8382935SToomas Soome    structured roughly as follows:
527b8382935SToomas Soome 
528b8382935SToomas Soome     for (;;) switch (state) {
529b8382935SToomas Soome     ...
530b8382935SToomas Soome     case STATEn:
531b8382935SToomas Soome         if (not enough input data or output space to make progress)
532b8382935SToomas Soome             return;
533b8382935SToomas Soome         ... make progress ...
534b8382935SToomas Soome         state = STATEm;
535b8382935SToomas Soome         break;
536b8382935SToomas Soome     ...
537b8382935SToomas Soome     }
538b8382935SToomas Soome 
539b8382935SToomas Soome    so when inflate() is called again, the same case is attempted again, and
540b8382935SToomas Soome    if the appropriate resources are provided, the machine proceeds to the
541b8382935SToomas Soome    next state.  The NEEDBITS() macro is usually the way the state evaluates
542b8382935SToomas Soome    whether it can proceed or should return.  NEEDBITS() does the return if
543b8382935SToomas Soome    the requested bits are not available.  The typical use of the BITS macros
544b8382935SToomas Soome    is:
545b8382935SToomas Soome 
546b8382935SToomas Soome         NEEDBITS(n);
547b8382935SToomas Soome         ... do something with BITS(n) ...
548b8382935SToomas Soome         DROPBITS(n);
549b8382935SToomas Soome 
550b8382935SToomas Soome    where NEEDBITS(n) either returns from inflate() if there isn't enough
551b8382935SToomas Soome    input left to load n bits into the accumulator, or it continues.  BITS(n)
552b8382935SToomas Soome    gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
553b8382935SToomas Soome    the low n bits off the accumulator.  INITBITS() clears the accumulator
554b8382935SToomas Soome    and sets the number of available bits to zero.  BYTEBITS() discards just
555b8382935SToomas Soome    enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
556b8382935SToomas Soome    and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
557b8382935SToomas Soome 
558b8382935SToomas Soome    NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
559b8382935SToomas Soome    if there is no input available.  The decoding of variable length codes uses
560b8382935SToomas Soome    PULLBYTE() directly in order to pull just enough bytes to decode the next
561b8382935SToomas Soome    code, and no more.
562b8382935SToomas Soome 
563b8382935SToomas Soome    Some states loop until they get enough input, making sure that enough
564b8382935SToomas Soome    state information is maintained to continue the loop where it left off
565b8382935SToomas Soome    if NEEDBITS() returns in the loop.  For example, want, need, and keep
566b8382935SToomas Soome    would all have to actually be part of the saved state in case NEEDBITS()
567b8382935SToomas Soome    returns:
568b8382935SToomas Soome 
569b8382935SToomas Soome     case STATEw:
570b8382935SToomas Soome         while (want < need) {
571b8382935SToomas Soome             NEEDBITS(n);
572b8382935SToomas Soome             keep[want++] = BITS(n);
573b8382935SToomas Soome             DROPBITS(n);
574b8382935SToomas Soome         }
575b8382935SToomas Soome         state = STATEx;
576b8382935SToomas Soome     case STATEx:
577b8382935SToomas Soome 
578b8382935SToomas Soome    As shown above, if the next state is also the next case, then the break
579b8382935SToomas Soome    is omitted.
580b8382935SToomas Soome 
581b8382935SToomas Soome    A state may also return if there is not enough output space available to
582b8382935SToomas Soome    complete that state.  Those states are copying stored data, writing a
583b8382935SToomas Soome    literal byte, and copying a matching string.
584b8382935SToomas Soome 
585b8382935SToomas Soome    When returning, a "goto inf_leave" is used to update the total counters,
586b8382935SToomas Soome    update the check value, and determine whether any progress has been made
587b8382935SToomas Soome    during that inflate() call in order to return the proper return code.
588b8382935SToomas Soome    Progress is defined as a change in either strm->avail_in or strm->avail_out.
589b8382935SToomas Soome    When there is a window, goto inf_leave will update the window with the last
590b8382935SToomas Soome    output written.  If a goto inf_leave occurs in the middle of decompression
591b8382935SToomas Soome    and there is no window currently, goto inf_leave will create one and copy
592b8382935SToomas Soome    output to the window for the next call of inflate().
593b8382935SToomas Soome 
594b8382935SToomas Soome    In this implementation, the flush parameter of inflate() only affects the
595b8382935SToomas Soome    return code (per zlib.h).  inflate() always writes as much as possible to
596b8382935SToomas Soome    strm->next_out, given the space available and the provided input--the effect
597b8382935SToomas Soome    documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
598b8382935SToomas Soome    the allocation of and copying into a sliding window until necessary, which
599b8382935SToomas Soome    provides the effect documented in zlib.h for Z_FINISH when the entire input
600b8382935SToomas Soome    stream available.  So the only thing the flush parameter actually does is:
601b8382935SToomas Soome    when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
602b8382935SToomas Soome    will return Z_BUF_ERROR if it has not reached the end of the stream.
603b8382935SToomas Soome  */
604b8382935SToomas Soome 
inflate(z_streamp strm,int flush)605b8382935SToomas Soome int ZEXPORT inflate(z_streamp strm, int flush)
606b8382935SToomas Soome {
607b8382935SToomas Soome     struct inflate_state FAR *state;
608b8382935SToomas Soome     z_const unsigned char FAR *next;    /* next input */
609b8382935SToomas Soome     unsigned char FAR *put;     /* next output */
610b8382935SToomas Soome     unsigned have, left;        /* available input and output */
611b8382935SToomas Soome     unsigned long hold;         /* bit buffer */
612b8382935SToomas Soome     unsigned bits;              /* bits in bit buffer */
613b8382935SToomas Soome     unsigned in, out;           /* save starting available input and output */
614b8382935SToomas Soome     unsigned copy;              /* number of stored or match bytes to copy */
615b8382935SToomas Soome     unsigned char FAR *from;    /* where to copy match bytes from */
616b8382935SToomas Soome     code here;                  /* current decoding table entry */
617b8382935SToomas Soome     code last;                  /* parent table entry */
618b8382935SToomas Soome     unsigned len;               /* length to copy for repeats, bits to drop */
619b8382935SToomas Soome     int ret;                    /* return code */
620b8382935SToomas Soome #ifdef GUNZIP
621b8382935SToomas Soome     unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
622b8382935SToomas Soome #endif
623b8382935SToomas Soome     static const unsigned short order[19] = /* permutation of code lengths */
624b8382935SToomas Soome         {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
625b8382935SToomas Soome 
626b8382935SToomas Soome     if (inflateStateCheck(strm) || strm->next_out == Z_NULL ||
627b8382935SToomas Soome         (strm->next_in == Z_NULL && strm->avail_in != 0))
628b8382935SToomas Soome         return Z_STREAM_ERROR;
629b8382935SToomas Soome 
630b8382935SToomas Soome     state = (struct inflate_state FAR *)strm->state;
631b8382935SToomas Soome     if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
632b8382935SToomas Soome     LOAD();
633b8382935SToomas Soome     in = have;
634b8382935SToomas Soome     out = left;
635b8382935SToomas Soome     ret = Z_OK;
636b8382935SToomas Soome     for (;;)
637b8382935SToomas Soome         switch (state->mode) {
638b8382935SToomas Soome         case HEAD:
639b8382935SToomas Soome             if (state->wrap == 0) {
640b8382935SToomas Soome                 state->mode = TYPEDO;
641b8382935SToomas Soome                 break;
642b8382935SToomas Soome             }
643b8382935SToomas Soome             NEEDBITS(16);
644b8382935SToomas Soome #ifdef GUNZIP
645b8382935SToomas Soome             if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
646b8382935SToomas Soome                 if (state->wbits == 0)
647b8382935SToomas Soome                     state->wbits = 15;
648b8382935SToomas Soome                 state->check = crc32(0L, Z_NULL, 0);
649b8382935SToomas Soome                 CRC2(state->check, hold);
650b8382935SToomas Soome                 INITBITS();
651b8382935SToomas Soome                 state->mode = FLAGS;
652b8382935SToomas Soome                 break;
653b8382935SToomas Soome             }
654b8382935SToomas Soome             if (state->head != Z_NULL)
655b8382935SToomas Soome                 state->head->done = -1;
656b8382935SToomas Soome             if (!(state->wrap & 1) ||   /* check if zlib header allowed */
657b8382935SToomas Soome #else
658b8382935SToomas Soome             if (
659b8382935SToomas Soome #endif
660b8382935SToomas Soome                 ((BITS(8) << 8) + (hold >> 8)) % 31) {
661b8382935SToomas Soome                 strm->msg = (char *)"incorrect header check";
662b8382935SToomas Soome                 state->mode = BAD;
663b8382935SToomas Soome                 break;
664b8382935SToomas Soome             }
665b8382935SToomas Soome             if (BITS(4) != Z_DEFLATED) {
666b8382935SToomas Soome                 strm->msg = (char *)"unknown compression method";
667b8382935SToomas Soome                 state->mode = BAD;
668b8382935SToomas Soome                 break;
669b8382935SToomas Soome             }
670b8382935SToomas Soome             DROPBITS(4);
671b8382935SToomas Soome             len = BITS(4) + 8;
672b8382935SToomas Soome             if (state->wbits == 0)
673b8382935SToomas Soome                 state->wbits = len;
674b8382935SToomas Soome             if (len > 15 || len > state->wbits) {
675b8382935SToomas Soome                 strm->msg = (char *)"invalid window size";
676b8382935SToomas Soome                 state->mode = BAD;
677b8382935SToomas Soome                 break;
678b8382935SToomas Soome             }
679b8382935SToomas Soome             state->dmax = 1U << len;
680*148fd93eSToomas Soome             state->flags = 0;               /* indicate zlib header */
681b8382935SToomas Soome             Tracev((stderr, "inflate:   zlib header ok\n"));
682b8382935SToomas Soome             strm->adler = state->check = adler32(0L, Z_NULL, 0);
683b8382935SToomas Soome             state->mode = hold & 0x200 ? DICTID : TYPE;
684b8382935SToomas Soome             INITBITS();
685b8382935SToomas Soome             break;
686b8382935SToomas Soome #ifdef GUNZIP
687b8382935SToomas Soome         case FLAGS:
688b8382935SToomas Soome             NEEDBITS(16);
689b8382935SToomas Soome             state->flags = (int)(hold);
690b8382935SToomas Soome             if ((state->flags & 0xff) != Z_DEFLATED) {
691b8382935SToomas Soome                 strm->msg = (char *)"unknown compression method";
692b8382935SToomas Soome                 state->mode = BAD;
693b8382935SToomas Soome                 break;
694b8382935SToomas Soome             }
695b8382935SToomas Soome             if (state->flags & 0xe000) {
696b8382935SToomas Soome                 strm->msg = (char *)"unknown header flags set";
697b8382935SToomas Soome                 state->mode = BAD;
698b8382935SToomas Soome                 break;
699b8382935SToomas Soome             }
700b8382935SToomas Soome             if (state->head != Z_NULL)
701b8382935SToomas Soome                 state->head->text = (int)((hold >> 8) & 1);
702b8382935SToomas Soome             if ((state->flags & 0x0200) && (state->wrap & 4))
703b8382935SToomas Soome                 CRC2(state->check, hold);
704b8382935SToomas Soome             INITBITS();
705b8382935SToomas Soome             state->mode = TIME;
706*148fd93eSToomas Soome                 /* fallthrough */
707b8382935SToomas Soome         case TIME:
708b8382935SToomas Soome             NEEDBITS(32);
709b8382935SToomas Soome             if (state->head != Z_NULL)
710b8382935SToomas Soome                 state->head->time = hold;
711b8382935SToomas Soome             if ((state->flags & 0x0200) && (state->wrap & 4))
712b8382935SToomas Soome                 CRC4(state->check, hold);
713b8382935SToomas Soome             INITBITS();
714b8382935SToomas Soome             state->mode = OS;
715*148fd93eSToomas Soome                 /* fallthrough */
716b8382935SToomas Soome         case OS:
717b8382935SToomas Soome             NEEDBITS(16);
718b8382935SToomas Soome             if (state->head != Z_NULL) {
719b8382935SToomas Soome                 state->head->xflags = (int)(hold & 0xff);
720b8382935SToomas Soome                 state->head->os = (int)(hold >> 8);
721b8382935SToomas Soome             }
722b8382935SToomas Soome             if ((state->flags & 0x0200) && (state->wrap & 4))
723b8382935SToomas Soome                 CRC2(state->check, hold);
724b8382935SToomas Soome             INITBITS();
725b8382935SToomas Soome             state->mode = EXLEN;
726b8382935SToomas Soome 	    /* FALLTHROUGH */
727b8382935SToomas Soome         case EXLEN:
728b8382935SToomas Soome             if (state->flags & 0x0400) {
729b8382935SToomas Soome                 NEEDBITS(16);
730b8382935SToomas Soome                 state->length = (unsigned)(hold);
731b8382935SToomas Soome                 if (state->head != Z_NULL)
732b8382935SToomas Soome                     state->head->extra_len = (unsigned)hold;
733b8382935SToomas Soome                 if ((state->flags & 0x0200) && (state->wrap & 4))
734b8382935SToomas Soome                     CRC2(state->check, hold);
735b8382935SToomas Soome                 INITBITS();
736b8382935SToomas Soome             }
737b8382935SToomas Soome             else if (state->head != Z_NULL)
738b8382935SToomas Soome                 state->head->extra = Z_NULL;
739b8382935SToomas Soome             state->mode = EXTRA;
740b8382935SToomas Soome 	    /* FALLTHROUGH */
741b8382935SToomas Soome         case EXTRA:
742b8382935SToomas Soome             if (state->flags & 0x0400) {
743b8382935SToomas Soome                 copy = state->length;
744b8382935SToomas Soome                 if (copy > have) copy = have;
745b8382935SToomas Soome                 if (copy) {
746b8382935SToomas Soome                     if (state->head != Z_NULL &&
747b8382935SToomas Soome                         state->head->extra != Z_NULL) {
748b8382935SToomas Soome                         len = state->head->extra_len - state->length;
749b8382935SToomas Soome                         zmemcpy(state->head->extra + len, next,
750b8382935SToomas Soome                                 len + copy > state->head->extra_max ?
751b8382935SToomas Soome                                 state->head->extra_max - len : copy);
752b8382935SToomas Soome                     }
753b8382935SToomas Soome                     if ((state->flags & 0x0200) && (state->wrap & 4))
754b8382935SToomas Soome                         state->check = crc32(state->check, next, copy);
755b8382935SToomas Soome                     have -= copy;
756b8382935SToomas Soome                     next += copy;
757b8382935SToomas Soome                     state->length -= copy;
758b8382935SToomas Soome                 }
759b8382935SToomas Soome                 if (state->length) goto inf_leave;
760b8382935SToomas Soome             }
761b8382935SToomas Soome             state->length = 0;
762b8382935SToomas Soome             state->mode = NAME;
763b8382935SToomas Soome 	    /* FALLTHROUGH */
764b8382935SToomas Soome         case NAME:
765b8382935SToomas Soome             if (state->flags & 0x0800) {
766b8382935SToomas Soome                 if (have == 0) goto inf_leave;
767b8382935SToomas Soome                 copy = 0;
768b8382935SToomas Soome                 do {
769b8382935SToomas Soome                     len = (unsigned)(next[copy++]);
770b8382935SToomas Soome                     if (state->head != Z_NULL &&
771b8382935SToomas Soome                             state->head->name != Z_NULL &&
772b8382935SToomas Soome                             state->length < state->head->name_max)
773b8382935SToomas Soome                         state->head->name[state->length++] = (Bytef)len;
774b8382935SToomas Soome                 } while (len && copy < have);
775b8382935SToomas Soome                 if ((state->flags & 0x0200) && (state->wrap & 4))
776b8382935SToomas Soome                     state->check = crc32(state->check, next, copy);
777b8382935SToomas Soome                 have -= copy;
778b8382935SToomas Soome                 next += copy;
779b8382935SToomas Soome                 if (len) goto inf_leave;
780b8382935SToomas Soome             }
781b8382935SToomas Soome             else if (state->head != Z_NULL)
782b8382935SToomas Soome                 state->head->name = Z_NULL;
783b8382935SToomas Soome             state->length = 0;
784b8382935SToomas Soome             state->mode = COMMENT;
785b8382935SToomas Soome 	    /* FALLTHROUGH */
786b8382935SToomas Soome         case COMMENT:
787b8382935SToomas Soome             if (state->flags & 0x1000) {
788b8382935SToomas Soome                 if (have == 0) goto inf_leave;
789b8382935SToomas Soome                 copy = 0;
790b8382935SToomas Soome                 do {
791b8382935SToomas Soome                     len = (unsigned)(next[copy++]);
792b8382935SToomas Soome                     if (state->head != Z_NULL &&
793b8382935SToomas Soome                             state->head->comment != Z_NULL &&
794b8382935SToomas Soome                             state->length < state->head->comm_max)
795b8382935SToomas Soome                         state->head->comment[state->length++] = (Bytef)len;
796b8382935SToomas Soome                 } while (len && copy < have);
797b8382935SToomas Soome                 if ((state->flags & 0x0200) && (state->wrap & 4))
798b8382935SToomas Soome                     state->check = crc32(state->check, next, copy);
799b8382935SToomas Soome                 have -= copy;
800b8382935SToomas Soome                 next += copy;
801b8382935SToomas Soome                 if (len) goto inf_leave;
802b8382935SToomas Soome             }
803b8382935SToomas Soome             else if (state->head != Z_NULL)
804b8382935SToomas Soome                 state->head->comment = Z_NULL;
805b8382935SToomas Soome             state->mode = HCRC;
806b8382935SToomas Soome 	    /* FALLTHROUGH */
807b8382935SToomas Soome         case HCRC:
808b8382935SToomas Soome             if (state->flags & 0x0200) {
809b8382935SToomas Soome                 NEEDBITS(16);
810b8382935SToomas Soome                 if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
811b8382935SToomas Soome                     strm->msg = (char *)"header crc mismatch";
812b8382935SToomas Soome                     state->mode = BAD;
813b8382935SToomas Soome                     break;
814b8382935SToomas Soome                 }
815b8382935SToomas Soome                 INITBITS();
816b8382935SToomas Soome             }
817b8382935SToomas Soome             if (state->head != Z_NULL) {
818b8382935SToomas Soome                 state->head->hcrc = (int)((state->flags >> 9) & 1);
819b8382935SToomas Soome                 state->head->done = 1;
820b8382935SToomas Soome             }
821b8382935SToomas Soome             strm->adler = state->check = crc32(0L, Z_NULL, 0);
822b8382935SToomas Soome             state->mode = TYPE;
823b8382935SToomas Soome             break;
824b8382935SToomas Soome #endif
825b8382935SToomas Soome         case DICTID:
826b8382935SToomas Soome             NEEDBITS(32);
827b8382935SToomas Soome             strm->adler = state->check = ZSWAP32(hold);
828b8382935SToomas Soome             INITBITS();
829b8382935SToomas Soome             state->mode = DICT;
830b8382935SToomas Soome 	    /* FALLTHROUGH */
831b8382935SToomas Soome         case DICT:
832b8382935SToomas Soome             if (state->havedict == 0) {
833b8382935SToomas Soome                 RESTORE();
834b8382935