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