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