xref: /titanic_54/usr/src/contrib/zlib/inflate.c (revision 64c3d15931c5518f89221f1e36d3015dbb54b9bd)
1ab9e68a2SToomas Soome /* inflate.c -- zlib decompression
2*64c3d159SToomas 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;
131*64c3d159SToomas 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
433*64c3d159SToomas Soome #  define UPDATE_CHECK(check, buf, len) \
434ab9e68a2SToomas Soome     (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
435ab9e68a2SToomas Soome #else
436*64c3d159SToomas 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;
680*64c3d159SToomas 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;
706*64c3d159SToomas 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;
715*64c3d159SToomas 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 &&
747ab9e68a2SToomas Soome                         state->head->extra != Z_NULL) {
748ab9e68a2SToomas Soome                         len = state->head->extra_len - state->length;
749ab9e68a2SToomas Soome                         zmemcpy(state->head->extra + len, next,
750ab9e68a2SToomas Soome                                 len + copy > state->head->extra_max ?
751ab9e68a2SToomas Soome                                 state->head->extra_max - len : copy);
752ab9e68a2SToomas Soome                     }
753ab9e68a2SToomas Soome                     if ((state->flags & 0x0200) && (state->wrap & 4))
754ab9e68a2SToomas Soome                         state->check = crc32(state->check, next, copy);
755ab9e68a2SToomas Soome                     have -= copy;
756ab9e68a2SToomas Soome                     next += copy;
757ab9e68a2SToomas Soome                     state->length -= copy;
758ab9e68a2SToomas Soome                 }
759ab9e68a2SToomas Soome                 if (state->length) goto inf_leave;
760ab9e68a2SToomas Soome             }
761ab9e68a2SToomas Soome             state->length = 0;
762ab9e68a2SToomas Soome             state->mode = NAME;
763ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
764ab9e68a2SToomas Soome         case NAME:
765ab9e68a2SToomas Soome             if (state->flags & 0x0800) {
766ab9e68a2SToomas Soome                 if (have == 0) goto inf_leave;
767ab9e68a2SToomas Soome                 copy = 0;
768ab9e68a2SToomas Soome                 do {
769ab9e68a2SToomas Soome                     len = (unsigned)(next[copy++]);
770ab9e68a2SToomas Soome                     if (state->head != Z_NULL &&
771ab9e68a2SToomas Soome                             state->head->name != Z_NULL &&
772ab9e68a2SToomas Soome                             state->length < state->head->name_max)
773ab9e68a2SToomas Soome                         state->head->name[state->length++] = (Bytef)len;
774ab9e68a2SToomas Soome                 } while (len && copy < have);
775ab9e68a2SToomas Soome                 if ((state->flags & 0x0200) && (state->wrap & 4))
776ab9e68a2SToomas Soome                     state->check = crc32(state->check, next, copy);
777ab9e68a2SToomas Soome                 have -= copy;
778ab9e68a2SToomas Soome                 next += copy;
779ab9e68a2SToomas Soome                 if (len) goto inf_leave;
780ab9e68a2SToomas Soome             }
781ab9e68a2SToomas Soome             else if (state->head != Z_NULL)
782ab9e68a2SToomas Soome                 state->head->name = Z_NULL;
783ab9e68a2SToomas Soome             state->length = 0;
784ab9e68a2SToomas Soome             state->mode = COMMENT;
785ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
786ab9e68a2SToomas Soome         case COMMENT:
787ab9e68a2SToomas Soome             if (state->flags & 0x1000) {
788ab9e68a2SToomas Soome                 if (have == 0) goto inf_leave;
789ab9e68a2SToomas Soome                 copy = 0;
790ab9e68a2SToomas Soome                 do {
791ab9e68a2SToomas Soome                     len = (unsigned)(next[copy++]);
792ab9e68a2SToomas Soome                     if (state->head != Z_NULL &&
793ab9e68a2SToomas Soome                             state->head->comment != Z_NULL &&
794ab9e68a2SToomas Soome                             state->length < state->head->comm_max)
795ab9e68a2SToomas Soome                         state->head->comment[state->length++] = (Bytef)len;
796ab9e68a2SToomas Soome                 } while (len && copy < have);
797ab9e68a2SToomas Soome                 if ((state->flags & 0x0200) && (state->wrap & 4))
798ab9e68a2SToomas Soome                     state->check = crc32(state->check, next, copy);
799ab9e68a2SToomas Soome                 have -= copy;
800ab9e68a2SToomas Soome                 next += copy;
801ab9e68a2SToomas Soome                 if (len) goto inf_leave;
802ab9e68a2SToomas Soome             }
803ab9e68a2SToomas Soome             else if (state->head != Z_NULL)
804ab9e68a2SToomas Soome                 state->head->comment = Z_NULL;
805ab9e68a2SToomas Soome             state->mode = HCRC;
806ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
807ab9e68a2SToomas Soome         case HCRC:
808ab9e68a2SToomas Soome             if (state->flags & 0x0200) {
809ab9e68a2SToomas Soome                 NEEDBITS(16);
810ab9e68a2SToomas Soome                 if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
811ab9e68a2SToomas Soome                     strm->msg = (char *)"header crc mismatch";
812ab9e68a2SToomas Soome                     state->mode = BAD;
813ab9e68a2SToomas Soome                     break;
814ab9e68a2SToomas Soome                 }
815ab9e68a2SToomas Soome                 INITBITS();
816ab9e68a2SToomas Soome             }
817ab9e68a2SToomas Soome             if (state->head != Z_NULL) {
818ab9e68a2SToomas Soome                 state->head->hcrc = (int)((state->flags >> 9) & 1);
819ab9e68a2SToomas Soome                 state->head->done = 1;
820ab9e68a2SToomas Soome             }
821ab9e68a2SToomas Soome             strm->adler = state->check = crc32(0L, Z_NULL, 0);
822ab9e68a2SToomas Soome             state->mode = TYPE;
823ab9e68a2SToomas Soome             break;
824ab9e68a2SToomas Soome #endif
825ab9e68a2SToomas Soome         case DICTID:
826ab9e68a2SToomas Soome             NEEDBITS(32);
827ab9e68a2SToomas Soome             strm->adler = state->check = ZSWAP32(hold);
828ab9e68a2SToomas Soome             INITBITS();
829ab9e68a2SToomas Soome             state->mode = DICT;
830ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
831ab9e68a2SToomas Soome         case DICT:
832ab9e68a2SToomas Soome             if (state->havedict == 0) {
833ab9e68a2SToomas Soome                 RESTORE();
834ab9e68a2SToomas Soome                 return Z_NEED_DICT;
835ab9e68a2SToomas Soome             }
836ab9e68a2SToomas Soome             strm->adler = state->check = adler32(0L, Z_NULL, 0);
837ab9e68a2SToomas Soome             state->mode = TYPE;
838ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
839ab9e68a2SToomas Soome         case TYPE:
840ab9e68a2SToomas Soome             if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
841ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
842ab9e68a2SToomas Soome         case TYPEDO:
843ab9e68a2SToomas Soome             if (state->last) {
844ab9e68a2SToomas Soome                 BYTEBITS();
845ab9e68a2SToomas Soome                 state->mode = CHECK;
846ab9e68a2SToomas Soome                 break;
847ab9e68a2SToomas Soome             }
848ab9e68a2SToomas Soome             NEEDBITS(3);
849ab9e68a2SToomas Soome             state->last = BITS(1);
850ab9e68a2SToomas Soome             DROPBITS(1);
851ab9e68a2SToomas Soome             switch (BITS(2)) {
852ab9e68a2SToomas Soome             case 0:                             /* stored block */
853ab9e68a2SToomas Soome                 Tracev((stderr, "inflate:     stored block%s\n",
854ab9e68a2SToomas Soome                         state->last ? " (last)" : ""));
855ab9e68a2SToomas Soome                 state->mode = STORED;
856ab9e68a2SToomas Soome                 break;
857ab9e68a2SToomas Soome             case 1:                             /* fixed block */
858ab9e68a2SToomas Soome                 fixedtables(state);
859ab9e68a2SToomas Soome                 Tracev((stderr, "inflate:     fixed codes block%s\n",
860ab9e68a2SToomas Soome                         state->last ? " (last)" : ""));
861ab9e68a2SToomas Soome                 state->mode = LEN_;             /* decode codes */
862ab9e68a2SToomas Soome                 if (flush == Z_TREES) {
863ab9e68a2SToomas Soome                     DROPBITS(2);
864ab9e68a2SToomas Soome                     goto inf_leave;
865ab9e68a2SToomas Soome                 }
866ab9e68a2SToomas Soome                 break;
867ab9e68a2SToomas Soome             case 2:                             /* dynamic block */
868ab9e68a2SToomas Soome                 Tracev((stderr, "inflate:     dynamic codes block%s\n",
869ab9e68a2SToomas Soome                         state->last ? " (last)" : ""));
870ab9e68a2SToomas Soome                 state->mode = TABLE;
871ab9e68a2SToomas Soome                 break;
872ab9e68a2SToomas Soome             case 3:
873ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid block type";
874ab9e68a2SToomas Soome                 state->mode = BAD;
875ab9e68a2SToomas Soome             }
876ab9e68a2SToomas Soome             DROPBITS(2);
877ab9e68a2SToomas Soome             break;
878ab9e68a2SToomas Soome         case STORED:
879ab9e68a2SToomas Soome             BYTEBITS();                         /* go to byte boundary */
880ab9e68a2SToomas Soome             NEEDBITS(32);
881ab9e68a2SToomas Soome             if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
882ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid stored block lengths";
883ab9e68a2SToomas Soome                 state->mode = BAD;
884ab9e68a2SToomas Soome                 break;
885ab9e68a2SToomas Soome             }
886ab9e68a2SToomas Soome             state->length = (unsigned)hold & 0xffff;
887ab9e68a2SToomas Soome             Tracev((stderr, "inflate:       stored length %u\n",
888ab9e68a2SToomas Soome                     state->length));
889ab9e68a2SToomas Soome             INITBITS();
890ab9e68a2SToomas Soome             state->mode = COPY_;
891ab9e68a2SToomas Soome             if (flush == Z_TREES) goto inf_leave;
892ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
893ab9e68a2SToomas Soome         case COPY_:
894ab9e68a2SToomas Soome             state->mode = COPY;
895ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
896ab9e68a2SToomas Soome         case COPY:
897ab9e68a2SToomas Soome             copy = state->length;
898ab9e68a2SToomas Soome             if (copy) {
899ab9e68a2SToomas Soome                 if (copy > have) copy = have;
900ab9e68a2SToomas Soome                 if (copy > left) copy = left;
901ab9e68a2SToomas Soome                 if (copy == 0) goto inf_leave;
902ab9e68a2SToomas Soome                 zmemcpy(put, next, copy);
903ab9e68a2SToomas Soome                 have -= copy;
904ab9e68a2SToomas Soome                 next += copy;
905ab9e68a2SToomas Soome                 left -= copy;
906ab9e68a2SToomas Soome                 put += copy;
907ab9e68a2SToomas Soome                 state->length -= copy;
908ab9e68a2SToomas Soome                 break;
909ab9e68a2SToomas Soome             }
910ab9e68a2SToomas Soome             Tracev((stderr, "inflate:       stored end\n"));
911ab9e68a2SToomas Soome             state->mode = TYPE;
912ab9e68a2SToomas Soome             break;
913ab9e68a2SToomas Soome         case TABLE:
914ab9e68a2SToomas Soome             NEEDBITS(14);
915ab9e68a2SToomas Soome             state->nlen = BITS(5) + 257;
916ab9e68a2SToomas Soome             DROPBITS(5);
917ab9e68a2SToomas Soome             state->ndist = BITS(5) + 1;
918ab9e68a2SToomas Soome             DROPBITS(5);
919ab9e68a2SToomas Soome             state->ncode = BITS(4) + 4;
920ab9e68a2SToomas Soome             DROPBITS(4);
921ab9e68a2SToomas Soome #ifndef PKZIP_BUG_WORKAROUND
922ab9e68a2SToomas Soome             if (state->nlen > 286 || state->ndist > 30) {
923ab9e68a2SToomas Soome                 strm->msg = (char *)"too many length or distance symbols";
924ab9e68a2SToomas Soome                 state->mode = BAD;
925ab9e68a2SToomas Soome                 break;
926ab9e68a2SToomas Soome             }
927ab9e68a2SToomas Soome #endif
928ab9e68a2SToomas Soome             Tracev((stderr, "inflate:       table sizes ok\n"));
929ab9e68a2SToomas Soome             state->have = 0;
930ab9e68a2SToomas Soome             state->mode = LENLENS;
931*64c3d159SToomas Soome                 /* fallthrough */
932ab9e68a2SToomas Soome         case LENLENS:
933ab9e68a2SToomas Soome             while (state->have < state->ncode) {
934ab9e68a2SToomas Soome                 NEEDBITS(3);
935ab9e68a2SToomas Soome                 state->lens[order[state->have++]] = (unsigned short)BITS(3);
936ab9e68a2SToomas Soome                 DROPBITS(3);
937ab9e68a2SToomas Soome             }
938ab9e68a2SToomas Soome             while (state->have < 19)
939ab9e68a2SToomas Soome                 state->lens[order[state->have++]] = 0;
940ab9e68a2SToomas Soome             state->next = state->codes;
941ab9e68a2SToomas Soome             state->lencode = (const code FAR *)(state->next);
942ab9e68a2SToomas Soome             state->lenbits = 7;
943ab9e68a2SToomas Soome             ret = inflate_table(CODES, state->lens, 19, &(state->next),
944ab9e68a2SToomas Soome                                 &(state->lenbits), state->work);
945ab9e68a2SToomas Soome             if (ret) {
946ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid code lengths set";
947ab9e68a2SToomas Soome                 state->mode = BAD;
948ab9e68a2SToomas Soome                 break;
949ab9e68a2SToomas Soome             }
950ab9e68a2SToomas Soome             Tracev((stderr, "inflate:       code lengths ok\n"));
951ab9e68a2SToomas Soome             state->have = 0;
952ab9e68a2SToomas Soome             state->mode = CODELENS;
953*64c3d159SToomas Soome                 /* fallthrough */
954ab9e68a2SToomas Soome         case CODELENS:
955ab9e68a2SToomas Soome             while (state->have < state->nlen + state->ndist) {
956ab9e68a2SToomas Soome                 for (;;) {
957ab9e68a2SToomas Soome                     here = state->lencode[BITS(state->lenbits)];
958ab9e68a2SToomas Soome                     if ((unsigned)(here.bits) <= bits) break;
959ab9e68a2SToomas Soome                     PULLBYTE();
960ab9e68a2SToomas Soome                 }
961ab9e68a2SToomas Soome                 if (here.val < 16) {
962ab9e68a2SToomas Soome                     DROPBITS(here.bits);
963ab9e68a2SToomas Soome                     state->lens[state->have++] = here.val;
964ab9e68a2SToomas Soome                 }
965ab9e68a2SToomas Soome                 else {
966ab9e68a2SToomas Soome                     if (here.val == 16) {
967ab9e68a2SToomas Soome                         NEEDBITS(here.bits + 2);
968ab9e68a2SToomas Soome                         DROPBITS(here.bits);
969ab9e68a2SToomas Soome                         if (state->have == 0) {
970ab9e68a2SToomas Soome                             strm->msg = (char *)"invalid bit length repeat";
971ab9e68a2SToomas Soome                             state->mode = BAD;
972ab9e68a2SToomas Soome                             break;
973ab9e68a2SToomas Soome                         }
974ab9e68a2SToomas Soome                         len = state->lens[state->have - 1];
975ab9e68a2SToomas Soome                         copy = 3 + BITS(2);
976ab9e68a2SToomas Soome                         DROPBITS(2);
977ab9e68a2SToomas Soome                     }
978ab9e68a2SToomas Soome                     else if (here.val == 17) {
979ab9e68a2SToomas Soome                         NEEDBITS(here.bits + 3);
980ab9e68a2SToomas Soome                         DROPBITS(here.bits);
981ab9e68a2SToomas Soome                         len = 0;
982ab9e68a2SToomas Soome                         copy = 3 + BITS(3);
983ab9e68a2SToomas Soome                         DROPBITS(3);
984ab9e68a2SToomas Soome                     }
985ab9e68a2SToomas Soome                     else {
986ab9e68a2SToomas Soome                         NEEDBITS(here.bits + 7);
987ab9e68a2SToomas Soome                         DROPBITS(here.bits);
988ab9e68a2SToomas Soome                         len = 0;
989ab9e68a2SToomas Soome                         copy = 11 + BITS(7);
990ab9e68a2SToomas Soome                         DROPBITS(7);
991ab9e68a2SToomas Soome                     }
992ab9e68a2SToomas Soome                     if (state->have + copy > state->nlen + state->ndist) {
993ab9e68a2SToomas Soome                         strm->msg = (char *)"invalid bit length repeat";
994ab9e68a2SToomas Soome                         state->mode = BAD;
995ab9e68a2SToomas Soome                         break;
996ab9e68a2SToomas Soome                     }
997ab9e68a2SToomas Soome                     while (copy--)
998ab9e68a2SToomas Soome                         state->lens[state->have++] = (unsigned short)len;
999ab9e68a2SToomas Soome                 }
1000ab9e68a2SToomas Soome             }
1001ab9e68a2SToomas Soome 
1002ab9e68a2SToomas Soome             /* handle error breaks in while */
1003ab9e68a2SToomas Soome             if (state->mode == BAD) break;
1004ab9e68a2SToomas Soome 
1005ab9e68a2SToomas Soome             /* check for end-of-block code (better have one) */
1006ab9e68a2SToomas Soome             if (state->lens[256] == 0) {
1007ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid code -- missing end-of-block";
1008ab9e68a2SToomas Soome                 state->mode = BAD;
1009ab9e68a2SToomas Soome                 break;
1010ab9e68a2SToomas Soome             }
1011ab9e68a2SToomas Soome 
1012ab9e68a2SToomas Soome             /* build code tables -- note: do not change the lenbits or distbits
1013ab9e68a2SToomas Soome                values here (9 and 6) without reading the comments in inftrees.h
1014ab9e68a2SToomas Soome                concerning the ENOUGH constants, which depend on those values */
1015ab9e68a2SToomas Soome             state->next = state->codes;
1016ab9e68a2SToomas Soome             state->lencode = (const code FAR *)(state->next);
1017ab9e68a2SToomas Soome             state->lenbits = 9;
1018ab9e68a2SToomas Soome             ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
1019ab9e68a2SToomas Soome                                 &(state->lenbits), state->work);
1020ab9e68a2SToomas Soome             if (ret) {
1021ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid literal/lengths set";
1022ab9e68a2SToomas Soome                 state->mode = BAD;
1023ab9e68a2SToomas Soome                 break;
1024ab9e68a2SToomas Soome             }
1025ab9e68a2SToomas Soome             state->distcode = (const code FAR *)(state->next);
1026ab9e68a2SToomas Soome             state->distbits = 6;
1027ab9e68a2SToomas Soome             ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
1028ab9e68a2SToomas Soome                             &(state->next), &(state->distbits), state->work);
1029ab9e68a2SToomas Soome             if (ret) {
1030ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid distances set";
1031ab9e68a2SToomas Soome                 state->mode = BAD;
1032ab9e68a2SToomas Soome                 break;
1033ab9e68a2SToomas Soome             }
1034ab9e68a2SToomas Soome             Tracev((stderr, "inflate:       codes ok\n"));
1035ab9e68a2SToomas Soome             state->mode = LEN_;
1036ab9e68a2SToomas Soome             if (flush == Z_TREES) goto inf_leave;
1037ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
1038ab9e68a2SToomas Soome         case LEN_:
1039ab9e68a2SToomas Soome             state->mode = LEN;
1040ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
1041ab9e68a2SToomas Soome         case LEN:
1042ab9e68a2SToomas Soome             if (have >= 6 && left >= 258) {
1043ab9e68a2SToomas Soome                 RESTORE();
1044ab9e68a2SToomas Soome                 inflate_fast(strm, out);
1045ab9e68a2SToomas Soome                 LOAD();
1046ab9e68a2SToomas Soome                 if (state->mode == TYPE)
1047ab9e68a2SToomas Soome                     state->back = -1;
1048ab9e68a2SToomas Soome                 break;
1049ab9e68a2SToomas Soome             }
1050ab9e68a2SToomas Soome             state->back = 0;
1051ab9e68a2SToomas Soome             for (;;) {
1052ab9e68a2SToomas Soome                 here = state->lencode[BITS(state->lenbits)];
1053ab9e68a2SToomas Soome                 if ((unsigned)(here.bits) <= bits) break;
1054ab9e68a2SToomas Soome                 PULLBYTE();
1055ab9e68a2SToomas Soome             }
1056ab9e68a2SToomas Soome             if (here.op && (here.op & 0xf0) == 0) {
1057ab9e68a2SToomas Soome                 last = here;
1058ab9e68a2SToomas Soome                 for (;;) {
1059ab9e68a2SToomas Soome                     here = state->lencode[last.val +
1060ab9e68a2SToomas Soome                             (BITS(last.bits + last.op) >> last.bits)];
1061ab9e68a2SToomas Soome                     if ((unsigned)(last.bits + here.bits) <= bits) break;
1062ab9e68a2SToomas Soome                     PULLBYTE();
1063ab9e68a2SToomas Soome                 }
1064ab9e68a2SToomas Soome                 DROPBITS(last.bits);
1065ab9e68a2SToomas Soome                 state->back += last.bits;
1066ab9e68a2SToomas Soome             }
1067ab9e68a2SToomas Soome             DROPBITS(here.bits);
1068ab9e68a2SToomas Soome             state->back += here.bits;
1069ab9e68a2SToomas Soome             state->length = (unsigned)here.val;
1070ab9e68a2SToomas Soome             if ((int)(here.op) == 0) {
1071ab9e68a2SToomas Soome                 Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
1072ab9e68a2SToomas Soome                         "inflate:         literal '%c'\n" :
1073ab9e68a2SToomas Soome                         "inflate:         literal 0x%02x\n", here.val));
1074ab9e68a2SToomas Soome                 state->mode = LIT;
1075ab9e68a2SToomas Soome                 break;
1076ab9e68a2SToomas Soome             }
1077ab9e68a2SToomas Soome             if (here.op & 32) {
1078ab9e68a2SToomas Soome                 Tracevv((stderr, "inflate:         end of block\n"));
1079ab9e68a2SToomas Soome                 state->back = -1;
1080ab9e68a2SToomas Soome                 state->mode = TYPE;
1081ab9e68a2SToomas Soome                 break;
1082ab9e68a2SToomas Soome             }
1083ab9e68a2SToomas Soome             if (here.op & 64) {
1084ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid literal/length code";
1085ab9e68a2SToomas Soome                 state->mode = BAD;
1086ab9e68a2SToomas Soome                 break;
1087ab9e68a2SToomas Soome             }
1088ab9e68a2SToomas Soome             state->extra = (unsigned)(here.op) & 15;
1089ab9e68a2SToomas Soome             state->mode = LENEXT;
1090ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
1091ab9e68a2SToomas Soome         case LENEXT:
1092ab9e68a2SToomas Soome             if (state->extra) {
1093ab9e68a2SToomas Soome                 NEEDBITS(state->extra);
1094ab9e68a2SToomas Soome                 state->length += BITS(state->extra);
1095ab9e68a2SToomas Soome                 DROPBITS(state->extra);
1096ab9e68a2SToomas Soome                 state->back += state->extra;
1097ab9e68a2SToomas Soome             }
1098ab9e68a2SToomas Soome             Tracevv((stderr, "inflate:         length %u\n", state->length));
1099ab9e68a2SToomas Soome             state->was = state->length;
1100ab9e68a2SToomas Soome             state->mode = DIST;
1101ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
1102ab9e68a2SToomas Soome         case DIST:
1103ab9e68a2SToomas Soome             for (;;) {
1104ab9e68a2SToomas Soome                 here = state->distcode[BITS(state->distbits)];
1105ab9e68a2SToomas Soome                 if ((unsigned)(here.bits) <= bits) break;
1106ab9e68a2SToomas Soome                 PULLBYTE();
1107ab9e68a2SToomas Soome             }
1108ab9e68a2SToomas Soome             if ((here.op & 0xf0) == 0) {
1109ab9e68a2SToomas Soome                 last = here;
1110ab9e68a2SToomas Soome                 for (;;) {
1111ab9e68a2SToomas Soome                     here = state->distcode[last.val +
1112ab9e68a2SToomas Soome                             (BITS(last.bits + last.op) >> last.bits)];
1113ab9e68a2SToomas Soome                     if ((unsigned)(last.bits + here.bits) <= bits) break;
1114ab9e68a2SToomas Soome                     PULLBYTE();
1115ab9e68a2SToomas Soome                 }
1116ab9e68a2SToomas Soome                 DROPBITS(last.bits);
1117ab9e68a2SToomas Soome                 state->back += last.bits;
1118ab9e68a2SToomas Soome             }
1119ab9e68a2SToomas Soome             DROPBITS(here.bits);
1120ab9e68a2SToomas Soome             state->back += here.bits;
1121ab9e68a2SToomas Soome             if (here.op & 64) {
1122ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid distance code";
1123ab9e68a2SToomas Soome                 state->mode = BAD;
1124ab9e68a2SToomas Soome                 break;
1125ab9e68a2SToomas Soome             }
1126ab9e68a2SToomas Soome             state->offset = (unsigned)here.val;
1127ab9e68a2SToomas Soome             state->extra = (unsigned)(here.op) & 15;
1128ab9e68a2SToomas Soome             state->mode = DISTEXT;
1129ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
1130ab9e68a2SToomas Soome         case DISTEXT:
1131ab9e68a2SToomas Soome             if (state->extra) {
1132ab9e68a2SToomas Soome                 NEEDBITS(state->extra);
1133ab9e68a2SToomas Soome                 state->offset += BITS(state->extra);
1134ab9e68a2SToomas Soome                 DROPBITS(state->extra);
1135ab9e68a2SToomas Soome                 state->back += state->extra;
1136ab9e68a2SToomas Soome             }
1137ab9e68a2SToomas Soome #ifdef INFLATE_STRICT
1138ab9e68a2SToomas Soome             if (state->offset > state->dmax) {
1139ab9e68a2SToomas Soome                 strm->msg = (char *)"invalid distance too far back";
1140ab9e68a2SToomas Soome                 state->mode = BAD;
1141ab9e68a2SToomas Soome                 break;
1142ab9e68a2SToomas Soome             }
1143ab9e68a2SToomas Soome #endif
1144ab9e68a2SToomas Soome             Tracevv((stderr, "inflate:         distance %u\n", state->offset));
1145ab9e68a2SToomas Soome             state->mode = MATCH;
1146ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
1147ab9e68a2SToomas Soome         case MATCH:
1148ab9e68a2SToomas Soome             if (left == 0) goto inf_leave;
1149ab9e68a2SToomas Soome             copy = out - left;
1150ab9e68a2SToomas Soome             if (state->offset > copy) {         /* copy from window */
1151ab9e68a2SToomas Soome                 copy = state->offset - copy;
1152ab9e68a2SToomas Soome                 if (copy > state->whave) {
1153ab9e68a2SToomas Soome                     if (state->sane) {
1154ab9e68a2SToomas Soome                         strm->msg = (char *)"invalid distance too far back";
1155ab9e68a2SToomas Soome                         state->mode = BAD;
1156ab9e68a2SToomas Soome                         break;
1157ab9e68a2SToomas Soome                     }
1158ab9e68a2SToomas Soome #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
1159ab9e68a2SToomas Soome                     Trace((stderr, "inflate.c too far\n"));
1160ab9e68a2SToomas Soome                     copy -= state->whave;
1161ab9e68a2SToomas Soome                     if (copy > state->length) copy = state->length;
1162ab9e68a2SToomas Soome                     if (copy > left) copy = left;
1163ab9e68a2SToomas Soome                     left -= copy;
1164ab9e68a2SToomas Soome                     state->length -= copy;
1165ab9e68a2SToomas Soome                     do {
1166ab9e68a2SToomas Soome                         *put++ = 0;
1167ab9e68a2SToomas Soome                     } while (--copy);
1168ab9e68a2SToomas Soome                     if (state->length == 0) state->mode = LEN;
1169ab9e68a2SToomas Soome                     break;
1170ab9e68a2SToomas Soome #endif
1171ab9e68a2SToomas Soome                 }
1172ab9e68a2SToomas Soome                 if (copy > state->wnext) {
1173ab9e68a2SToomas Soome                     copy -= state->wnext;
1174ab9e68a2SToomas Soome                     from = state->window + (state->wsize - copy);
1175ab9e68a2SToomas Soome                 }
1176ab9e68a2SToomas Soome                 else
1177ab9e68a2SToomas Soome                     from = state->window + (state->wnext - copy);
1178ab9e68a2SToomas Soome                 if (copy > state->length) copy = state->length;
1179ab9e68a2SToomas Soome             }
1180ab9e68a2SToomas Soome             else {                              /* copy from output */
1181ab9e68a2SToomas Soome                 from = put - state->offset;
1182ab9e68a2SToomas Soome                 copy = state->length;
1183ab9e68a2SToomas Soome             }
1184ab9e68a2SToomas Soome             if (copy > left) copy = left;
1185ab9e68a2SToomas Soome             left -= copy;
1186ab9e68a2SToomas Soome             state->length -= copy;
1187ab9e68a2SToomas Soome             do {
1188ab9e68a2SToomas Soome                 *put++ = *from++;
1189ab9e68a2SToomas Soome             } while (--copy);
1190ab9e68a2SToomas Soome             if (state->length == 0) state->mode = LEN;
1191ab9e68a2SToomas Soome             break;
1192ab9e68a2SToomas Soome         case LIT:
1193ab9e68a2SToomas Soome             if (left == 0) goto inf_leave;
1194ab9e68a2SToomas Soome             *put++ = (unsigned char)(state->length);
1195ab9e68a2SToomas Soome             left--;
1196ab9e68a2SToomas Soome             state->mode = LEN;
1197ab9e68a2SToomas Soome             break;
1198ab9e68a2SToomas Soome         case CHECK:
1199ab9e68a2SToomas Soome             if (state->wrap) {
1200ab9e68a2SToomas Soome                 NEEDBITS(32);
1201ab9e68a2SToomas Soome                 out -= left;
1202ab9e68a2SToomas Soome                 strm->total_out += out;
1203ab9e68a2SToomas Soome                 state->total += out;
1204ab9e68a2SToomas Soome                 if ((state->wrap & 4) && out)
1205ab9e68a2SToomas Soome                     strm->adler = state->check =
1206*64c3d159SToomas Soome                         UPDATE_CHECK(state->check, put - out, out);
1207ab9e68a2SToomas Soome                 out = left;
1208ab9e68a2SToomas Soome                 if ((state->wrap & 4) && (
1209ab9e68a2SToomas Soome #ifdef GUNZIP
1210ab9e68a2SToomas Soome                      state->flags ? hold :
1211ab9e68a2SToomas Soome #endif
1212ab9e68a2SToomas Soome                      ZSWAP32(hold)) != state->check) {
1213ab9e68a2SToomas Soome                     strm->msg = (char *)"incorrect data check";
1214ab9e68a2SToomas Soome                     state->mode = BAD;
1215ab9e68a2SToomas Soome                     break;
1216ab9e68a2SToomas Soome                 }
1217ab9e68a2SToomas Soome                 INITBITS();
1218ab9e68a2SToomas Soome                 Tracev((stderr, "inflate:   check matches trailer\n"));
1219ab9e68a2SToomas Soome             }
1220ab9e68a2SToomas Soome #ifdef GUNZIP
1221ab9e68a2SToomas Soome             state->mode = LENGTH;
1222ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
1223ab9e68a2SToomas Soome         case LENGTH:
1224ab9e68a2SToomas Soome             if (state->wrap && state->flags) {
1225ab9e68a2SToomas Soome                 NEEDBITS(32);
1226*64c3d159SToomas Soome                 if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
1227ab9e68a2SToomas Soome                     strm->msg = (char *)"incorrect length check";
1228ab9e68a2SToomas Soome                     state->mode = BAD;
1229ab9e68a2SToomas Soome                     break;
1230ab9e68a2SToomas Soome                 }
1231ab9e68a2SToomas Soome                 INITBITS();
1232ab9e68a2SToomas Soome                 Tracev((stderr, "inflate:   length matches trailer\n"));
1233ab9e68a2SToomas Soome             }
1234ab9e68a2SToomas Soome #endif
1235ab9e68a2SToomas Soome             state->mode = DONE;
1236ab9e68a2SToomas Soome 	    /* FALLTHROUGH */
1237ab9e68a2SToomas Soome         case DONE:
1238ab9e68a2SToomas Soome             ret = Z_STREAM_END;
1239ab9e68a2SToomas Soome             goto inf_leave;
1240ab9e68a2SToomas Soome         case BAD:
1241ab9e68a2SToomas Soome             ret = Z_DATA_ERROR;
1242ab9e68a2SToomas Soome             goto inf_leave;
1243ab9e68a2SToomas Soome         case MEM:
1244ab9e68a2SToomas Soome             return Z_MEM_ERROR;
1245ab9e68a2SToomas Soome         case SYNC:
1246*64c3d159SToomas Soome                 /* fallthrough */
1247ab9e68a2SToomas Soome         default:
1248ab9e68a2SToomas Soome             return Z_STREAM_ERROR;
1249ab9e68a2SToomas Soome         }
1250ab9e68a2SToomas Soome 
1251ab9e68a2SToomas Soome     /*
1252ab9e68a2SToomas Soome        Return from inflate(), updating the total counts and the check value.
1253ab9e68a2SToomas Soome        If there was no progress during the inflate() call, return a buffer
1254ab9e68a2SToomas Soome        error.  Call updatewindow() to create and/or update the window state.
1255ab9e68a2SToomas Soome        Note: a memory error from inflate() is non-recoverable.
1256ab9e68a2SToomas Soome      */
1257ab9e68a2SToomas Soome   inf_leave:
1258ab9e68a2SToomas Soome     RESTORE();
1259ab9e68a2SToomas Soome     if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
1260ab9e68a2SToomas Soome             (state->mode < CHECK || flush != Z_FINISH)))
1261ab9e68a2SToomas Soome         if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
1262ab9e68a2SToomas Soome             state->mode = MEM;
1263ab9e68a2SToomas Soome             return Z_MEM_ERROR;
1264ab9e68a2SToomas Soome         }
1265ab9e68a2SToomas Soome     in -= strm->avail_in;
1266ab9e68a2SToomas Soome     out -= strm->avail_out;
1267ab9e68a2SToomas Soome     strm->total_in += in;
1268ab9e68a2SToomas Soome     strm->total_out += out;
1269ab9e68a2SToomas Soome     state->total += out;
1270ab9e68a2SToomas Soome     if ((state->wrap & 4) && out)
1271ab9e68a2SToomas Soome         strm->adler = state->check =
1272*64c3d159SToomas Soome             UPDATE_CHECK(state->check, strm->next_out - out, out);
1273ab9e68a2SToomas Soome     strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
1274ab9e68a2SToomas Soome                       (state->mode == TYPE ? 128 : 0) +
1275ab9e68a2SToomas Soome                       (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
1276ab9e68a2SToomas Soome     if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
1277ab9e68a2SToomas Soome         ret = Z_BUF_ERROR;
1278ab9e68a2SToomas Soome     return ret;
1279ab9e68a2SToomas Soome }
1280ab9e68a2SToomas Soome 
1281ab9e68a2SToomas Soome int ZEXPORT inflateEnd(z_streamp strm)
1282ab9e68a2SToomas Soome {
1283ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1284ab9e68a2SToomas Soome     if (inflateStateCheck(strm))
1285ab9e68a2SToomas Soome         return Z_STREAM_ERROR;
1286ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1287ab9e68a2SToomas Soome     if (state->window != Z_NULL) ZFREE(strm, state->window);
1288ab9e68a2SToomas Soome     ZFREE(strm, strm->state);
1289ab9e68a2SToomas Soome     strm->state = Z_NULL;
1290ab9e68a2SToomas Soome     Tracev((stderr, "inflate: end\n"));
1291ab9e68a2SToomas Soome     return Z_OK;
1292ab9e68a2SToomas Soome }
1293ab9e68a2SToomas Soome 
1294ab9e68a2SToomas Soome int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary,
1295ab9e68a2SToomas Soome     uInt *dictLength)
1296ab9e68a2SToomas Soome {
1297ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1298ab9e68a2SToomas Soome 
1299ab9e68a2SToomas Soome     /* check state */
1300ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
1301ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1302ab9e68a2SToomas Soome 
1303ab9e68a2SToomas Soome     /* copy dictionary */
1304ab9e68a2SToomas Soome     if (state->whave && dictionary != Z_NULL) {
1305ab9e68a2SToomas Soome         zmemcpy(dictionary, state->window + state->wnext,
1306ab9e68a2SToomas Soome                 state->whave - state->wnext);
1307ab9e68a2SToomas Soome         zmemcpy(dictionary + state->whave - state->wnext,
1308ab9e68a2SToomas Soome                 state->window, state->wnext);
1309ab9e68a2SToomas Soome     }
1310ab9e68a2SToomas Soome     if (dictLength != Z_NULL)
1311ab9e68a2SToomas Soome         *dictLength = state->whave;
1312ab9e68a2SToomas Soome     return Z_OK;
1313ab9e68a2SToomas Soome }
1314ab9e68a2SToomas Soome 
1315ab9e68a2SToomas Soome int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary,
1316ab9e68a2SToomas Soome     uInt dictLength)
1317ab9e68a2SToomas Soome {
1318ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1319ab9e68a2SToomas Soome     unsigned long dictid;
1320ab9e68a2SToomas Soome     int ret;
1321ab9e68a2SToomas Soome 
1322ab9e68a2SToomas Soome     /* check state */
1323ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
1324ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1325ab9e68a2SToomas Soome     if (state->wrap != 0 && state->mode != DICT)
1326ab9e68a2SToomas Soome         return Z_STREAM_ERROR;
1327ab9e68a2SToomas Soome 
1328ab9e68a2SToomas Soome     /* check for correct dictionary identifier */
1329ab9e68a2SToomas Soome     if (state->mode == DICT) {
1330ab9e68a2SToomas Soome         dictid = adler32(0L, Z_NULL, 0);
1331ab9e68a2SToomas Soome         dictid = adler32(dictid, dictionary, dictLength);
1332ab9e68a2SToomas Soome         if (dictid != state->check)
1333ab9e68a2SToomas Soome             return Z_DATA_ERROR;
1334ab9e68a2SToomas Soome     }
1335ab9e68a2SToomas Soome 
1336ab9e68a2SToomas Soome     /* copy dictionary to window using updatewindow(), which will amend the
1337ab9e68a2SToomas Soome        existing dictionary if appropriate */
1338ab9e68a2SToomas Soome     ret = updatewindow(strm, dictionary + dictLength, dictLength);
1339ab9e68a2SToomas Soome     if (ret) {
1340ab9e68a2SToomas Soome         state->mode = MEM;
1341ab9e68a2SToomas Soome         return Z_MEM_ERROR;
1342ab9e68a2SToomas Soome     }
1343ab9e68a2SToomas Soome     state->havedict = 1;
1344ab9e68a2SToomas Soome     Tracev((stderr, "inflate:   dictionary set\n"));
1345ab9e68a2SToomas Soome     return Z_OK;
1346ab9e68a2SToomas Soome }
1347ab9e68a2SToomas Soome 
1348ab9e68a2SToomas Soome int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head)
1349ab9e68a2SToomas Soome {
1350ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1351ab9e68a2SToomas Soome 
1352ab9e68a2SToomas Soome     /* check state */
1353ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
1354ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1355ab9e68a2SToomas Soome     if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
1356ab9e68a2SToomas Soome 
1357ab9e68a2SToomas Soome     /* save header structure */
1358ab9e68a2SToomas Soome     state->head = head;
1359ab9e68a2SToomas Soome     head->done = 0;
1360ab9e68a2SToomas Soome     return Z_OK;
1361ab9e68a2SToomas Soome }
1362ab9e68a2SToomas Soome 
1363ab9e68a2SToomas Soome /*
1364ab9e68a2SToomas Soome    Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
1365ab9e68a2SToomas Soome    or when out of input.  When called, *have is the number of pattern bytes
1366ab9e68a2SToomas Soome    found in order so far, in 0..3.  On return *have is updated to the new
1367ab9e68a2SToomas Soome    state.  If on return *have equals four, then the pattern was found and the
1368ab9e68a2SToomas Soome    return value is how many bytes were read including the last byte of the
1369ab9e68a2SToomas Soome    pattern.  If *have is less than four, then the pattern has not been found
1370ab9e68a2SToomas Soome    yet and the return value is len.  In the latter case, syncsearch() can be
1371ab9e68a2SToomas Soome    called again with more data and the *have state.  *have is initialized to
1372ab9e68a2SToomas Soome    zero for the first call.
1373ab9e68a2SToomas Soome  */
1374ab9e68a2SToomas Soome local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf,
1375ab9e68a2SToomas Soome     unsigned len)
1376ab9e68a2SToomas Soome {
1377ab9e68a2SToomas Soome     unsigned got;
1378ab9e68a2SToomas Soome     unsigned next;
1379ab9e68a2SToomas Soome 
1380ab9e68a2SToomas Soome     got = *have;
1381ab9e68a2SToomas Soome     next = 0;
1382ab9e68a2SToomas Soome     while (next < len && got < 4) {
1383ab9e68a2SToomas Soome         if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
1384ab9e68a2SToomas Soome             got++;
1385ab9e68a2SToomas Soome         else if (buf[next])
1386ab9e68a2SToomas Soome             got = 0;
1387ab9e68a2SToomas Soome         else
1388ab9e68a2SToomas Soome             got = 4 - got;
1389ab9e68a2SToomas Soome         next++;
1390ab9e68a2SToomas Soome     }
1391ab9e68a2SToomas Soome     *have = got;
1392ab9e68a2SToomas Soome     return next;
1393ab9e68a2SToomas Soome }
1394ab9e68a2SToomas Soome 
1395ab9e68a2SToomas Soome int ZEXPORT inflateSync(z_streamp strm)
1396ab9e68a2SToomas Soome {
1397ab9e68a2SToomas Soome     unsigned len;               /* number of bytes to look at or looked at */
1398*64c3d159SToomas Soome     int flags;                  /* temporary to save header status */
1399ab9e68a2SToomas Soome     unsigned long in, out;      /* temporary to save total_in and total_out */
1400ab9e68a2SToomas Soome     unsigned char buf[4];       /* to restore bit buffer to byte string */
1401ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1402ab9e68a2SToomas Soome 
1403ab9e68a2SToomas Soome     /* check parameters */
1404ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
1405ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1406ab9e68a2SToomas Soome     if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
1407ab9e68a2SToomas Soome 
1408ab9e68a2SToomas Soome     /* if first time, start search in bit buffer */
1409ab9e68a2SToomas Soome     if (state->mode != SYNC) {
1410ab9e68a2SToomas Soome         state->mode = SYNC;
1411ab9e68a2SToomas Soome         state->hold <<= state->bits & 7;
1412ab9e68a2SToomas Soome         state->bits -= state->bits & 7;
1413ab9e68a2SToomas Soome         len = 0;
1414ab9e68a2SToomas Soome         while (state->bits >= 8) {
1415ab9e68a2SToomas Soome             buf[len++] = (unsigned char)(state->hold);
1416ab9e68a2SToomas Soome             state->hold >>= 8;
1417ab9e68a2SToomas Soome             state->bits -= 8;
1418ab9e68a2SToomas Soome         }
1419ab9e68a2SToomas Soome         state->have = 0;
1420ab9e68a2SToomas Soome         syncsearch(&(state->have), buf, len);
1421ab9e68a2SToomas Soome     }
1422ab9e68a2SToomas Soome 
1423ab9e68a2SToomas Soome     /* search available input */
1424ab9e68a2SToomas Soome     len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
1425ab9e68a2SToomas Soome     strm->avail_in -= len;
1426ab9e68a2SToomas Soome     strm->next_in += len;
1427ab9e68a2SToomas Soome     strm->total_in += len;
1428ab9e68a2SToomas Soome 
1429ab9e68a2SToomas Soome     /* return no joy or set up to restart inflate() on a new block */
1430ab9e68a2SToomas Soome     if (state->have != 4) return Z_DATA_ERROR;
1431*64c3d159SToomas Soome     if (state->flags == -1)
1432*64c3d159SToomas Soome         state->wrap = 0;    /* if no header yet, treat as raw */
1433*64c3d159SToomas Soome     else
1434*64c3d159SToomas Soome         state->wrap &= ~4;  /* no point in computing a check value now */
1435*64c3d159SToomas Soome     flags = state->flags;
1436ab9e68a2SToomas Soome     in = strm->total_in;  out = strm->total_out;
1437ab9e68a2SToomas Soome     inflateReset(strm);
1438ab9e68a2SToomas Soome     strm->total_in = in;  strm->total_out = out;
1439*64c3d159SToomas Soome     state->flags = flags;
1440ab9e68a2SToomas Soome     state->mode = TYPE;
1441ab9e68a2SToomas Soome     return Z_OK;
1442ab9e68a2SToomas Soome }
1443ab9e68a2SToomas Soome 
1444ab9e68a2SToomas Soome /*
1445ab9e68a2SToomas Soome    Returns true if inflate is currently at the end of a block generated by
1446ab9e68a2SToomas Soome    Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
1447ab9e68a2SToomas Soome    implementation to provide an additional safety check. PPP uses
1448ab9e68a2SToomas Soome    Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
1449ab9e68a2SToomas Soome    block. When decompressing, PPP checks that at the end of input packet,
1450ab9e68a2SToomas Soome    inflate is waiting for these length bytes.
1451ab9e68a2SToomas Soome  */
1452ab9e68a2SToomas Soome int ZEXPORT inflateSyncPoint(z_streamp strm)
1453ab9e68a2SToomas Soome {
1454ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1455ab9e68a2SToomas Soome 
1456ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
1457ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1458ab9e68a2SToomas Soome     return state->mode == STORED && state->bits == 0;
1459ab9e68a2SToomas Soome }
1460ab9e68a2SToomas Soome 
1461ab9e68a2SToomas Soome int ZEXPORT inflateCopy(z_streamp dest, z_streamp source)
1462ab9e68a2SToomas Soome {
1463ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1464ab9e68a2SToomas Soome     struct inflate_state FAR *copy;
1465ab9e68a2SToomas Soome     unsigned char FAR *window;
1466ab9e68a2SToomas Soome     unsigned wsize;
1467ab9e68a2SToomas Soome 
1468ab9e68a2SToomas Soome     /* check input */
1469ab9e68a2SToomas Soome     if (inflateStateCheck(source) || dest == Z_NULL)
1470ab9e68a2SToomas Soome         return Z_STREAM_ERROR;
1471ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)source->state;
1472ab9e68a2SToomas Soome 
1473ab9e68a2SToomas Soome     /* allocate space */
1474ab9e68a2SToomas Soome     copy = (struct inflate_state FAR *)
1475ab9e68a2SToomas Soome            ZALLOC(source, 1, sizeof(struct inflate_state));
1476ab9e68a2SToomas Soome     if (copy == Z_NULL) return Z_MEM_ERROR;
1477ab9e68a2SToomas Soome     window = Z_NULL;
1478ab9e68a2SToomas Soome     if (state->window != Z_NULL) {
1479ab9e68a2SToomas Soome         window = (unsigned char FAR *)
1480ab9e68a2SToomas Soome                  ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
1481ab9e68a2SToomas Soome         if (window == Z_NULL) {
1482ab9e68a2SToomas Soome             ZFREE(source, copy);
1483ab9e68a2SToomas Soome             return Z_MEM_ERROR;
1484ab9e68a2SToomas Soome         }
1485ab9e68a2SToomas Soome     }
1486ab9e68a2SToomas Soome 
1487ab9e68a2SToomas Soome     /* copy state */
1488ab9e68a2SToomas Soome     zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
1489ab9e68a2SToomas Soome     zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
1490ab9e68a2SToomas Soome     copy->strm = dest;
1491ab9e68a2SToomas Soome     if (state->lencode >= state->codes &&
1492ab9e68a2SToomas Soome         state->lencode <= state->codes + ENOUGH - 1) {
1493ab9e68a2SToomas Soome         copy->lencode = copy->codes + (state->lencode - state->codes);
1494ab9e68a2SToomas Soome         copy->distcode = copy->codes + (state->distcode - state->codes);
1495ab9e68a2SToomas Soome     }
1496ab9e68a2SToomas Soome     copy->next = copy->codes + (state->next - state->codes);
1497ab9e68a2SToomas Soome     if (window != Z_NULL) {
1498ab9e68a2SToomas Soome         wsize = 1U << state->wbits;
1499ab9e68a2SToomas Soome         zmemcpy(window, state->window, wsize);
1500ab9e68a2SToomas Soome     }
1501ab9e68a2SToomas Soome     copy->window = window;
1502ab9e68a2SToomas Soome     dest->state = (struct internal_state FAR *)copy;
1503ab9e68a2SToomas Soome     return Z_OK;
1504ab9e68a2SToomas Soome }
1505ab9e68a2SToomas Soome 
1506ab9e68a2SToomas Soome int ZEXPORT inflateUndermine(z_streamp strm, int subvert)
1507ab9e68a2SToomas Soome {
1508ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1509ab9e68a2SToomas Soome 
1510ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
1511ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1512ab9e68a2SToomas Soome #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
1513ab9e68a2SToomas Soome     state->sane = !subvert;
1514ab9e68a2SToomas Soome     return Z_OK;
1515ab9e68a2SToomas Soome #else
1516ab9e68a2SToomas Soome     (void)subvert;
1517ab9e68a2SToomas Soome     state->sane = 1;
1518ab9e68a2SToomas Soome     return Z_DATA_ERROR;
1519ab9e68a2SToomas Soome #endif
1520ab9e68a2SToomas Soome }
1521ab9e68a2SToomas Soome 
1522ab9e68a2SToomas Soome int ZEXPORT inflateValidate(z_streamp strm, int check)
1523ab9e68a2SToomas Soome {
1524ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1525ab9e68a2SToomas Soome 
1526ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
1527ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1528*64c3d159SToomas Soome     if (check && state->wrap)
1529ab9e68a2SToomas Soome         state->wrap |= 4;
1530ab9e68a2SToomas Soome     else
1531ab9e68a2SToomas Soome         state->wrap &= ~4;
1532ab9e68a2SToomas Soome     return Z_OK;
1533ab9e68a2SToomas Soome }
1534ab9e68a2SToomas Soome 
1535ab9e68a2SToomas Soome long ZEXPORT inflateMark(z_streamp strm)
1536ab9e68a2SToomas Soome {
1537ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1538ab9e68a2SToomas Soome 
1539ab9e68a2SToomas Soome     if (inflateStateCheck(strm))
1540ab9e68a2SToomas Soome         return -(1L << 16);
1541ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1542ab9e68a2SToomas Soome     return (long)(((unsigned long)((long)state->back)) << 16) +
1543ab9e68a2SToomas Soome         (state->mode == COPY ? state->length :
1544ab9e68a2SToomas Soome             (state->mode == MATCH ? state->was - state->length : 0));
1545ab9e68a2SToomas Soome }
1546ab9e68a2SToomas Soome 
1547ab9e68a2SToomas Soome unsigned long ZEXPORT inflateCodesUsed(z_streamp strm)
1548ab9e68a2SToomas Soome {
1549ab9e68a2SToomas Soome     struct inflate_state FAR *state;
1550ab9e68a2SToomas Soome     if (inflateStateCheck(strm)) return (unsigned long)-1;
1551ab9e68a2SToomas Soome     state = (struct inflate_state FAR *)strm->state;
1552ab9e68a2SToomas Soome     return (unsigned long)(state->next - state->codes);
1553ab9e68a2SToomas Soome }
1554