xref: /titanic_51/usr/src/contrib/zlib/inflate.c (revision 255bd2d68e7ee834beb530ec5e5f02d861e445ad)
1ab9e68a2SToomas Soome /* inflate.c -- zlib decompression
264c3d159SToomas Soome  * Copyright (C) 1995-2022 Mark Adler
3ab9e68a2SToomas Soome  * For conditions of distribution and use, see copyright notice in zlib.h
4ab9e68a2SToomas Soome  */
5ab9e68a2SToomas Soome 
6ab9e68a2SToomas Soome /*
7ab9e68a2SToomas Soome  * Change history:
8ab9e68a2SToomas Soome  *
9ab9e68a2SToomas Soome  * 1.2.beta0    24 Nov 2002
10ab9e68a2SToomas Soome  * - First version -- complete rewrite of inflate to simplify code, avoid
11ab9e68a2SToomas Soome  *   creation of window when not needed, minimize use of window when it is
12ab9e68a2SToomas Soome  *   needed, make inffast.c even faster, implement gzip decoding, and to
13ab9e68a2SToomas Soome  *   improve code readability and style over the previous zlib inflate code
14ab9e68a2SToomas Soome  *
15ab9e68a2SToomas Soome  * 1.2.beta1    25 Nov 2002
16ab9e68a2SToomas Soome  * - Use pointers for available input and output checking in inffast.c
17ab9e68a2SToomas Soome  * - Remove input and output counters in inffast.c
18ab9e68a2SToomas Soome  * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
19ab9e68a2SToomas Soome  * - Remove unnecessary second byte pull from length extra in inffast.c
20ab9e68a2SToomas Soome  * - Unroll direct copy to three copies per loop in inffast.c
21ab9e68a2SToomas Soome  *
22ab9e68a2SToomas Soome  * 1.2.beta2    4 Dec 2002
23ab9e68a2SToomas Soome  * - Change external routine names to reduce potential conflicts
24ab9e68a2SToomas Soome  * - Correct filename to inffixed.h for fixed tables in inflate.c
25ab9e68a2SToomas Soome  * - Make hbuf[] unsigned char to match parameter type in inflate.c
26ab9e68a2SToomas Soome  * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
27ab9e68a2SToomas Soome  *   to avoid negation problem on Alphas (64 bit) in inflate.c
28ab9e68a2SToomas Soome  *
29ab9e68a2SToomas Soome  * 1.2.beta3    22 Dec 2002
30ab9e68a2SToomas Soome  * - Add comments on state->bits assertion in inffast.c
31ab9e68a2SToomas Soome  * - Add comments on op field in inftrees.h
32ab9e68a2SToomas Soome  * - Fix bug in reuse of allocated window after inflateReset()
33ab9e68a2SToomas Soome  * - Remove bit fields--back to byte structure for speed
34ab9e68a2SToomas Soome  * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
35ab9e68a2SToomas Soome  * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
36ab9e68a2SToomas Soome  * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
37ab9e68a2SToomas Soome  * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
38ab9e68a2SToomas Soome  * - Use local copies of stream next and avail values, as well as local bit
39ab9e68a2SToomas Soome  *   buffer and bit count in inflate()--for speed when inflate_fast() not used
40ab9e68a2SToomas Soome  *
41ab9e68a2SToomas Soome  * 1.2.beta4    1 Jan 2003
42ab9e68a2SToomas Soome  * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
43ab9e68a2SToomas Soome  * - Move a comment on output buffer sizes from inffast.c to inflate.c
44ab9e68a2SToomas Soome  * - Add comments in inffast.c to introduce the inflate_fast() routine
45ab9e68a2SToomas Soome  * - Rearrange window copies in inflate_fast() for speed and simplification
46ab9e68a2SToomas Soome  * - Unroll last copy for window match in inflate_fast()
47ab9e68a2SToomas Soome  * - Use local copies of window variables in inflate_fast() for speed
48ab9e68a2SToomas Soome  * - Pull out common wnext == 0 case for speed in inflate_fast()
49ab9e68a2SToomas Soome  * - Make op and len in inflate_fast() unsigned for consistency
50ab9e68a2SToomas Soome  * - Add FAR to lcode and dcode declarations in inflate_fast()
51ab9e68a2SToomas Soome  * - Simplified bad distance check in inflate_fast()
52ab9e68a2SToomas Soome  * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
53ab9e68a2SToomas Soome  *   source file infback.c to provide a call-back interface to inflate for
54ab9e68a2SToomas Soome  *   programs like gzip and unzip -- uses window as output buffer to avoid
55ab9e68a2SToomas Soome  *   window copying
56ab9e68a2SToomas Soome  *
57ab9e68a2SToomas Soome  * 1.2.beta5    1 Jan 2003
58ab9e68a2SToomas Soome  * - Improved inflateBack() interface to allow the caller to provide initial
59ab9e68a2SToomas Soome  *   input in strm.
60ab9e68a2SToomas Soome  * - Fixed stored blocks bug in inflateBack()
61ab9e68a2SToomas Soome  *
62ab9e68a2SToomas Soome  * 1.2.beta6    4 Jan 2003
63ab9e68a2SToomas Soome  * - Added comments in inffast.c on effectiveness of POSTINC
64ab9e68a2SToomas Soome  * - Typecasting all around to reduce compiler warnings
65ab9e68a2SToomas Soome  * - Changed loops from while (1) or do {} while (1) to for (;;), again to
66ab9e68a2SToomas Soome  *   make compilers happy
67ab9e68a2SToomas Soome  * - Changed type of window in inflateBackInit() to unsigned char *
68ab9e68a2SToomas Soome  *
69ab9e68a2SToomas Soome  * 1.2.beta7    27 Jan 2003
70ab9e68a2SToomas Soome  * - Changed many types to unsigned or unsigned short to avoid warnings
71ab9e68a2SToomas Soome  * - Added inflateCopy() function
72ab9e68a2SToomas Soome  *
73ab9e68a2SToomas Soome  * 1.2.0        9 Mar 2003
74ab9e68a2SToomas Soome  * - Changed inflateBack() interface to provide separate opaque descriptors
75ab9e68a2SToomas Soome  *   for the in() and out() functions
76ab9e68a2SToomas Soome  * - Changed inflateBack() argument and in_func typedef to swap the length
77ab9e68a2SToomas Soome  *   and buffer address return values for the input function
78ab9e68a2SToomas Soome  * - Check next_in and next_out for Z_NULL on entry to inflate()
79ab9e68a2SToomas Soome  *
80ab9e68a2SToomas Soome  * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
81ab9e68a2SToomas Soome  */
82ab9e68a2SToomas Soome 
83ab9e68a2SToomas Soome #include "zutil.h"
84ab9e68a2SToomas Soome #include "inftrees.h"
85ab9e68a2SToomas Soome #include "inflate.h"
86ab9e68a2SToomas Soome #include "inffast.h"
87ab9e68a2SToomas Soome 
88ab9e68a2SToomas Soome #ifdef MAKEFIXED
89ab9e68a2SToomas Soome #  ifndef BUILDFIXED
90ab9e68a2SToomas Soome #    define BUILDFIXED
91ab9e68a2SToomas Soome #  endif
92ab9e68a2SToomas Soome #endif
93ab9e68a2SToomas Soome 
94ab9e68a2SToomas Soome /* function prototypes */
95ab9e68a2SToomas Soome local int inflateStateCheck OF((z_streamp strm));
96ab9e68a2SToomas Soome local void fixedtables OF((struct inflate_state FAR *state));
97ab9e68a2SToomas Soome local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
98ab9e68a2SToomas Soome                            unsigned copy));
99ab9e68a2SToomas Soome #ifdef BUILDFIXED
100ab9e68a2SToomas Soome    void makefixed OF((void));
101ab9e68a2SToomas Soome #endif
102ab9e68a2SToomas Soome local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
103ab9e68a2SToomas Soome                               unsigned len));
104ab9e68a2SToomas Soome 
105ab9e68a2SToomas Soome local int inflateStateCheck(z_streamp strm)
106ab9e68a2SToomas Soome {
107ab9e68a2SToomas Soome     struct inflate_state FAR *state;
108ab9e68a2SToomas Soome     if (strm == Z_NULL ||
109ab9e68a2SToomas Soome         strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
110ab9e68a2SToomas Soome         return 1;
111ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
112ab9e68a2SToomas Soome     if (state == Z_NULL || state->strm != strm ||
113ab9e68a2SToomas Soome         state->mode < HEAD || state->mode > SYNC)
114ab9e68a2SToomas Soome         return 1;
115ab9e68a2SToomas Soome     return 0;
116ab9e68a2SToomas Soome }
117ab9e68a2SToomas Soome 
118ab9e68a2SToomas Soome int ZEXPORT inflateResetKeep(z_streamp strm)
119ab9e68a2SToomas Soome {
120ab9e68a2SToomas Soome     struct inflate_state FAR *state;
121ab9e68a2SToomas Soome 
122ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
123ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
124ab9e68a2SToomas Soome     strm->total_in = strm->total_out = state->total = 0;
125ab9e68a2SToomas Soome     strm->msg = Z_NULL;
126ab9e68a2SToomas Soome     if (state->wrap)        /* to support ill-conceived Java test suite */
127ab9e68a2SToomas Soome         strm->adler = state->wrap & 1;
128ab9e68a2SToomas Soome     state->mode = HEAD;
129ab9e68a2SToomas Soome     state->last = 0;
130ab9e68a2SToomas Soome     state->havedict = 0;
13164c3d159SToomas Soome     state->flags = -1;
132ab9e68a2SToomas Soome     state->dmax = 32768U;
133ab9e68a2SToomas Soome     state->head = Z_NULL;
134ab9e68a2SToomas Soome     state->hold = 0;
135ab9e68a2SToomas Soome     state->bits = 0;
136ab9e68a2SToomas Soome     state->lencode = state->distcode = state->next = state->codes;
137ab9e68a2SToomas Soome     state->sane = 1;
138ab9e68a2SToomas Soome     state->back = -1;
139ab9e68a2SToomas Soome     Tracev((stderr, "inflate: reset\n"));
140ab9e68a2SToomas Soome     return Z_OK;
141ab9e68a2SToomas Soome }
142ab9e68a2SToomas Soome 
143ab9e68a2SToomas Soome int ZEXPORT inflateReset(z_streamp strm)
144ab9e68a2SToomas Soome {
145ab9e68a2SToomas Soome     struct inflate_state FAR *state;
146ab9e68a2SToomas Soome 
147ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
148ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
149ab9e68a2SToomas Soome     state->wsize = 0;
150ab9e68a2SToomas Soome     state->whave = 0;
151ab9e68a2SToomas Soome     state->wnext = 0;
152ab9e68a2SToomas Soome     return inflateResetKeep(strm);
153ab9e68a2SToomas Soome }
154ab9e68a2SToomas Soome 
155ab9e68a2SToomas Soome int ZEXPORT inflateReset2(z_streamp strm, int windowBits)
156ab9e68a2SToomas Soome {
157ab9e68a2SToomas Soome     int wrap;
158ab9e68a2SToomas Soome     struct inflate_state FAR *state;
159ab9e68a2SToomas Soome 
160ab9e68a2SToomas Soome     /* get the state */
161ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
162ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
163ab9e68a2SToomas Soome 
164ab9e68a2SToomas Soome     /* extract wrap request from windowBits parameter */
165ab9e68a2SToomas Soome     if (windowBits < 0) {
166ab9e68a2SToomas Soome         wrap = 0;
167ab9e68a2SToomas Soome         windowBits = -windowBits;
168ab9e68a2SToomas Soome     }
169ab9e68a2SToomas Soome     else {
170ab9e68a2SToomas Soome         wrap = (windowBits >> 4) + 5;
171ab9e68a2SToomas Soome #ifdef GUNZIP
172ab9e68a2SToomas Soome         if (windowBits < 48)
173ab9e68a2SToomas Soome             windowBits &= 15;
174ab9e68a2SToomas Soome #endif
175ab9e68a2SToomas Soome     }
176ab9e68a2SToomas Soome 
177ab9e68a2SToomas Soome     /* set number of window bits, free window if different */
178ab9e68a2SToomas Soome     if (windowBits && (windowBits < 8 || windowBits > 15))
179ab9e68a2SToomas Soome         return Z_STREAM_ERROR;
180ab9e68a2SToomas Soome     if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
181ab9e68a2SToomas Soome         ZFREE(strm, state->window);
182ab9e68a2SToomas Soome         state->window = Z_NULL;
183ab9e68a2SToomas Soome     }
184ab9e68a2SToomas Soome 
185ab9e68a2SToomas Soome     /* update state and reset the rest of it */
186ab9e68a2SToomas Soome     state->wrap = wrap;
187ab9e68a2SToomas Soome     state->wbits = (unsigned)windowBits;
188ab9e68a2SToomas Soome     return inflateReset(strm);
189ab9e68a2SToomas Soome }
190ab9e68a2SToomas Soome 
191ab9e68a2SToomas Soome int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version,
192ab9e68a2SToomas Soome     int stream_size)
193ab9e68a2SToomas Soome {
194ab9e68a2SToomas Soome     int ret;
195ab9e68a2SToomas Soome     struct inflate_state FAR *state;
196ab9e68a2SToomas Soome 
197ab9e68a2SToomas Soome     if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
198ab9e68a2SToomas Soome         stream_size != (int)(sizeof(z_stream)))
199ab9e68a2SToomas Soome         return Z_VERSION_ERROR;
200ab9e68a2SToomas Soome     if (strm == Z_NULL) return Z_STREAM_ERROR;
201ab9e68a2SToomas Soome     strm->msg = Z_NULL;                 /* in case we return an error */
202ab9e68a2SToomas Soome     if (strm->zalloc == (alloc_func)0) {
203ab9e68a2SToomas Soome #ifdef Z_SOLO
204ab9e68a2SToomas Soome         return Z_STREAM_ERROR;
205ab9e68a2SToomas Soome #else
206ab9e68a2SToomas Soome         strm->zalloc = zcalloc;
207ab9e68a2SToomas Soome         strm->opaque = (voidpf)0;
208ab9e68a2SToomas Soome #endif
209ab9e68a2SToomas Soome     }
210ab9e68a2SToomas Soome     if (strm->zfree == (free_func)0)
211ab9e68a2SToomas Soome #ifdef Z_SOLO
212ab9e68a2SToomas Soome         return Z_STREAM_ERROR;
213ab9e68a2SToomas Soome #else
214ab9e68a2SToomas Soome         strm->zfree = zcfree;
215ab9e68a2SToomas Soome #endif
216ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)
217ab9e68a2SToomas Soome             ZALLOC(strm, 1, sizeof(struct inflate_state));
218ab9e68a2SToomas Soome     if (state == Z_NULL) return Z_MEM_ERROR;
219ab9e68a2SToomas Soome     Tracev((stderr, "inflate: allocated\n"));
220ab9e68a2SToomas Soome     strm->state = (struct internal_state FAR *)state;
221ab9e68a2SToomas Soome     state->strm = strm;
222ab9e68a2SToomas Soome     state->window = Z_NULL;
223ab9e68a2SToomas Soome     state->mode = HEAD;     /* to pass state test in inflateReset2() */
224ab9e68a2SToomas Soome     ret = inflateReset2(strm, windowBits);
225ab9e68a2SToomas Soome     if (ret != Z_OK) {
226ab9e68a2SToomas Soome         ZFREE(strm, state);
227ab9e68a2SToomas Soome         strm->state = Z_NULL;
228ab9e68a2SToomas Soome     }
229ab9e68a2SToomas Soome     return ret;
230ab9e68a2SToomas Soome }
231ab9e68a2SToomas Soome 
232ab9e68a2SToomas Soome int ZEXPORT inflateInit_(z_streamp strm, const char *version, int stream_size)
233ab9e68a2SToomas Soome {
234ab9e68a2SToomas Soome     return inflateInit2_(strm, DEF_WBITS, version, stream_size);
235ab9e68a2SToomas Soome }
236ab9e68a2SToomas Soome 
237ab9e68a2SToomas Soome int ZEXPORT inflatePrime(z_streamp strm, int bits, int value)
238ab9e68a2SToomas Soome {
239ab9e68a2SToomas Soome     struct inflate_state FAR *state;
240ab9e68a2SToomas Soome 
241ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
242ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
243ab9e68a2SToomas Soome     if (bits < 0) {
244ab9e68a2SToomas Soome         state->hold = 0;
245ab9e68a2SToomas Soome         state->bits = 0;
246ab9e68a2SToomas Soome         return Z_OK;
247ab9e68a2SToomas Soome     }
248ab9e68a2SToomas Soome     if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;
249ab9e68a2SToomas Soome     value &= (1L << bits) - 1;
250ab9e68a2SToomas Soome     state->hold += (unsigned)value << state->bits;
251ab9e68a2SToomas Soome     state->bits += (uInt)bits;
252ab9e68a2SToomas Soome     return Z_OK;
253ab9e68a2SToomas Soome }
254ab9e68a2SToomas Soome 
255ab9e68a2SToomas Soome /*
256ab9e68a2SToomas Soome    Return state with length and distance decoding tables and index sizes set to
257ab9e68a2SToomas Soome    fixed code decoding.  Normally this returns fixed tables from inffixed.h.
258ab9e68a2SToomas Soome    If BUILDFIXED is defined, then instead this routine builds the tables the
259ab9e68a2SToomas Soome    first time it's called, and returns those tables the first time and
260ab9e68a2SToomas Soome    thereafter.  This reduces the size of the code by about 2K bytes, in
261ab9e68a2SToomas Soome    exchange for a little execution time.  However, BUILDFIXED should not be
262ab9e68a2SToomas Soome    used for threaded applications, since the rewriting of the tables and virgin
263ab9e68a2SToomas Soome    may not be thread-safe.
264ab9e68a2SToomas Soome  */
265ab9e68a2SToomas Soome local void fixedtables(struct inflate_state FAR *state)
266ab9e68a2SToomas Soome {
267ab9e68a2SToomas Soome #ifdef BUILDFIXED
268ab9e68a2SToomas Soome     static int virgin = 1;
269ab9e68a2SToomas Soome     static code *lenfix, *distfix;
270ab9e68a2SToomas Soome     static code fixed[544];
271ab9e68a2SToomas Soome 
272ab9e68a2SToomas Soome     /* build fixed huffman tables if first call (may not be thread safe) */
273ab9e68a2SToomas Soome     if (virgin) {
274ab9e68a2SToomas Soome         unsigned sym, bits;
275ab9e68a2SToomas Soome         static code *next;
276ab9e68a2SToomas Soome 
277ab9e68a2SToomas Soome         /* literal/length table */
278ab9e68a2SToomas Soome         sym = 0;
279ab9e68a2SToomas Soome         while (sym < 144) state->lens[sym++] = 8;
280ab9e68a2SToomas Soome         while (sym < 256) state->lens[sym++] = 9;
281ab9e68a2SToomas Soome         while (sym < 280) state->lens[sym++] = 7;
282ab9e68a2SToomas Soome         while (sym < 288) state->lens[sym++] = 8;
283ab9e68a2SToomas Soome         next = fixed;
284ab9e68a2SToomas Soome         lenfix = next;
285ab9e68a2SToomas Soome         bits = 9;
286ab9e68a2SToomas Soome         inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
287ab9e68a2SToomas Soome 
288ab9e68a2SToomas Soome         /* distance table */
289ab9e68a2SToomas Soome         sym = 0;
290ab9e68a2SToomas Soome         while (sym < 32) state->lens[sym++] = 5;
291ab9e68a2SToomas Soome         distfix = next;
292ab9e68a2SToomas Soome         bits = 5;
293ab9e68a2SToomas Soome         inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
294ab9e68a2SToomas Soome 
295ab9e68a2SToomas Soome         /* do this just once */
296ab9e68a2SToomas Soome         virgin = 0;
297ab9e68a2SToomas Soome     }
298ab9e68a2SToomas Soome #else /* !BUILDFIXED */
299ab9e68a2SToomas Soome #   include "inffixed.h"
300ab9e68a2SToomas Soome #endif /* BUILDFIXED */
301ab9e68a2SToomas Soome     state->lencode = lenfix;
302ab9e68a2SToomas Soome     state->lenbits = 9;
303ab9e68a2SToomas Soome     state->distcode = distfix;
304ab9e68a2SToomas Soome     state->distbits = 5;
305ab9e68a2SToomas Soome }
306ab9e68a2SToomas Soome 
307ab9e68a2SToomas Soome #ifdef MAKEFIXED
308ab9e68a2SToomas Soome #include <stdio.h>
309ab9e68a2SToomas Soome 
310ab9e68a2SToomas Soome /*
311ab9e68a2SToomas Soome    Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
312ab9e68a2SToomas Soome    defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
313ab9e68a2SToomas Soome    those tables to stdout, which would be piped to inffixed.h.  A small program
314ab9e68a2SToomas Soome    can simply call makefixed to do this:
315ab9e68a2SToomas Soome 
316ab9e68a2SToomas Soome     void makefixed(void);
317ab9e68a2SToomas Soome 
318ab9e68a2SToomas Soome     int main(void)
319ab9e68a2SToomas Soome     {
320ab9e68a2SToomas Soome         makefixed();
321ab9e68a2SToomas Soome         return 0;
322ab9e68a2SToomas Soome     }
323ab9e68a2SToomas Soome 
324ab9e68a2SToomas Soome    Then that can be linked with zlib built with MAKEFIXED defined and run:
325ab9e68a2SToomas Soome 
326ab9e68a2SToomas Soome     a.out > inffixed.h
327ab9e68a2SToomas Soome  */
328ab9e68a2SToomas Soome void makefixed(void)
329ab9e68a2SToomas Soome {
330ab9e68a2SToomas Soome     unsigned low, size;
331ab9e68a2SToomas Soome     struct inflate_state state;
332ab9e68a2SToomas Soome 
333ab9e68a2SToomas Soome     fixedtables(&state);
334ab9e68a2SToomas Soome     puts("    /* inffixed.h -- table for decoding fixed codes");
335ab9e68a2SToomas Soome     puts("     * Generated automatically by makefixed().");
336ab9e68a2SToomas Soome     puts("     */");
337ab9e68a2SToomas Soome     puts("");
338ab9e68a2SToomas Soome     puts("    /* WARNING: this file should *not* be used by applications.");
339ab9e68a2SToomas Soome     puts("       It is part of the implementation of this library and is");
340ab9e68a2SToomas Soome     puts("       subject to change. Applications should only use zlib.h.");
341ab9e68a2SToomas Soome     puts("     */");
342ab9e68a2SToomas Soome     puts("");
343ab9e68a2SToomas Soome     size = 1U << 9;
344ab9e68a2SToomas Soome     printf("    static const code lenfix[%u] = {", size);
345ab9e68a2SToomas Soome     low = 0;
346ab9e68a2SToomas Soome     for (;;) {
347ab9e68a2SToomas Soome         if ((low % 7) == 0) printf("\n        ");
348ab9e68a2SToomas Soome         printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
349ab9e68a2SToomas Soome                state.lencode[low].bits, state.lencode[low].val);
350ab9e68a2SToomas Soome         if (++low == size) break;
351ab9e68a2SToomas Soome         putchar(',');
352ab9e68a2SToomas Soome     }
353ab9e68a2SToomas Soome     puts("\n    };");
354ab9e68a2SToomas Soome     size = 1U << 5;
355ab9e68a2SToomas Soome     printf("\n    static const code distfix[%u] = {", size);
356ab9e68a2SToomas Soome     low = 0;
357ab9e68a2SToomas Soome     for (;;) {
358ab9e68a2SToomas Soome         if ((low % 6) == 0) printf("\n        ");
359ab9e68a2SToomas Soome         printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
360ab9e68a2SToomas Soome                state.distcode[low].val);
361ab9e68a2SToomas Soome         if (++low == size) break;
362ab9e68a2SToomas Soome         putchar(',');
363ab9e68a2SToomas Soome     }
364ab9e68a2SToomas Soome     puts("\n    };");
365ab9e68a2SToomas Soome }
366ab9e68a2SToomas Soome #endif /* MAKEFIXED */
367ab9e68a2SToomas Soome 
368ab9e68a2SToomas Soome /*
369ab9e68a2SToomas Soome    Update the window with the last wsize (normally 32K) bytes written before
370ab9e68a2SToomas Soome    returning.  If window does not exist yet, create it.  This is only called
371ab9e68a2SToomas Soome    when a window is already in use, or when output has been written during this
372ab9e68a2SToomas Soome    inflate call, but the end of the deflate stream has not been reached yet.
373ab9e68a2SToomas Soome    It is also called to create a window for dictionary data when a dictionary
374ab9e68a2SToomas Soome    is loaded.
375ab9e68a2SToomas Soome 
376ab9e68a2SToomas Soome    Providing output buffers larger than 32K to inflate() should provide a speed
377ab9e68a2SToomas Soome    advantage, since only the last 32K of output is copied to the sliding window
378ab9e68a2SToomas Soome    upon return from inflate(), and since all distances after the first 32K of
379ab9e68a2SToomas Soome    output will fall in the output data, making match copies simpler and faster.
380ab9e68a2SToomas Soome    The advantage may be dependent on the size of the processor's data caches.
381ab9e68a2SToomas Soome  */
382ab9e68a2SToomas Soome local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy)
383ab9e68a2SToomas Soome {
384ab9e68a2SToomas Soome     struct inflate_state FAR *state;
385ab9e68a2SToomas Soome     unsigned dist;
386ab9e68a2SToomas Soome 
387ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
388ab9e68a2SToomas Soome 
389ab9e68a2SToomas Soome     /* if it hasn't been done already, allocate space for the window */
390ab9e68a2SToomas Soome     if (state->window == Z_NULL) {
391ab9e68a2SToomas Soome         state->window = (unsigned char FAR *)
392ab9e68a2SToomas Soome                         ZALLOC(strm, 1U << state->wbits,
393ab9e68a2SToomas Soome                                sizeof(unsigned char));
394ab9e68a2SToomas Soome         if (state->window == Z_NULL) return 1;
395ab9e68a2SToomas Soome     }
396ab9e68a2SToomas Soome 
397ab9e68a2SToomas Soome     /* if window not in use yet, initialize */
398ab9e68a2SToomas Soome     if (state->wsize == 0) {
399ab9e68a2SToomas Soome         state->wsize = 1U << state->wbits;
400ab9e68a2SToomas Soome         state->wnext = 0;
401ab9e68a2SToomas Soome         state->whave = 0;
402ab9e68a2SToomas Soome     }
403ab9e68a2SToomas Soome 
404ab9e68a2SToomas Soome     /* copy state->wsize or less output bytes into the circular window */
405ab9e68a2SToomas Soome     if (copy >= state->wsize) {
406ab9e68a2SToomas Soome         zmemcpy(state->window, end - state->wsize, state->wsize);
407ab9e68a2SToomas Soome         state->wnext = 0;
408ab9e68a2SToomas Soome         state->whave = state->wsize;
409ab9e68a2SToomas Soome     }
410ab9e68a2SToomas Soome     else {
411ab9e68a2SToomas Soome         dist = state->wsize - state->wnext;
412ab9e68a2SToomas Soome         if (dist > copy) dist = copy;
413ab9e68a2SToomas Soome         zmemcpy(state->window + state->wnext, end - copy, dist);
414ab9e68a2SToomas Soome         copy -= dist;
415ab9e68a2SToomas Soome         if (copy) {
416ab9e68a2SToomas Soome             zmemcpy(state->window, end - copy, copy);
417ab9e68a2SToomas Soome             state->wnext = copy;
418ab9e68a2SToomas Soome             state->whave = state->wsize;
419ab9e68a2SToomas Soome         }
420ab9e68a2SToomas Soome         else {
421ab9e68a2SToomas Soome             state->wnext += dist;
422ab9e68a2SToomas Soome             if (state->wnext == state->wsize) state->wnext = 0;
423ab9e68a2SToomas Soome             if (state->whave < state->wsize) state->whave += dist;
424ab9e68a2SToomas Soome         }
425ab9e68a2SToomas Soome     }
426ab9e68a2SToomas Soome     return 0;
427ab9e68a2SToomas Soome }
428ab9e68a2SToomas Soome 
429ab9e68a2SToomas Soome /* Macros for inflate(): */
430ab9e68a2SToomas Soome 
431ab9e68a2SToomas Soome /* check function to use adler32() for zlib or crc32() for gzip */
432ab9e68a2SToomas Soome #ifdef GUNZIP
43364c3d159SToomas Soome #  define UPDATE_CHECK(check, buf, len) \
434ab9e68a2SToomas Soome     (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
435ab9e68a2SToomas Soome #else
43664c3d159SToomas Soome #  define UPDATE_CHECK(check, buf, len) adler32(check, buf, len)
437ab9e68a2SToomas Soome #endif
438ab9e68a2SToomas Soome 
439ab9e68a2SToomas Soome /* check macros for header crc */
440ab9e68a2SToomas Soome #ifdef GUNZIP
441ab9e68a2SToomas Soome #  define CRC2(check, word) \
442ab9e68a2SToomas Soome     do { \
443ab9e68a2SToomas Soome         hbuf[0] = (unsigned char)(word); \
444ab9e68a2SToomas Soome         hbuf[1] = (unsigned char)((word) >> 8); \
445ab9e68a2SToomas Soome         check = crc32(check, hbuf, 2); \
446ab9e68a2SToomas Soome     } while (0)
447ab9e68a2SToomas Soome 
448ab9e68a2SToomas Soome #  define CRC4(check, word) \
449ab9e68a2SToomas Soome     do { \
450ab9e68a2SToomas Soome         hbuf[0] = (unsigned char)(word); \
451ab9e68a2SToomas Soome         hbuf[1] = (unsigned char)((word) >> 8); \
452ab9e68a2SToomas Soome         hbuf[2] = (unsigned char)((word) >> 16); \
453ab9e68a2SToomas Soome         hbuf[3] = (unsigned char)((word) >> 24); \
454ab9e68a2SToomas Soome         check = crc32(check, hbuf, 4); \
455ab9e68a2SToomas Soome     } while (0)
456ab9e68a2SToomas Soome #endif
457ab9e68a2SToomas Soome 
458ab9e68a2SToomas Soome /* Load registers with state in inflate() for speed */
459ab9e68a2SToomas Soome #define LOAD() \
460ab9e68a2SToomas Soome     do { \
461ab9e68a2SToomas Soome         put = strm->next_out; \
462ab9e68a2SToomas Soome         left = strm->avail_out; \
463ab9e68a2SToomas Soome         next = strm->next_in; \
464ab9e68a2SToomas Soome         have = strm->avail_in; \
465ab9e68a2SToomas Soome         hold = state->hold; \
466ab9e68a2SToomas Soome         bits = state->bits; \
467ab9e68a2SToomas Soome     } while (0)
468ab9e68a2SToomas Soome 
469ab9e68a2SToomas Soome /* Restore state from registers in inflate() */
470ab9e68a2SToomas Soome #define RESTORE() \
471ab9e68a2SToomas Soome     do { \
472ab9e68a2SToomas Soome         strm->next_out = put; \
473ab9e68a2SToomas Soome         strm->avail_out = left; \
474ab9e68a2SToomas Soome         strm->next_in = next; \
475ab9e68a2SToomas Soome         strm->avail_in = have; \
476ab9e68a2SToomas Soome         state->hold = hold; \
477ab9e68a2SToomas Soome         state->bits = bits; \
478ab9e68a2SToomas Soome     } while (0)
479ab9e68a2SToomas Soome 
480ab9e68a2SToomas Soome /* Clear the input bit accumulator */
481ab9e68a2SToomas Soome #define INITBITS() \
482ab9e68a2SToomas Soome     do { \
483ab9e68a2SToomas Soome         hold = 0; \
484ab9e68a2SToomas Soome         bits = 0; \
485ab9e68a2SToomas Soome     } while (0)
486ab9e68a2SToomas Soome 
487ab9e68a2SToomas Soome /* Get a byte of input into the bit accumulator, or return from inflate()
488ab9e68a2SToomas Soome    if there is no input available. */
489ab9e68a2SToomas Soome #define PULLBYTE() \
490ab9e68a2SToomas Soome     do { \
491ab9e68a2SToomas Soome         if (have == 0) goto inf_leave; \
492ab9e68a2SToomas Soome         have--; \
493ab9e68a2SToomas Soome         hold += (unsigned long)(*next++) << bits; \
494ab9e68a2SToomas Soome         bits += 8; \
495ab9e68a2SToomas Soome     } while (0)
496ab9e68a2SToomas Soome 
497ab9e68a2SToomas Soome /* Assure that there are at least n bits in the bit accumulator.  If there is
498ab9e68a2SToomas Soome    not enough available input to do that, then return from inflate(). */
499ab9e68a2SToomas Soome #define NEEDBITS(n) \
500ab9e68a2SToomas Soome     do { \
501ab9e68a2SToomas Soome         while (bits < (unsigned)(n)) \
502ab9e68a2SToomas Soome             PULLBYTE(); \
503ab9e68a2SToomas Soome     } while (0)
504ab9e68a2SToomas Soome 
505ab9e68a2SToomas Soome /* Return the low n bits of the bit accumulator (n < 16) */
506ab9e68a2SToomas Soome #define BITS(n) \
507ab9e68a2SToomas Soome     ((unsigned)hold & ((1U << (n)) - 1))
508ab9e68a2SToomas Soome 
509ab9e68a2SToomas Soome /* Remove n bits from the bit accumulator */
510ab9e68a2SToomas Soome #define DROPBITS(n) \
511ab9e68a2SToomas Soome     do { \
512ab9e68a2SToomas Soome         hold >>= (n); \
513ab9e68a2SToomas Soome         bits -= (unsigned)(n); \
514ab9e68a2SToomas Soome     } while (0)
515ab9e68a2SToomas Soome 
516ab9e68a2SToomas Soome /* Remove zero to seven bits as needed to go to a byte boundary */
517ab9e68a2SToomas Soome #define BYTEBITS() \
518ab9e68a2SToomas Soome     do { \
519ab9e68a2SToomas Soome         hold >>= bits & 7; \
520ab9e68a2SToomas Soome         bits -= bits & 7; \
521ab9e68a2SToomas Soome     } while (0)
522ab9e68a2SToomas Soome 
523ab9e68a2SToomas Soome /*
524ab9e68a2SToomas Soome    inflate() uses a state machine to process as much input data and generate as
525ab9e68a2SToomas Soome    much output data as possible before returning.  The state machine is
526ab9e68a2SToomas Soome    structured roughly as follows:
527ab9e68a2SToomas Soome 
528ab9e68a2SToomas Soome     for (;;) switch (state) {
529ab9e68a2SToomas Soome     ...
530ab9e68a2SToomas Soome     case STATEn:
531ab9e68a2SToomas Soome         if (not enough input data or output space to make progress)
532ab9e68a2SToomas Soome             return;
533ab9e68a2SToomas Soome         ... make progress ...
534ab9e68a2SToomas Soome         state = STATEm;
535ab9e68a2SToomas Soome         break;
536ab9e68a2SToomas Soome     ...
537ab9e68a2SToomas Soome     }
538ab9e68a2SToomas Soome 
539ab9e68a2SToomas Soome    so when inflate() is called again, the same case is attempted again, and
540ab9e68a2SToomas Soome    if the appropriate resources are provided, the machine proceeds to the
541ab9e68a2SToomas Soome    next state.  The NEEDBITS() macro is usually the way the state evaluates
542ab9e68a2SToomas Soome    whether it can proceed or should return.  NEEDBITS() does the return if
543ab9e68a2SToomas Soome    the requested bits are not available.  The typical use of the BITS macros
544ab9e68a2SToomas Soome    is:
545ab9e68a2SToomas Soome 
546ab9e68a2SToomas Soome         NEEDBITS(n);
547ab9e68a2SToomas Soome         ... do something with BITS(n) ...
548ab9e68a2SToomas Soome         DROPBITS(n);
549ab9e68a2SToomas Soome 
550ab9e68a2SToomas Soome    where NEEDBITS(n) either returns from inflate() if there isn't enough
551ab9e68a2SToomas Soome    input left to load n bits into the accumulator, or it continues.  BITS(n)
552ab9e68a2SToomas Soome    gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
553ab9e68a2SToomas Soome    the low n bits off the accumulator.  INITBITS() clears the accumulator
554ab9e68a2SToomas Soome    and sets the number of available bits to zero.  BYTEBITS() discards just
555ab9e68a2SToomas Soome    enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
556ab9e68a2SToomas Soome    and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
557ab9e68a2SToomas Soome 
558ab9e68a2SToomas Soome    NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
559ab9e68a2SToomas Soome    if there is no input available.  The decoding of variable length codes uses
560ab9e68a2SToomas Soome    PULLBYTE() directly in order to pull just enough bytes to decode the next
561ab9e68a2SToomas Soome    code, and no more.
562ab9e68a2SToomas Soome 
563ab9e68a2SToomas Soome    Some states loop until they get enough input, making sure that enough
564ab9e68a2SToomas Soome    state information is maintained to continue the loop where it left off
565ab9e68a2SToomas Soome    if NEEDBITS() returns in the loop.  For example, want, need, and keep
566ab9e68a2SToomas Soome    would all have to actually be part of the saved state in case NEEDBITS()
567ab9e68a2SToomas Soome    returns:
568ab9e68a2SToomas Soome 
569ab9e68a2SToomas Soome     case STATEw:
570ab9e68a2SToomas Soome         while (want < need) {
571ab9e68a2SToomas Soome             NEEDBITS(n);
572ab9e68a2SToomas Soome             keep[want++] = BITS(n);
573ab9e68a2SToomas Soome             DROPBITS(n);
574ab9e68a2SToomas Soome         }
575ab9e68a2SToomas Soome         state = STATEx;
576ab9e68a2SToomas Soome     case STATEx:
577ab9e68a2SToomas Soome 
578ab9e68a2SToomas Soome    As shown above, if the next state is also the next case, then the break
579ab9e68a2SToomas Soome    is omitted.
580ab9e68a2SToomas Soome 
581ab9e68a2SToomas Soome    A state may also return if there is not enough output space available to
582ab9e68a2SToomas Soome    complete that state.  Those states are copying stored data, writing a
583ab9e68a2SToomas Soome    literal byte, and copying a matching string.
584ab9e68a2SToomas Soome 
585ab9e68a2SToomas Soome    When returning, a "goto inf_leave" is used to update the total counters,
586ab9e68a2SToomas Soome    update the check value, and determine whether any progress has been made
587ab9e68a2SToomas Soome    during that inflate() call in order to return the proper return code.
588ab9e68a2SToomas Soome    Progress is defined as a change in either strm->avail_in or strm->avail_out.
589ab9e68a2SToomas Soome    When there is a window, goto inf_leave will update the window with the last
590ab9e68a2SToomas Soome    output written.  If a goto inf_leave occurs in the middle of decompression
591ab9e68a2SToomas Soome    and there is no window currently, goto inf_leave will create one and copy
592ab9e68a2SToomas Soome    output to the window for the next call of inflate().
593ab9e68a2SToomas Soome 
594ab9e68a2SToomas Soome    In this implementation, the flush parameter of inflate() only affects the
595ab9e68a2SToomas Soome    return code (per zlib.h).  inflate() always writes as much as possible to
596ab9e68a2SToomas Soome    strm->next_out, given the space available and the provided input--the effect
597ab9e68a2SToomas Soome    documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
598ab9e68a2SToomas Soome    the allocation of and copying into a sliding window until necessary, which
599ab9e68a2SToomas Soome    provides the effect documented in zlib.h for Z_FINISH when the entire input
600ab9e68a2SToomas Soome    stream available.  So the only thing the flush parameter actually does is:
601ab9e68a2SToomas Soome    when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
602ab9e68a2SToomas Soome    will return Z_BUF_ERROR if it has not reached the end of the stream.
603ab9e68a2SToomas Soome  */
604ab9e68a2SToomas Soome 
605ab9e68a2SToomas Soome int ZEXPORT inflate(z_streamp strm, int flush)
606ab9e68a2SToomas Soome {
607ab9e68a2SToomas Soome     struct inflate_state FAR *state;
608ab9e68a2SToomas Soome     z_const unsigned char FAR *next;    /* next input */
609ab9e68a2SToomas Soome     unsigned char FAR *put;     /* next output */
610ab9e68a2SToomas Soome     unsigned have, left;        /* available input and output */
611ab9e68a2SToomas Soome     unsigned long hold;         /* bit buffer */
612ab9e68a2SToomas Soome     unsigned bits;              /* bits in bit buffer */
613ab9e68a2SToomas Soome     unsigned in, out;           /* save starting available input and output */
614ab9e68a2SToomas Soome     unsigned copy;              /* number of stored or match bytes to copy */
615ab9e68a2SToomas Soome     unsigned char FAR *from;    /* where to copy match bytes from */
616ab9e68a2SToomas Soome     code here;                  /* current decoding table entry */
617ab9e68a2SToomas Soome     code last;                  /* parent table entry */
618ab9e68a2SToomas Soome     unsigned len;               /* length to copy for repeats, bits to drop */
619ab9e68a2SToomas Soome     int ret;                    /* return code */
620ab9e68a2SToomas Soome #ifdef GUNZIP
621ab9e68a2SToomas Soome     unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
622ab9e68a2SToomas Soome #endif
623ab9e68a2SToomas Soome     static const unsigned short order[19] = /* permutation of code lengths */
624ab9e68a2SToomas Soome         {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
625ab9e68a2SToomas Soome 
626ab9e68a2SToomas Soome     if (inflateStateCheck(strm) || strm->next_out == Z_NULL ||
627ab9e68a2SToomas Soome         (strm->next_in == Z_NULL && strm->avail_in != 0))
628ab9e68a2SToomas Soome         return Z_STREAM_ERROR;
629ab9e68a2SToomas Soome 
630ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
631ab9e68a2SToomas Soome     if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
632ab9e68a2SToomas Soome     LOAD();
633ab9e68a2SToomas Soome     in = have;
634ab9e68a2SToomas Soome     out = left;
635ab9e68a2SToomas Soome     ret = Z_OK;
636ab9e68a2SToomas Soome     for (;;)
637ab9e68a2SToomas Soome         switch (state->mode) {
638ab9e68a2SToomas Soome         case HEAD:
639ab9e68a2SToomas Soome             if (state->wrap == 0) {
640ab9e68a2SToomas Soome                 state->mode = TYPEDO;
641ab9e68a2SToomas Soome                 break;
642ab9e68a2SToomas Soome             }
643ab9e68a2SToomas Soome             NEEDBITS(16);
644ab9e68a2SToomas Soome #ifdef GUNZIP
645ab9e68a2SToomas Soome             if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
646ab9e68a2SToomas Soome                 if (state->wbits == 0)
647ab9e68a2SToomas Soome                     state->wbits = 15;
648ab9e68a2SToomas Soome                 state->check = crc32(0L, Z_NULL, 0);
649ab9e68a2SToomas Soome                 CRC2(state->check, hold);
650ab9e68a2SToomas Soome                 INITBITS();
651ab9e68a2SToomas Soome                 state->mode = FLAGS;
652ab9e68a2SToomas Soome                 break;
653ab9e68a2SToomas Soome             }
654ab9e68a2SToomas Soome             if (state->head != Z_NULL)
655ab9e68a2SToomas Soome                 state->head->done = -1;
656ab9e68a2SToomas Soome             if (!(state->wrap & 1) ||   /* check if zlib header allowed */
657ab9e68a2SToomas Soome #else
658ab9e68a2SToomas Soome             if (
659ab9e68a2SToomas Soome #endif
660ab9e68a2SToomas Soome                 ((BITS(8) << 8) + (hold >> 8)) % 31) {
661ab9e68a2SToomas Soome                 strm->msg = (char *)"incorrect header check";
662ab9e68a2SToomas Soome                 state->mode = BAD;
663ab9e68a2SToomas Soome                 break;
664ab9e68a2SToomas Soome             }
665ab9e68a2SToomas Soome             if (BITS(4) != Z_DEFLATED) {
666ab9e68a2SToomas Soome                 strm->msg = (char *)"unknown compression method";
667ab9e68a2SToomas Soome                 state->mode = BAD;
668ab9e68a2SToomas Soome                 break;
669ab9e68a2SToomas Soome             }
670ab9e68a2SToomas Soome             DROPBITS(4);
671ab9e68a2SToomas Soome             len = BITS(4) + 8;
672ab9e68a2SToomas Soome             if (state->wbits == 0)
673ab9e68a2SToomas Soome                 state->wbits = len;
674ab9e68a2SToomas Soome             if (len > 15 || len > state->wbits) {
675ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid window size";
676ab9e68a2SToomas Soome                 state->mode = BAD;
677ab9e68a2SToomas Soome                 break;
678ab9e68a2SToomas Soome             }
679ab9e68a2SToomas Soome             state->dmax = 1U << len;
68064c3d159SToomas Soome             state->flags = 0;               /* indicate zlib header */
681ab9e68a2SToomas Soome             Tracev((stderr, "inflate:   zlib header ok\n"));
682ab9e68a2SToomas Soome             strm->adler = state->check = adler32(0L, Z_NULL, 0);
683ab9e68a2SToomas Soome             state->mode = hold & 0x200 ? DICTID : TYPE;
684ab9e68a2SToomas Soome             INITBITS();
685ab9e68a2SToomas Soome             break;
686ab9e68a2SToomas Soome #ifdef GUNZIP
687ab9e68a2SToomas Soome         case FLAGS:
688ab9e68a2SToomas Soome             NEEDBITS(16);
689ab9e68a2SToomas Soome             state->flags = (int)(hold);
690ab9e68a2SToomas Soome             if ((state->flags & 0xff) != Z_DEFLATED) {
691ab9e68a2SToomas Soome                 strm->msg = (char *)"unknown compression method";
692ab9e68a2SToomas Soome                 state->mode = BAD;
693ab9e68a2SToomas Soome                 break;
694ab9e68a2SToomas Soome             }
695ab9e68a2SToomas Soome             if (state->flags & 0xe000) {
696ab9e68a2SToomas Soome                 strm->msg = (char *)"unknown header flags set";
697ab9e68a2SToomas Soome                 state->mode = BAD;
698ab9e68a2SToomas Soome                 break;
699ab9e68a2SToomas Soome             }
700ab9e68a2SToomas Soome             if (state->head != Z_NULL)
701ab9e68a2SToomas Soome                 state->head->text = (int)((hold >> 8) & 1);
702ab9e68a2SToomas Soome             if ((state->flags & 0x0200) && (state->wrap & 4))
703ab9e68a2SToomas Soome                 CRC2(state->check, hold);
704ab9e68a2SToomas Soome             INITBITS();
705ab9e68a2SToomas Soome             state->mode = TIME;
70664c3d159SToomas Soome                 /* fallthrough */
707ab9e68a2SToomas Soome         case TIME:
708ab9e68a2SToomas Soome             NEEDBITS(32);
709ab9e68a2SToomas Soome             if (state->head != Z_NULL)
710ab9e68a2SToomas Soome                 state->head->time = hold;
711ab9e68a2SToomas Soome             if ((state->flags & 0x0200) && (state->wrap & 4))
712ab9e68a2SToomas Soome                 CRC4(state->check, hold);
713ab9e68a2SToomas Soome             INITBITS();
714ab9e68a2SToomas Soome             state->mode = OS;
71564c3d159SToomas Soome                 /* fallthrough */
716ab9e68a2SToomas Soome         case OS:
717ab9e68a2SToomas Soome             NEEDBITS(16);
718ab9e68a2SToomas Soome             if (state->head != Z_NULL) {
719ab9e68a2SToomas Soome                 state->head->xflags = (int)(hold & 0xff);
720ab9e68a2SToomas Soome                 state->head->os = (int)(hold >> 8);
721ab9e68a2SToomas Soome             }
722ab9e68a2SToomas Soome             if ((state->flags & 0x0200) && (state->wrap & 4))
723ab9e68a2SToomas Soome                 CRC2(state->check, hold);
724ab9e68a2SToomas Soome             INITBITS();
725ab9e68a2SToomas Soome             state->mode = EXLEN;
726ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
727ab9e68a2SToomas Soome         case EXLEN:
728ab9e68a2SToomas Soome             if (state->flags & 0x0400) {
729ab9e68a2SToomas Soome                 NEEDBITS(16);
730ab9e68a2SToomas Soome                 state->length = (unsigned)(hold);
731ab9e68a2SToomas Soome                 if (state->head != Z_NULL)
732ab9e68a2SToomas Soome                     state->head->extra_len = (unsigned)hold;
733ab9e68a2SToomas Soome                 if ((state->flags & 0x0200) && (state->wrap & 4))
734ab9e68a2SToomas Soome                     CRC2(state->check, hold);
735ab9e68a2SToomas Soome                 INITBITS();
736ab9e68a2SToomas Soome             }
737ab9e68a2SToomas Soome             else if (state->head != Z_NULL)
738ab9e68a2SToomas Soome                 state->head->extra = Z_NULL;
739ab9e68a2SToomas Soome             state->mode = EXTRA;
740ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
741ab9e68a2SToomas Soome         case EXTRA:
742ab9e68a2SToomas Soome             if (state->flags & 0x0400) {
743ab9e68a2SToomas Soome                 copy = state->length;
744ab9e68a2SToomas Soome                 if (copy > have) copy = have;
745ab9e68a2SToomas Soome                 if (copy) {
746ab9e68a2SToomas Soome                     if (state->head != Z_NULL &&
747*255bd2d6SMark Adler                         state->head->extra != Z_NULL &&
748*255bd2d6SMark Adler                         (len = state->head->extra_len - state->length) <
749*255bd2d6SMark Adler                             state->head->extra_max) {
750ab9e68a2SToomas Soome                         zmemcpy(state->head->extra + len, next,
751ab9e68a2SToomas Soome                                 len + copy > state->head->extra_max ?
752ab9e68a2SToomas Soome                                 state->head->extra_max - len : copy);
753ab9e68a2SToomas Soome                     }
754ab9e68a2SToomas Soome                     if ((state->flags & 0x0200) && (state->wrap & 4))
755ab9e68a2SToomas Soome                         state->check = crc32(state->check, next, copy);
756ab9e68a2SToomas Soome                     have -= copy;
757ab9e68a2SToomas Soome                     next += copy;
758ab9e68a2SToomas Soome                     state->length -= copy;
759ab9e68a2SToomas Soome                 }
760ab9e68a2SToomas Soome                 if (state->length) goto inf_leave;
761ab9e68a2SToomas Soome             }
762ab9e68a2SToomas Soome             state->length = 0;
763ab9e68a2SToomas Soome             state->mode = NAME;
764ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
765ab9e68a2SToomas Soome         case NAME:
766ab9e68a2SToomas Soome             if (state->flags & 0x0800) {
767ab9e68a2SToomas Soome                 if (have == 0) goto inf_leave;
768ab9e68a2SToomas Soome                 copy = 0;
769ab9e68a2SToomas Soome                 do {
770ab9e68a2SToomas Soome                     len = (unsigned)(next[copy++]);
771ab9e68a2SToomas Soome                     if (state->head != Z_NULL &&
772ab9e68a2SToomas Soome                             state->head->name != Z_NULL &&
773ab9e68a2SToomas Soome                             state->length < state->head->name_max)
774ab9e68a2SToomas Soome                         state->head->name[state->length++] = (Bytef)len;
775ab9e68a2SToomas Soome                 } while (len && copy < have);
776ab9e68a2SToomas Soome                 if ((state->flags & 0x0200) && (state->wrap & 4))
777ab9e68a2SToomas Soome                     state->check = crc32(state->check, next, copy);
778ab9e68a2SToomas Soome                 have -= copy;
779ab9e68a2SToomas Soome                 next += copy;
780ab9e68a2SToomas Soome                 if (len) goto inf_leave;
781ab9e68a2SToomas Soome             }
782ab9e68a2SToomas Soome             else if (state->head != Z_NULL)
783ab9e68a2SToomas Soome                 state->head->name = Z_NULL;
784ab9e68a2SToomas Soome             state->length = 0;
785ab9e68a2SToomas Soome             state->mode = COMMENT;
786ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
787ab9e68a2SToomas Soome         case COMMENT:
788ab9e68a2SToomas Soome             if (state->flags & 0x1000) {
789ab9e68a2SToomas Soome                 if (have == 0) goto inf_leave;
790ab9e68a2SToomas Soome                 copy = 0;
791ab9e68a2SToomas Soome                 do {
792ab9e68a2SToomas Soome                     len = (unsigned)(next[copy++]);
793ab9e68a2SToomas Soome                     if (state->head != Z_NULL &&
794ab9e68a2SToomas Soome                             state->head->comment != Z_NULL &&
795ab9e68a2SToomas Soome                             state->length < state->head->comm_max)
796ab9e68a2SToomas Soome                         state->head->comment[state->length++] = (Bytef)len;
797ab9e68a2SToomas Soome                 } while (len && copy < have);
798ab9e68a2SToomas Soome                 if ((state->flags & 0x0200) && (state->wrap & 4))
799ab9e68a2SToomas Soome                     state->check = crc32(state->check, next, copy);
800ab9e68a2SToomas Soome                 have -= copy;
801ab9e68a2SToomas Soome                 next += copy;
802ab9e68a2SToomas Soome                 if (len) goto inf_leave;
803ab9e68a2SToomas Soome             }
804ab9e68a2SToomas Soome             else if (state->head != Z_NULL)
805ab9e68a2SToomas Soome                 state->head->comment = Z_NULL;
806ab9e68a2SToomas Soome             state->mode = HCRC;
807ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
808ab9e68a2SToomas Soome         case HCRC:
809ab9e68a2SToomas Soome             if (state->flags & 0x0200) {
810ab9e68a2SToomas Soome                 NEEDBITS(16);
811ab9e68a2SToomas Soome                 if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
812ab9e68a2SToomas Soome                     strm->msg = (char *)"header crc mismatch";
813ab9e68a2SToomas Soome                     state->mode = BAD;
814ab9e68a2SToomas Soome                     break;
815ab9e68a2SToomas Soome                 }
816ab9e68a2SToomas Soome                 INITBITS();
817ab9e68a2SToomas Soome             }
818ab9e68a2SToomas Soome             if (state->head != Z_NULL) {
819ab9e68a2SToomas Soome                 state->head->hcrc = (int)((state->flags >> 9) & 1);
820ab9e68a2SToomas Soome                 state->head->done = 1;
821ab9e68a2SToomas Soome             }
822ab9e68a2SToomas Soome             strm->adler = state->check = crc32(0L, Z_NULL, 0);
823ab9e68a2SToomas Soome             state->mode = TYPE;
824ab9e68a2SToomas Soome             break;
825ab9e68a2SToomas Soome #endif
826ab9e68a2SToomas Soome         case DICTID:
827ab9e68a2SToomas Soome             NEEDBITS(32);
828ab9e68a2SToomas Soome             strm->adler = state->check = ZSWAP32(hold);
829ab9e68a2SToomas Soome             INITBITS();
830ab9e68a2SToomas Soome             state->mode = DICT;
831ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
832ab9e68a2SToomas Soome         case DICT:
833ab9e68a2SToomas Soome             if (state->havedict == 0) {
834ab9e68a2SToomas Soome                 RESTORE();
835ab9e68a2SToomas Soome                 return Z_NEED_DICT;
836ab9e68a2SToomas Soome             }
837ab9e68a2SToomas Soome             strm->adler = state->check = adler32(0L, Z_NULL, 0);
838ab9e68a2SToomas Soome             state->mode = TYPE;
839ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
840ab9e68a2SToomas Soome         case TYPE:
841ab9e68a2SToomas Soome             if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
842ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
843ab9e68a2SToomas Soome         case TYPEDO:
844ab9e68a2SToomas Soome             if (state->last) {
845ab9e68a2SToomas Soome                 BYTEBITS();
846ab9e68a2SToomas Soome                 state->mode = CHECK;
847ab9e68a2SToomas Soome                 break;
848ab9e68a2SToomas Soome             }
849ab9e68a2SToomas Soome             NEEDBITS(3);
850ab9e68a2SToomas Soome             state->last = BITS(1);
851ab9e68a2SToomas Soome             DROPBITS(1);
852ab9e68a2SToomas Soome             switch (BITS(2)) {
853ab9e68a2SToomas Soome             case 0:                             /* stored block */
854ab9e68a2SToomas Soome                 Tracev((stderr, "inflate:     stored block%s\n",
855ab9e68a2SToomas Soome                         state->last ? " (last)" : ""));
856ab9e68a2SToomas Soome                 state->mode = STORED;
857ab9e68a2SToomas Soome                 break;
858ab9e68a2SToomas Soome             case 1:                             /* fixed block */
859ab9e68a2SToomas Soome                 fixedtables(state);
860ab9e68a2SToomas Soome                 Tracev((stderr, "inflate:     fixed codes block%s\n",
861ab9e68a2SToomas Soome                         state->last ? " (last)" : ""));
862ab9e68a2SToomas Soome                 state->mode = LEN_;             /* decode codes */
863ab9e68a2SToomas Soome                 if (flush == Z_TREES) {
864ab9e68a2SToomas Soome                     DROPBITS(2);
865ab9e68a2SToomas Soome                     goto inf_leave;
866ab9e68a2SToomas Soome                 }
867ab9e68a2SToomas Soome                 break;
868ab9e68a2SToomas Soome             case 2:                             /* dynamic block */
869ab9e68a2SToomas Soome                 Tracev((stderr, "inflate:     dynamic codes block%s\n",
870ab9e68a2SToomas Soome                         state->last ? " (last)" : ""));
871ab9e68a2SToomas Soome                 state->mode = TABLE;
872ab9e68a2SToomas Soome                 break;
873ab9e68a2SToomas Soome             case 3:
874ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid block type";
875ab9e68a2SToomas Soome                 state->mode = BAD;
876ab9e68a2SToomas Soome             }
877ab9e68a2SToomas Soome             DROPBITS(2);
878ab9e68a2SToomas Soome             break;
879ab9e68a2SToomas Soome         case STORED:
880ab9e68a2SToomas Soome             BYTEBITS();                         /* go to byte boundary */
881ab9e68a2SToomas Soome             NEEDBITS(32);
882ab9e68a2SToomas Soome             if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
883ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid stored block lengths";
884ab9e68a2SToomas Soome                 state->mode = BAD;
885ab9e68a2SToomas Soome                 break;
886ab9e68a2SToomas Soome             }
887ab9e68a2SToomas Soome             state->length = (unsigned)hold & 0xffff;
888ab9e68a2SToomas Soome             Tracev((stderr, "inflate:       stored length %u\n",
889ab9e68a2SToomas Soome                     state->length));
890ab9e68a2SToomas Soome             INITBITS();
891ab9e68a2SToomas Soome             state->mode = COPY_;
892ab9e68a2SToomas Soome             if (flush == Z_TREES) goto inf_leave;
893ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
894ab9e68a2SToomas Soome         case COPY_:
895ab9e68a2SToomas Soome             state->mode = COPY;
896ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
897ab9e68a2SToomas Soome         case COPY:
898ab9e68a2SToomas Soome             copy = state->length;
899ab9e68a2SToomas Soome             if (copy) {
900ab9e68a2SToomas Soome                 if (copy > have) copy = have;
901ab9e68a2SToomas Soome                 if (copy > left) copy = left;
902ab9e68a2SToomas Soome                 if (copy == 0) goto inf_leave;
903ab9e68a2SToomas Soome                 zmemcpy(put, next, copy);
904ab9e68a2SToomas Soome                 have -= copy;
905ab9e68a2SToomas Soome                 next += copy;
906ab9e68a2SToomas Soome                 left -= copy;
907ab9e68a2SToomas Soome                 put += copy;
908ab9e68a2SToomas Soome                 state->length -= copy;
909ab9e68a2SToomas Soome                 break;
910ab9e68a2SToomas Soome             }
911ab9e68a2SToomas Soome             Tracev((stderr, "inflate:       stored end\n"));
912ab9e68a2SToomas Soome             state->mode = TYPE;
913ab9e68a2SToomas Soome             break;
914ab9e68a2SToomas Soome         case TABLE:
915ab9e68a2SToomas Soome             NEEDBITS(14);
916ab9e68a2SToomas Soome             state->nlen = BITS(5) + 257;
917ab9e68a2SToomas Soome             DROPBITS(5);
918ab9e68a2SToomas Soome             state->ndist = BITS(5) + 1;
919ab9e68a2SToomas Soome             DROPBITS(5);
920ab9e68a2SToomas Soome             state->ncode = BITS(4) + 4;
921ab9e68a2SToomas Soome             DROPBITS(4);
922ab9e68a2SToomas Soome #ifndef PKZIP_BUG_WORKAROUND
923ab9e68a2SToomas Soome             if (state->nlen > 286 || state->ndist > 30) {
924ab9e68a2SToomas Soome                 strm->msg = (char *)"too many length or distance symbols";
925ab9e68a2SToomas Soome                 state->mode = BAD;
926ab9e68a2SToomas Soome                 break;
927ab9e68a2SToomas Soome             }
928ab9e68a2SToomas Soome #endif
929ab9e68a2SToomas Soome             Tracev((stderr, "inflate:       table sizes ok\n"));
930ab9e68a2SToomas Soome             state->have = 0;
931ab9e68a2SToomas Soome             state->mode = LENLENS;
93264c3d159SToomas Soome                 /* fallthrough */
933ab9e68a2SToomas Soome         case LENLENS:
934ab9e68a2SToomas Soome             while (state->have < state->ncode) {
935ab9e68a2SToomas Soome                 NEEDBITS(3);
936ab9e68a2SToomas Soome                 state->lens[order[state->have++]] = (unsigned short)BITS(3);
937ab9e68a2SToomas Soome                 DROPBITS(3);
938ab9e68a2SToomas Soome             }
939ab9e68a2SToomas Soome             while (state->have < 19)
940ab9e68a2SToomas Soome                 state->lens[order[state->have++]] = 0;
941ab9e68a2SToomas Soome             state->next = state->codes;
942ab9e68a2SToomas Soome             state->lencode = (const code FAR *)(state->next);
943ab9e68a2SToomas Soome             state->lenbits = 7;
944ab9e68a2SToomas Soome             ret = inflate_table(CODES, state->lens, 19, &(state->next),
945ab9e68a2SToomas Soome                                 &(state->lenbits), state->work);
946ab9e68a2SToomas Soome             if (ret) {
947ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid code lengths set";
948ab9e68a2SToomas Soome                 state->mode = BAD;
949ab9e68a2SToomas Soome                 break;
950ab9e68a2SToomas Soome             }
951ab9e68a2SToomas Soome             Tracev((stderr, "inflate:       code lengths ok\n"));
952ab9e68a2SToomas Soome             state->have = 0;
953ab9e68a2SToomas Soome             state->mode = CODELENS;
95464c3d159SToomas Soome                 /* fallthrough */
955ab9e68a2SToomas Soome         case CODELENS:
956ab9e68a2SToomas Soome             while (state->have < state->nlen + state->ndist) {
957ab9e68a2SToomas Soome                 for (;;) {
958ab9e68a2SToomas Soome                     here = state->lencode[BITS(state->lenbits)];
959ab9e68a2SToomas Soome                     if ((unsigned)(here.bits) <= bits) break;
960ab9e68a2SToomas Soome                     PULLBYTE();
961ab9e68a2SToomas Soome                 }
962ab9e68a2SToomas Soome                 if (here.val < 16) {
963ab9e68a2SToomas Soome                     DROPBITS(here.bits);
964ab9e68a2SToomas Soome                     state->lens[state->have++] = here.val;
965ab9e68a2SToomas Soome                 }
966ab9e68a2SToomas Soome                 else {
967ab9e68a2SToomas Soome                     if (here.val == 16) {
968ab9e68a2SToomas Soome                         NEEDBITS(here.bits + 2);
969ab9e68a2SToomas Soome                         DROPBITS(here.bits);
970ab9e68a2SToomas Soome                         if (state->have == 0) {
971ab9e68a2SToomas Soome                             strm->msg = (char *)"invalid bit length repeat";
972ab9e68a2SToomas Soome                             state->mode = BAD;
973ab9e68a2SToomas Soome                             break;
974ab9e68a2SToomas Soome                         }
975ab9e68a2SToomas Soome                         len = state->lens[state->have - 1];
976ab9e68a2SToomas Soome                         copy = 3 + BITS(2);
977ab9e68a2SToomas Soome                         DROPBITS(2);
978ab9e68a2SToomas Soome                     }
979ab9e68a2SToomas Soome                     else if (here.val == 17) {
980ab9e68a2SToomas Soome                         NEEDBITS(here.bits + 3);
981ab9e68a2SToomas Soome                         DROPBITS(here.bits);
982ab9e68a2SToomas Soome                         len = 0;
983ab9e68a2SToomas Soome                         copy = 3 + BITS(3);
984ab9e68a2SToomas Soome                         DROPBITS(3);
985ab9e68a2SToomas Soome                     }
986ab9e68a2SToomas Soome                     else {
987ab9e68a2SToomas Soome                         NEEDBITS(here.bits + 7);
988ab9e68a2SToomas Soome                         DROPBITS(here.bits);
989ab9e68a2SToomas Soome                         len = 0;
990ab9e68a2SToomas Soome                         copy = 11 + BITS(7);
991ab9e68a2SToomas Soome                         DROPBITS(7);
992ab9e68a2SToomas Soome                     }
993ab9e68a2SToomas Soome                     if (state->have + copy > state->nlen + state->ndist) {
994ab9e68a2SToomas Soome                         strm->msg = (char *)"invalid bit length repeat";
995ab9e68a2SToomas Soome                         state->mode = BAD;
996ab9e68a2SToomas Soome                         break;
997ab9e68a2SToomas Soome                     }
998ab9e68a2SToomas Soome                     while (copy--)
999ab9e68a2SToomas Soome                         state->lens[state->have++] = (unsigned short)len;
1000ab9e68a2SToomas Soome                 }
1001ab9e68a2SToomas Soome             }
1002ab9e68a2SToomas Soome 
1003ab9e68a2SToomas Soome             /* handle error breaks in while */
1004ab9e68a2SToomas Soome             if (state->mode == BAD) break;
1005ab9e68a2SToomas Soome 
1006ab9e68a2SToomas Soome             /* check for end-of-block code (better have one) */
1007ab9e68a2SToomas Soome             if (state->lens[256] == 0) {
1008ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid code -- missing end-of-block";
1009ab9e68a2SToomas Soome                 state->mode = BAD;
1010ab9e68a2SToomas Soome                 break;
1011ab9e68a2SToomas Soome             }
1012ab9e68a2SToomas Soome 
1013ab9e68a2SToomas Soome             /* build code tables -- note: do not change the lenbits or distbits
1014ab9e68a2SToomas Soome                values here (9 and 6) without reading the comments in inftrees.h
1015ab9e68a2SToomas Soome                concerning the ENOUGH constants, which depend on those values */
1016ab9e68a2SToomas Soome             state->next = state->codes;
1017ab9e68a2SToomas Soome             state->lencode = (const code FAR *)(state->next);
1018ab9e68a2SToomas Soome             state->lenbits = 9;
1019ab9e68a2SToomas Soome             ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
1020ab9e68a2SToomas Soome                                 &(state->lenbits), state->work);
1021ab9e68a2SToomas Soome             if (ret) {
1022ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid literal/lengths set";
1023ab9e68a2SToomas Soome                 state->mode = BAD;
1024ab9e68a2SToomas Soome                 break;
1025ab9e68a2SToomas Soome             }
1026ab9e68a2SToomas Soome             state->distcode = (const code FAR *)(state->next);
1027ab9e68a2SToomas Soome             state->distbits = 6;
1028ab9e68a2SToomas Soome             ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
1029ab9e68a2SToomas Soome                             &(state->next), &(state->distbits), state->work);
1030ab9e68a2SToomas Soome             if (ret) {
1031ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid distances set";
1032ab9e68a2SToomas Soome                 state->mode = BAD;
1033ab9e68a2SToomas Soome                 break;
1034ab9e68a2SToomas Soome             }
1035ab9e68a2SToomas Soome             Tracev((stderr, "inflate:       codes ok\n"));
1036ab9e68a2SToomas Soome             state->mode = LEN_;
1037ab9e68a2SToomas Soome             if (flush == Z_TREES) goto inf_leave;
1038ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
1039ab9e68a2SToomas Soome         case LEN_:
1040ab9e68a2SToomas Soome             state->mode = LEN;
1041ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
1042ab9e68a2SToomas Soome         case LEN:
1043ab9e68a2SToomas Soome             if (have >= 6 && left >= 258) {
1044ab9e68a2SToomas Soome                 RESTORE();
1045ab9e68a2SToomas Soome                 inflate_fast(strm, out);
1046ab9e68a2SToomas Soome                 LOAD();
1047ab9e68a2SToomas Soome                 if (state->mode == TYPE)
1048ab9e68a2SToomas Soome                     state->back = -1;
1049ab9e68a2SToomas Soome                 break;
1050ab9e68a2SToomas Soome             }
1051ab9e68a2SToomas Soome             state->back = 0;
1052ab9e68a2SToomas Soome             for (;;) {
1053ab9e68a2SToomas Soome                 here = state->lencode[BITS(state->lenbits)];
1054ab9e68a2SToomas Soome                 if ((unsigned)(here.bits) <= bits) break;
1055ab9e68a2SToomas Soome                 PULLBYTE();
1056ab9e68a2SToomas Soome             }
1057ab9e68a2SToomas Soome             if (here.op && (here.op & 0xf0) == 0) {
1058ab9e68a2SToomas Soome                 last = here;
1059ab9e68a2SToomas Soome                 for (;;) {
1060ab9e68a2SToomas Soome                     here = state->lencode[last.val +
1061ab9e68a2SToomas Soome                             (BITS(last.bits + last.op) >> last.bits)];
1062ab9e68a2SToomas Soome                     if ((unsigned)(last.bits + here.bits) <= bits) break;
1063ab9e68a2SToomas Soome                     PULLBYTE();
1064ab9e68a2SToomas Soome                 }
1065ab9e68a2SToomas Soome                 DROPBITS(last.bits);
1066ab9e68a2SToomas Soome                 state->back += last.bits;
1067ab9e68a2SToomas Soome             }
1068ab9e68a2SToomas Soome             DROPBITS(here.bits);
1069ab9e68a2SToomas Soome             state->back += here.bits;
1070ab9e68a2SToomas Soome             state->length = (unsigned)here.val;
1071ab9e68a2SToomas Soome             if ((int)(here.op) == 0) {
1072ab9e68a2SToomas Soome                 Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
1073ab9e68a2SToomas Soome                         "inflate:         literal '%c'\n" :
1074ab9e68a2SToomas Soome                         "inflate:         literal 0x%02x\n", here.val));
1075ab9e68a2SToomas Soome                 state->mode = LIT;
1076ab9e68a2SToomas Soome                 break;
1077ab9e68a2SToomas Soome             }
1078ab9e68a2SToomas Soome             if (here.op & 32) {
1079ab9e68a2SToomas Soome                 Tracevv((stderr, "inflate:         end of block\n"));
1080ab9e68a2SToomas Soome                 state->back = -1;
1081ab9e68a2SToomas Soome                 state->mode = TYPE;
1082ab9e68a2SToomas Soome                 break;
1083ab9e68a2SToomas Soome             }
1084ab9e68a2SToomas Soome             if (here.op & 64) {
1085ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid literal/length code";
1086ab9e68a2SToomas Soome                 state->mode = BAD;
1087ab9e68a2SToomas Soome                 break;
1088ab9e68a2SToomas Soome             }
1089ab9e68a2SToomas Soome             state->extra = (unsigned)(here.op) & 15;
1090ab9e68a2SToomas Soome             state->mode = LENEXT;
1091ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
1092ab9e68a2SToomas Soome         case LENEXT:
1093ab9e68a2SToomas Soome             if (state->extra) {
1094ab9e68a2SToomas Soome                 NEEDBITS(state->extra);
1095ab9e68a2SToomas Soome                 state->length += BITS(state->extra);
1096ab9e68a2SToomas Soome                 DROPBITS(state->extra);
1097ab9e68a2SToomas Soome                 state->back += state->extra;
1098ab9e68a2SToomas Soome             }
1099ab9e68a2SToomas Soome             Tracevv((stderr, "inflate:         length %u\n", state->length));
1100ab9e68a2SToomas Soome             state->was = state->length;
1101ab9e68a2SToomas Soome             state->mode = DIST;
1102ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
1103ab9e68a2SToomas Soome         case DIST:
1104ab9e68a2SToomas Soome             for (;;) {
1105ab9e68a2SToomas Soome                 here = state->distcode[BITS(state->distbits)];
1106ab9e68a2SToomas Soome                 if ((unsigned)(here.bits) <= bits) break;
1107ab9e68a2SToomas Soome                 PULLBYTE();
1108ab9e68a2SToomas Soome             }
1109ab9e68a2SToomas Soome             if ((here.op & 0xf0) == 0) {
1110ab9e68a2SToomas Soome                 last = here;
1111ab9e68a2SToomas Soome                 for (;;) {
1112ab9e68a2SToomas Soome                     here = state->distcode[last.val +
1113ab9e68a2SToomas Soome                             (BITS(last.bits + last.op) >> last.bits)];
1114ab9e68a2SToomas Soome                     if ((unsigned)(last.bits + here.bits) <= bits) break;
1115ab9e68a2SToomas Soome                     PULLBYTE();
1116ab9e68a2SToomas Soome                 }
1117ab9e68a2SToomas Soome                 DROPBITS(last.bits);
1118ab9e68a2SToomas Soome                 state->back += last.bits;
1119ab9e68a2SToomas Soome             }
1120ab9e68a2SToomas Soome             DROPBITS(here.bits);
1121ab9e68a2SToomas Soome             state->back += here.bits;
1122ab9e68a2SToomas Soome             if (here.op & 64) {
1123ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid distance code";
1124ab9e68a2SToomas Soome                 state->mode = BAD;
1125ab9e68a2SToomas Soome                 break;
1126ab9e68a2SToomas Soome             }
1127ab9e68a2SToomas Soome             state->offset = (unsigned)here.val;
1128ab9e68a2SToomas Soome             state->extra = (unsigned)(here.op) & 15;
1129ab9e68a2SToomas Soome             state->mode = DISTEXT;
1130ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
1131ab9e68a2SToomas Soome         case DISTEXT:
1132ab9e68a2SToomas Soome             if (state->extra) {
1133ab9e68a2SToomas Soome                 NEEDBITS(state->extra);
1134ab9e68a2SToomas Soome                 state->offset += BITS(state->extra);
1135ab9e68a2SToomas Soome                 DROPBITS(state->extra);
1136ab9e68a2SToomas Soome                 state->back += state->extra;
1137ab9e68a2SToomas Soome             }
1138ab9e68a2SToomas Soome #ifdef INFLATE_STRICT
1139ab9e68a2SToomas Soome             if (state->offset > state->dmax) {
1140ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid distance too far back";
1141ab9e68a2SToomas Soome                 state->mode = BAD;
1142ab9e68a2SToomas Soome                 break;
1143ab9e68a2SToomas Soome             }
1144ab9e68a2SToomas Soome #endif
1145ab9e68a2SToomas Soome             Tracevv((stderr, "inflate:         distance %u\n", state->offset));
1146ab9e68a2SToomas Soome             state->mode = MATCH;
1147ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
1148ab9e68a2SToomas Soome         case MATCH:
1149ab9e68a2SToomas Soome             if (left == 0) goto inf_leave;
1150ab9e68a2SToomas Soome             copy = out - left;
1151ab9e68a2SToomas Soome             if (state->offset > copy) {         /* copy from window */
1152ab9e68a2SToomas Soome                 copy = state->offset - copy;
1153ab9e68a2SToomas Soome                 if (copy > state->whave) {
1154ab9e68a2SToomas Soome                     if (state->sane) {
1155ab9e68a2SToomas Soome                         strm->msg = (char *)"invalid distance too far back";
1156ab9e68a2SToomas Soome                         state->mode = BAD;
1157ab9e68a2SToomas Soome                         break;
1158ab9e68a2SToomas Soome                     }
1159ab9e68a2SToomas Soome #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
1160ab9e68a2SToomas Soome                     Trace((stderr, "inflate.c too far\n"));
1161ab9e68a2SToomas Soome                     copy -= state->whave;
1162ab9e68a2SToomas Soome                     if (copy > state->length) copy = state->length;
1163ab9e68a2SToomas Soome                     if (copy > left) copy = left;
1164ab9e68a2SToomas Soome                     left -= copy;
1165ab9e68a2SToomas Soome                     state->length -= copy;
1166ab9e68a2SToomas Soome                     do {
1167ab9e68a2SToomas Soome                         *put++ = 0;
1168ab9e68a2SToomas Soome                     } while (--copy);
1169ab9e68a2SToomas Soome                     if (state->length == 0) state->mode = LEN;
1170ab9e68a2SToomas Soome                     break;
1171ab9e68a2SToomas Soome #endif
1172ab9e68a2SToomas Soome                 }
1173ab9e68a2SToomas Soome                 if (copy > state->wnext) {
1174ab9e68a2SToomas Soome                     copy -= state->wnext;
1175ab9e68a2SToomas Soome                     from = state->window + (state->wsize - copy);
1176ab9e68a2SToomas Soome                 }
1177ab9e68a2SToomas Soome                 else
1178ab9e68a2SToomas Soome                     from = state->window + (state->wnext - copy);
1179ab9e68a2SToomas Soome                 if (copy > state->length) copy = state->length;
1180ab9e68a2SToomas Soome             }
1181ab9e68a2SToomas Soome             else {                              /* copy from output */
1182ab9e68a2SToomas Soome                 from = put - state->offset;
1183ab9e68a2SToomas Soome                 copy = state->length;
1184ab9e68a2SToomas Soome             }
1185ab9e68a2SToomas Soome             if (copy > left) copy = left;
1186ab9e68a2SToomas Soome             left -= copy;
1187ab9e68a2SToomas Soome             state->length -= copy;
1188ab9e68a2SToomas Soome             do {
1189ab9e68a2SToomas Soome                 *put++ = *from++;
1190ab9e68a2SToomas Soome             } while (--copy);
1191ab9e68a2SToomas Soome             if (state->length == 0) state->mode = LEN;
1192ab9e68a2SToomas Soome             break;
1193ab9e68a2SToomas Soome         case LIT:
1194ab9e68a2SToomas Soome             if (left == 0) goto inf_leave;
1195ab9e68a2SToomas Soome             *put++ = (unsigned char)(state->length);
1196ab9e68a2SToomas Soome             left--;
1197ab9e68a2SToomas Soome             state->mode = LEN;
1198ab9e68a2SToomas Soome             break;
1199ab9e68a2SToomas Soome         case CHECK:
1200ab9e68a2SToomas Soome             if (state->wrap) {
1201ab9e68a2SToomas Soome                 NEEDBITS(32);
1202ab9e68a2SToomas Soome                 out -= left;
1203ab9e68a2SToomas Soome                 strm->total_out += out;
1204ab9e68a2SToomas Soome                 state->total += out;
1205ab9e68a2SToomas Soome                 if ((state->wrap & 4) && out)
1206ab9e68a2SToomas Soome                     strm->adler = state->check =
120764c3d159SToomas Soome                         UPDATE_CHECK(state->check, put - out, out);
1208ab9e68a2SToomas Soome                 out = left;
1209ab9e68a2SToomas Soome                 if ((state->wrap & 4) && (
1210ab9e68a2SToomas Soome #ifdef GUNZIP
1211ab9e68a2SToomas Soome                      state->flags ? hold :
1212ab9e68a2SToomas Soome #endif
1213ab9e68a2SToomas Soome                      ZSWAP32(hold)) != state->check) {
1214ab9e68a2SToomas Soome                     strm->msg = (char *)"incorrect data check";
1215ab9e68a2SToomas Soome                     state->mode = BAD;
1216ab9e68a2SToomas Soome                     break;
1217ab9e68a2SToomas Soome                 }
1218ab9e68a2SToomas Soome                 INITBITS();
1219ab9e68a2SToomas Soome                 Tracev((stderr, "inflate:   check matches trailer\n"));
1220ab9e68a2SToomas Soome             }
1221ab9e68a2SToomas Soome #ifdef GUNZIP
1222ab9e68a2SToomas Soome             state->mode = LENGTH;
1223ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
1224ab9e68a2SToomas Soome         case LENGTH:
1225ab9e68a2SToomas Soome             if (state->wrap && state->flags) {
1226ab9e68a2SToomas Soome                 NEEDBITS(32);
122764c3d159SToomas Soome                 if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
1228ab9e68a2SToomas Soome                     strm->msg = (char *)"incorrect length check";
1229ab9e68a2SToomas Soome                     state->mode = BAD;
1230ab9e68a2SToomas Soome                     break;
1231ab9e68a2SToomas Soome                 }
1232ab9e68a2SToomas Soome                 INITBITS();
1233ab9e68a2SToomas Soome                 Tracev((stderr, "inflate:   length matches trailer\n"));
1234ab9e68a2SToomas Soome             }
1235ab9e68a2SToomas Soome #endif
1236ab9e68a2SToomas Soome             state->mode = DONE;
1237ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
1238ab9e68a2SToomas Soome         case DONE:
1239ab9e68a2SToomas Soome             ret = Z_STREAM_END;
1240ab9e68a2SToomas Soome             goto inf_leave;
1241ab9e68a2SToomas Soome         case BAD:
1242ab9e68a2SToomas Soome             ret = Z_DATA_ERROR;
1243ab9e68a2SToomas Soome             goto inf_leave;
1244ab9e68a2SToomas Soome         case MEM:
1245ab9e68a2SToomas Soome             return Z_MEM_ERROR;
1246ab9e68a2SToomas Soome         case SYNC:
124764c3d159SToomas Soome                 /* fallthrough */
1248ab9e68a2SToomas Soome         default:
1249ab9e68a2SToomas Soome             return Z_STREAM_ERROR;
1250ab9e68a2SToomas Soome         }
1251ab9e68a2SToomas Soome 
1252ab9e68a2SToomas Soome     /*
1253ab9e68a2SToomas Soome        Return from inflate(), updating the total counts and the check value.
1254ab9e68a2SToomas Soome        If there was no progress during the inflate() call, return a buffer
1255ab9e68a2SToomas Soome        error.  Call updatewindow() to create and/or update the window state.
1256ab9e68a2SToomas Soome        Note: a memory error from inflate() is non-recoverable.
1257ab9e68a2SToomas Soome      */
1258ab9e68a2SToomas Soome   inf_leave:
1259ab9e68a2SToomas Soome     RESTORE();
1260ab9e68a2SToomas Soome     if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
1261ab9e68a2SToomas Soome             (state->mode < CHECK || flush != Z_FINISH)))
1262ab9e68a2SToomas Soome         if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
1263ab9e68a2SToomas Soome             state->mode = MEM;
1264ab9e68a2SToomas Soome             return Z_MEM_ERROR;
1265ab9e68a2SToomas Soome         }
1266ab9e68a2SToomas Soome     in -= strm->avail_in;
1267ab9e68a2SToomas Soome     out -= strm->avail_out;
1268ab9e68a2SToomas Soome     strm->total_in += in;
1269ab9e68a2SToomas Soome     strm->total_out += out;
1270ab9e68a2SToomas Soome     state->total += out;
1271ab9e68a2SToomas Soome     if ((state->wrap & 4) && out)
1272ab9e68a2SToomas Soome         strm->adler = state->check =
127364c3d159SToomas Soome             UPDATE_CHECK(state->check, strm->next_out - out, out);
1274ab9e68a2SToomas Soome     strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
1275ab9e68a2SToomas Soome                       (state->mode == TYPE ? 128 : 0) +
1276ab9e68a2SToomas Soome                       (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
1277ab9e68a2SToomas Soome     if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
1278ab9e68a2SToomas Soome         ret = Z_BUF_ERROR;
1279ab9e68a2SToomas Soome     return ret;
1280ab9e68a2SToomas Soome }
1281ab9e68a2SToomas Soome 
1282ab9e68a2SToomas Soome int ZEXPORT inflateEnd(z_streamp strm)
1283ab9e68a2SToomas Soome {
1284ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1285ab9e68a2SToomas Soome     if (inflateStateCheck(strm))
1286ab9e68a2SToomas Soome         return Z_STREAM_ERROR;
1287ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1288ab9e68a2SToomas Soome     if (state->window != Z_NULL) ZFREE(strm, state->window);
1289ab9e68a2SToomas Soome     ZFREE(strm, strm->state);
1290ab9e68a2SToomas Soome     strm->state = Z_NULL;
1291ab9e68a2SToomas Soome     Tracev((stderr, "inflate: end\n"));
1292ab9e68a2SToomas Soome     return Z_OK;
1293ab9e68a2SToomas Soome }
1294ab9e68a2SToomas Soome 
1295ab9e68a2SToomas Soome int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary,
1296ab9e68a2SToomas Soome     uInt *dictLength)
1297ab9e68a2SToomas Soome {
1298ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1299ab9e68a2SToomas Soome 
1300ab9e68a2SToomas Soome     /* check state */
1301ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
1302ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1303ab9e68a2SToomas Soome 
1304ab9e68a2SToomas Soome     /* copy dictionary */
1305ab9e68a2SToomas Soome     if (state->whave && dictionary != Z_NULL) {
1306ab9e68a2SToomas Soome         zmemcpy(dictionary, state->window + state->wnext,
1307ab9e68a2SToomas Soome                 state->whave - state->wnext);
1308ab9e68a2SToomas Soome         zmemcpy(dictionary + state->whave - state->wnext,
1309ab9e68a2SToomas Soome                 state->window, state->wnext);
1310ab9e68a2SToomas Soome     }
1311ab9e68a2SToomas Soome     if (dictLength != Z_NULL)
1312ab9e68a2SToomas Soome         *dictLength = state->whave;
1313ab9e68a2SToomas Soome     return Z_OK;
1314ab9e68a2SToomas Soome }
1315ab9e68a2SToomas Soome 
1316ab9e68a2SToomas Soome int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary,
1317ab9e68a2SToomas Soome     uInt dictLength)
1318ab9e68a2SToomas Soome {
1319ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1320ab9e68a2SToomas Soome     unsigned long dictid;
1321ab9e68a2SToomas Soome     int ret;
1322ab9e68a2SToomas Soome 
1323ab9e68a2SToomas Soome     /* check state */
1324ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
1325ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1326ab9e68a2SToomas Soome     if (state->wrap != 0 && state->mode != DICT)
1327ab9e68a2SToomas Soome         return Z_STREAM_ERROR;
1328ab9e68a2SToomas Soome 
1329ab9e68a2SToomas Soome     /* check for correct dictionary identifier */
1330ab9e68a2SToomas Soome     if (state->mode == DICT) {
1331ab9e68a2SToomas Soome         dictid = adler32(0L, Z_NULL, 0);
1332ab9e68a2SToomas Soome         dictid = adler32(dictid, dictionary, dictLength);
1333ab9e68a2SToomas Soome         if (dictid != state->check)
1334ab9e68a2SToomas Soome             return Z_DATA_ERROR;
1335ab9e68a2SToomas Soome     }
1336ab9e68a2SToomas Soome 
1337ab9e68a2SToomas Soome     /* copy dictionary to window using updatewindow(), which will amend the
1338ab9e68a2SToomas Soome        existing dictionary if appropriate */
1339ab9e68a2SToomas Soome     ret = updatewindow(strm, dictionary + dictLength, dictLength);
1340ab9e68a2SToomas Soome     if (ret) {
1341ab9e68a2SToomas Soome         state->mode = MEM;
1342ab9e68a2SToomas Soome         return Z_MEM_ERROR;
1343ab9e68a2SToomas Soome     }
1344ab9e68a2SToomas Soome     state->havedict = 1;
1345ab9e68a2SToomas Soome     Tracev((stderr, "inflate:   dictionary set\n"));
1346ab9e68a2SToomas Soome     return Z_OK;
1347ab9e68a2SToomas Soome }
1348ab9e68a2SToomas Soome 
1349ab9e68a2SToomas Soome int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head)
1350ab9e68a2SToomas Soome {
1351ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1352ab9e68a2SToomas Soome 
1353ab9e68a2SToomas Soome     /* check state */
1354ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
1355ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1356ab9e68a2SToomas Soome     if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
1357ab9e68a2SToomas Soome 
1358ab9e68a2SToomas Soome     /* save header structure */
1359ab9e68a2SToomas Soome     state->head = head;
1360ab9e68a2SToomas Soome     head->done = 0;
1361ab9e68a2SToomas Soome     return Z_OK;
1362ab9e68a2SToomas Soome }
1363ab9e68a2SToomas Soome 
1364ab9e68a2SToomas Soome /*
1365ab9e68a2SToomas Soome    Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
1366ab9e68a2SToomas Soome    or when out of input.  When called, *have is the number of pattern bytes
1367ab9e68a2SToomas Soome    found in order so far, in 0..3.  On return *have is updated to the new
1368ab9e68a2SToomas Soome    state.  If on return *have equals four, then the pattern was found and the
1369ab9e68a2SToomas Soome    return value is how many bytes were read including the last byte of the
1370ab9e68a2SToomas Soome    pattern.  If *have is less than four, then the pattern has not been found
1371ab9e68a2SToomas Soome    yet and the return value is len.  In the latter case, syncsearch() can be
1372ab9e68a2SToomas Soome    called again with more data and the *have state.  *have is initialized to
1373ab9e68a2SToomas Soome    zero for the first call.
1374ab9e68a2SToomas Soome  */
1375ab9e68a2SToomas Soome local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf,
1376ab9e68a2SToomas Soome     unsigned len)
1377ab9e68a2SToomas Soome {
1378ab9e68a2SToomas Soome     unsigned got;
1379ab9e68a2SToomas Soome     unsigned next;
1380ab9e68a2SToomas Soome 
1381ab9e68a2SToomas Soome     got = *have;
1382ab9e68a2SToomas Soome     next = 0;
1383ab9e68a2SToomas Soome     while (next < len && got < 4) {
1384ab9e68a2SToomas Soome         if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
1385ab9e68a2SToomas Soome             got++;
1386ab9e68a2SToomas Soome         else if (buf[next])
1387ab9e68a2SToomas Soome             got = 0;
1388ab9e68a2SToomas Soome         else
1389ab9e68a2SToomas Soome             got = 4 - got;
1390ab9e68a2SToomas Soome         next++;
1391ab9e68a2SToomas Soome     }
1392ab9e68a2SToomas Soome     *have = got;
1393ab9e68a2SToomas Soome     return next;
1394ab9e68a2SToomas Soome }
1395ab9e68a2SToomas Soome 
1396ab9e68a2SToomas Soome int ZEXPORT inflateSync(z_streamp strm)
1397ab9e68a2SToomas Soome {
1398ab9e68a2SToomas Soome     unsigned len;               /* number of bytes to look at or looked at */
139964c3d159SToomas Soome     int flags;                  /* temporary to save header status */
1400ab9e68a2SToomas Soome     unsigned long in, out;      /* temporary to save total_in and total_out */
1401ab9e68a2SToomas Soome     unsigned char buf[4];       /* to restore bit buffer to byte string */
1402ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1403ab9e68a2SToomas Soome 
1404ab9e68a2SToomas Soome     /* check parameters */
1405ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
1406ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1407ab9e68a2SToomas Soome     if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
1408ab9e68a2SToomas Soome 
1409ab9e68a2SToomas Soome     /* if first time, start search in bit buffer */
1410ab9e68a2SToomas Soome     if (state->mode != SYNC) {
1411ab9e68a2SToomas Soome         state->mode = SYNC;
1412ab9e68a2SToomas Soome         state->hold <<= state->bits & 7;
1413ab9e68a2SToomas Soome         state->bits -= state->bits & 7;
1414ab9e68a2SToomas Soome         len = 0;
1415ab9e68a2SToomas Soome         while (state->bits >= 8) {
1416ab9e68a2SToomas Soome             buf[len++] = (unsigned char)(state->hold);
1417ab9e68a2SToomas Soome             state->hold >>= 8;
1418ab9e68a2SToomas Soome             state->bits -= 8;
1419ab9e68a2SToomas Soome         }
1420ab9e68a2SToomas Soome         state->have = 0;
1421ab9e68a2SToomas Soome         syncsearch(&(state->have), buf, len);
1422ab9e68a2SToomas Soome     }
1423ab9e68a2SToomas Soome 
1424ab9e68a2SToomas Soome     /* search available input */
1425ab9e68a2SToomas Soome     len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
1426ab9e68a2SToomas Soome     strm->avail_in -= len;
1427ab9e68a2SToomas Soome     strm->next_in += len;
1428ab9e68a2SToomas Soome     strm->total_in += len;
1429ab9e68a2SToomas Soome 
1430ab9e68a2SToomas Soome     /* return no joy or set up to restart inflate() on a new block */
1431ab9e68a2SToomas Soome     if (state->have != 4) return Z_DATA_ERROR;
143264c3d159SToomas Soome     if (state->flags == -1)
143364c3d159SToomas Soome         state->wrap = 0;    /* if no header yet, treat as raw */
143464c3d159SToomas Soome     else
143564c3d159SToomas Soome         state->wrap &= ~4;  /* no point in computing a check value now */
143664c3d159SToomas Soome     flags = state->flags;
1437ab9e68a2SToomas Soome     in = strm->total_in;  out = strm->total_out;
1438ab9e68a2SToomas Soome     inflateReset(strm);
1439ab9e68a2SToomas Soome     strm->total_in = in;  strm->total_out = out;
144064c3d159SToomas Soome     state->flags = flags;
1441ab9e68a2SToomas Soome     state->mode = TYPE;
1442ab9e68a2SToomas Soome     return Z_OK;
1443ab9e68a2SToomas Soome }
1444ab9e68a2SToomas Soome 
1445ab9e68a2SToomas Soome /*
1446ab9e68a2SToomas Soome    Returns true if inflate is currently at the end of a block generated by
1447ab9e68a2SToomas Soome    Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
1448ab9e68a2SToomas Soome    implementation to provide an additional safety check. PPP uses
1449ab9e68a2SToomas Soome    Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
1450ab9e68a2SToomas Soome    block. When decompressing, PPP checks that at the end of input packet,
1451ab9e68a2SToomas Soome    inflate is waiting for these length bytes.
1452ab9e68a2SToomas Soome  */
1453ab9e68a2SToomas Soome int ZEXPORT inflateSyncPoint(z_streamp strm)
1454ab9e68a2SToomas Soome {
1455ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1456ab9e68a2SToomas Soome 
1457ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
1458ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1459ab9e68a2SToomas Soome     return state->mode == STORED && state->bits == 0;
1460ab9e68a2SToomas Soome }
1461ab9e68a2SToomas Soome 
1462ab9e68a2SToomas Soome int ZEXPORT inflateCopy(z_streamp dest, z_streamp source)
1463ab9e68a2SToomas Soome {
1464ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1465ab9e68a2SToomas Soome     struct inflate_state FAR *copy;
1466ab9e68a2SToomas Soome     unsigned char FAR *window;
1467ab9e68a2SToomas Soome     unsigned wsize;
1468ab9e68a2SToomas Soome 
1469ab9e68a2SToomas Soome     /* check input */
1470ab9e68a2SToomas Soome     if (inflateStateCheck(source) || dest == Z_NULL)
1471ab9e68a2SToomas Soome         return Z_STREAM_ERROR;
1472ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)source->state;
1473ab9e68a2SToomas Soome 
1474ab9e68a2SToomas Soome     /* allocate space */
1475ab9e68a2SToomas Soome     copy = (struct inflate_state FAR *)
1476ab9e68a2SToomas Soome            ZALLOC(source, 1, sizeof(struct inflate_state));
1477ab9e68a2SToomas Soome     if (copy == Z_NULL) return Z_MEM_ERROR;
1478ab9e68a2SToomas Soome     window = Z_NULL;
1479ab9e68a2SToomas Soome     if (state->window != Z_NULL) {
1480ab9e68a2SToomas Soome         window = (unsigned char FAR *)
1481ab9e68a2SToomas Soome                  ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
1482ab9e68a2SToomas Soome         if (window == Z_NULL) {
1483ab9e68a2SToomas Soome             ZFREE(source, copy);
1484ab9e68a2SToomas Soome             return Z_MEM_ERROR;
1485ab9e68a2SToomas Soome         }
1486ab9e68a2SToomas Soome     }
1487ab9e68a2SToomas Soome 
1488ab9e68a2SToomas Soome     /* copy state */
1489ab9e68a2SToomas Soome     zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
1490ab9e68a2SToomas Soome     zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
1491ab9e68a2SToomas Soome     copy->strm = dest;
1492ab9e68a2SToomas Soome     if (state->lencode >= state->codes &&
1493ab9e68a2SToomas Soome         state->lencode <= state->codes + ENOUGH - 1) {
1494ab9e68a2SToomas Soome         copy->lencode = copy->codes + (state->lencode - state->codes);
1495ab9e68a2SToomas Soome         copy->distcode = copy->codes + (state->distcode - state->codes);
1496ab9e68a2SToomas Soome     }
1497ab9e68a2SToomas Soome     copy->next = copy->codes + (state->next - state->codes);
1498ab9e68a2SToomas Soome     if (window != Z_NULL) {
1499ab9e68a2SToomas Soome         wsize = 1U << state->wbits;
1500ab9e68a2SToomas Soome         zmemcpy(window, state->window, wsize);
1501ab9e68a2SToomas Soome     }
1502ab9e68a2SToomas Soome     copy->window = window;
1503ab9e68a2SToomas Soome     dest->state = (struct internal_state FAR *)copy;
1504ab9e68a2SToomas Soome     return Z_OK;
1505ab9e68a2SToomas Soome }
1506ab9e68a2SToomas Soome 
1507ab9e68a2SToomas Soome int ZEXPORT inflateUndermine(z_streamp strm, int subvert)
1508ab9e68a2SToomas Soome {
1509ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1510ab9e68a2SToomas Soome 
1511ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
1512ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1513ab9e68a2SToomas Soome #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
1514ab9e68a2SToomas Soome     state->sane = !subvert;
1515ab9e68a2SToomas Soome     return Z_OK;
1516ab9e68a2SToomas Soome #else
1517ab9e68a2SToomas Soome     (void)subvert;
1518ab9e68a2SToomas Soome     state->sane = 1;
1519ab9e68a2SToomas Soome     return Z_DATA_ERROR;
1520ab9e68a2SToomas Soome #endif
1521ab9e68a2SToomas Soome }
1522ab9e68a2SToomas Soome 
1523ab9e68a2SToomas Soome int ZEXPORT inflateValidate(z_streamp strm, int check)
1524ab9e68a2SToomas Soome {
1525ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1526ab9e68a2SToomas Soome 
1527ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
1528ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
152964c3d159SToomas Soome     if (check && state->wrap)
1530ab9e68a2SToomas Soome         state->wrap |= 4;
1531ab9e68a2SToomas Soome     else
1532ab9e68a2SToomas Soome         state->wrap &= ~4;
1533ab9e68a2SToomas Soome     return Z_OK;
1534ab9e68a2SToomas Soome }
1535ab9e68a2SToomas Soome 
1536ab9e68a2SToomas Soome long ZEXPORT inflateMark(z_streamp strm)
1537ab9e68a2SToomas Soome {
1538ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1539ab9e68a2SToomas Soome 
1540ab9e68a2SToomas Soome     if (inflateStateCheck(strm))
1541ab9e68a2SToomas Soome         return -(1L << 16);
1542ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1543ab9e68a2SToomas Soome     return (long)(((unsigned long)((long)state->back)) << 16) +
1544ab9e68a2SToomas Soome         (state->mode == COPY ? state->length :
1545ab9e68a2SToomas Soome             (state->mode == MATCH ? state->was - state->length : 0));
1546ab9e68a2SToomas Soome }
1547ab9e68a2SToomas Soome 
1548ab9e68a2SToomas Soome unsigned long ZEXPORT inflateCodesUsed(z_streamp strm)
1549ab9e68a2SToomas Soome {
1550ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1551ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return (unsigned long)-1;
1552ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1553ab9e68a2SToomas Soome     return (unsigned long)(state->next - state->codes);
1554ab9e68a2SToomas Soome }
1555