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