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