1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* infback.c -- inflate using a call-back interface
2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Copyright (C) 1995-2011 Mark Adler
3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * For conditions of distribution and use, see copyright notice in zlib.h
4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   This code is largely copied from inflate.c.  Normally either infback.o or
8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   inflate.o would be linked into an application--not both.  The interface
9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   with inffast.c is retained so that optimized assembler-coded versions of
10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   inflate_fast() can be used with either inflate.c or infback.c.
11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "zutil.h"
14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "inftrees.h"
15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "inflate.h"
16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "inffast.h"
17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* function prototypes */
19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerlocal void fixedtables OF((struct inflate_state FAR *state));
20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   strm provides memory allocation functions in zalloc and zfree, or
23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   Z_NULL to use the library memory allocation functions.
24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   windowBits is in the range 8..15, and window is a user-supplied
26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   window and output buffer that is 2**windowBits bytes.
27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerint ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerz_streamp strm;
30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerint windowBits;
31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerunsigned char FAR *window;
32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerconst char *version;
33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerint stream_size;
34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    struct inflate_state FAR *state;
36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        stream_size != (int)(sizeof(z_stream)))
39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return Z_VERSION_ERROR;
40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (strm == Z_NULL || window == Z_NULL ||
41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        windowBits < 8 || windowBits > 15)
42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return Z_STREAM_ERROR;
43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    strm->msg = Z_NULL;                 /* in case we return an error */
44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (strm->zalloc == (alloc_func)0) {
45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef Z_SOLO
46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return Z_STREAM_ERROR;
47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#else
48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        strm->zalloc = zcalloc;
49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        strm->opaque = (voidpf)0;
50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
52793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (strm->zfree == (free_func)0)
53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef Z_SOLO
54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return Z_STREAM_ERROR;
55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#else
56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    strm->zfree = zcfree;
57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    state = (struct inflate_state FAR *)ZALLOC(strm, 1,
59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                               sizeof(struct inflate_state));
60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (state == Z_NULL) return Z_MEM_ERROR;
61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Tracev((stderr, "inflate: allocated\n"));
62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    strm->state = (struct internal_state FAR *)state;
63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    state->dmax = 32768U;
64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    state->wbits = windowBits;
65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    state->wsize = 1U << windowBits;
66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    state->window = window;
67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    state->wnext = 0;
68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    state->whave = 0;
69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return Z_OK;
70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   Return state with length and distance decoding tables and index sizes set to
74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   If BUILDFIXED is defined, then instead this routine builds the tables the
76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   first time it's called, and returns those tables the first time and
77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   thereafter.  This reduces the size of the code by about 2K bytes, in
78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   exchange for a little execution time.  However, BUILDFIXED should not be
79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   used for threaded applications, since the rewriting of the tables and virgin
80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   may not be thread-safe.
81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerlocal void fixedtables(state)
83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstruct inflate_state FAR *state;
84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef BUILDFIXED
86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    static int virgin = 1;
87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    static code *lenfix, *distfix;
88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    static code fixed[544];
89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
90793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* build fixed huffman tables if first call (may not be thread safe) */
91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (virgin) {
92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        unsigned sym, bits;
93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        static code *next;
94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        /* literal/length table */
96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        sym = 0;
97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        while (sym < 144) state->lens[sym++] = 8;
98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        while (sym < 256) state->lens[sym++] = 9;
99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        while (sym < 280) state->lens[sym++] = 7;
100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        while (sym < 288) state->lens[sym++] = 8;
101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        next = fixed;
102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        lenfix = next;
103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        bits = 9;
104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        /* distance table */
107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        sym = 0;
108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        while (sym < 32) state->lens[sym++] = 5;
109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        distfix = next;
110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        bits = 5;
111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        /* do this just once */
114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        virgin = 0;
115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#else /* !BUILDFIXED */
117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#   include "inffixed.h"
118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif /* BUILDFIXED */
119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    state->lencode = lenfix;
120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    state->lenbits = 9;
121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    state->distcode = distfix;
122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    state->distbits = 5;
123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Macros for inflateBack(): */
126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Load returned state from inflate_fast() */
128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define LOAD() \
129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    do { \
130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        put = strm->next_out; \
131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        left = strm->avail_out; \
132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        next = strm->next_in; \
133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        have = strm->avail_in; \
134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        hold = state->hold; \
135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        bits = state->bits; \
136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } while (0)
137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Set state from registers for inflate_fast() */
139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define RESTORE() \
140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    do { \
141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        strm->next_out = put; \
142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        strm->avail_out = left; \
143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        strm->next_in = next; \
144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        strm->avail_in = have; \
145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        state->hold = hold; \
146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        state->bits = bits; \
147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } while (0)
148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Clear the input bit accumulator */
150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define INITBITS() \
151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    do { \
152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        hold = 0; \
153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        bits = 0; \
154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } while (0)
155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Assure that some input is available.  If input is requested, but denied,
157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   then return a Z_BUF_ERROR from inflateBack(). */
158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define PULL() \
159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    do { \
160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (have == 0) { \
161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            have = in(in_desc, &next); \
162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (have == 0) { \
163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                next = Z_NULL; \
164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                ret = Z_BUF_ERROR; \
165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                goto inf_leave; \
166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            } \
167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        } \
168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } while (0)
169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Get a byte of input into the bit accumulator, or return from inflateBack()
171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   with an error if there is no input available. */
172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define PULLBYTE() \
173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    do { \
174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        PULL(); \
175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        have--; \
176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        hold += (unsigned long)(*next++) << bits; \
177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        bits += 8; \
178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } while (0)
179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Assure that there are at least n bits in the bit accumulator.  If there is
181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   not enough available input to do that, then return from inflateBack() with
182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   an error. */
183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define NEEDBITS(n) \
184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    do { \
185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        while (bits < (unsigned)(n)) \
186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            PULLBYTE(); \
187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } while (0)
188793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Return the low n bits of the bit accumulator (n < 16) */
190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define BITS(n) \
191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ((unsigned)hold & ((1U << (n)) - 1))
192793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Remove n bits from the bit accumulator */
194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define DROPBITS(n) \
195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    do { \
196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        hold >>= (n); \
197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        bits -= (unsigned)(n); \
198793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } while (0)
199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Remove zero to seven bits as needed to go to a byte boundary */
201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define BYTEBITS() \
202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    do { \
203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        hold >>= bits & 7; \
204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        bits -= bits & 7; \
205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } while (0)
206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Assure that some output space is available, by writing out the window
208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   if it's full.  If the write fails, return from inflateBack() with a
209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   Z_BUF_ERROR. */
210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ROOM() \
211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    do { \
212793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (left == 0) { \
213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            put = state->window; \
214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            left = state->wsize; \
215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->whave = left; \
216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (out(out_desc, put, left)) { \
217793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                ret = Z_BUF_ERROR; \
218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                goto inf_leave; \
219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            } \
220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        } \
221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } while (0)
222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
224793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   strm provides the memory allocation functions and window buffer on input,
225793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   and provides information on the unused input on return.  For Z_DATA_ERROR
226793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   returns, strm will also provide an error message.
227793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
228793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   in() and out() are the call-back input and output functions.  When
229793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   inflateBack() needs more input, it calls in().  When inflateBack() has
230793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   filled the window with output, or when it completes with data in the
231793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   window, it calls out() to write out the data.  The application must not
232793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   change the provided input until in() is called again or inflateBack()
233793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   returns.  The application must not change the window/output buffer until
234793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   inflateBack() returns.
235793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
236793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   in() and out() are called with a descriptor parameter provided in the
237793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   inflateBack() call.  This parameter can be a structure that provides the
238793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   information required to do the read or write, as well as accumulated
239793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   information on the input and output such as totals and check values.
240793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
241793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   in() should return zero on failure.  out() should return non-zero on
242793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   failure.  If either in() or out() fails, than inflateBack() returns a
243793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
244793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   was in() or out() that caused in the error.  Otherwise,  inflateBack()
245793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
246793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   error, or Z_MEM_ERROR if it could not allocate memory for the state.
247793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   inflateBack() can also return Z_STREAM_ERROR if the input parameters
248793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   are not correct, i.e. strm is Z_NULL or the state was not initialized.
249793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
250793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerint ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
251793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerz_streamp strm;
252793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerin_func in;
253793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid FAR *in_desc;
254793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerout_func out;
255793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid FAR *out_desc;
256793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
257793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    struct inflate_state FAR *state;
258793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    z_const unsigned char FAR *next;    /* next input */
259793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    unsigned char FAR *put;     /* next output */
260793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    unsigned have, left;        /* available input and output */
261793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    unsigned long hold;         /* bit buffer */
262793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    unsigned bits;              /* bits in bit buffer */
263793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    unsigned copy;              /* number of stored or match bytes to copy */
264793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    unsigned char FAR *from;    /* where to copy match bytes from */
265793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    code here;                  /* current decoding table entry */
266793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    code last;                  /* parent table entry */
267793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    unsigned len;               /* length to copy for repeats, bits to drop */
268793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int ret;                    /* return code */
269793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    static const unsigned short order[19] = /* permutation of code lengths */
270793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
271793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
272793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* Check that the strm exists and that the state was initialized */
273793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (strm == Z_NULL || strm->state == Z_NULL)
274793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return Z_STREAM_ERROR;
275793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    state = (struct inflate_state FAR *)strm->state;
276793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
277793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* Reset the state */
278793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    strm->msg = Z_NULL;
279793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    state->mode = TYPE;
280793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    state->last = 0;
281793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    state->whave = 0;
282793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    next = strm->next_in;
283793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    have = next != Z_NULL ? strm->avail_in : 0;
284793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    hold = 0;
285793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    bits = 0;
286793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    put = state->window;
287793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    left = state->wsize;
288793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
289793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* Inflate until end of block marked as last */
290793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for (;;)
291793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        switch (state->mode) {
292793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case TYPE:
293793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* determine and dispatch block type */
294793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (state->last) {
295793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                BYTEBITS();
296793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->mode = DONE;
297793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
298793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
299793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            NEEDBITS(3);
300793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->last = BITS(1);
301793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            DROPBITS(1);
302793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            switch (BITS(2)) {
303793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            case 0:                             /* stored block */
304793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                Tracev((stderr, "inflate:     stored block%s\n",
305793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        state->last ? " (last)" : ""));
306793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->mode = STORED;
307793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
308793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            case 1:                             /* fixed block */
309793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                fixedtables(state);
310793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                Tracev((stderr, "inflate:     fixed codes block%s\n",
311793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        state->last ? " (last)" : ""));
312793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->mode = LEN;              /* decode codes */
313793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
314793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            case 2:                             /* dynamic block */
315793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                Tracev((stderr, "inflate:     dynamic codes block%s\n",
316793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        state->last ? " (last)" : ""));
317793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->mode = TABLE;
318793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
319793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            case 3:
320793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                strm->msg = (char *)"invalid block type";
321793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->mode = BAD;
322793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
323793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            DROPBITS(2);
324793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
325793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
326793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case STORED:
327793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* get and verify stored block length */
328793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            BYTEBITS();                         /* go to byte boundary */
329793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            NEEDBITS(32);
330793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
331793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                strm->msg = (char *)"invalid stored block lengths";
332793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->mode = BAD;
333793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
334793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
335793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->length = (unsigned)hold & 0xffff;
336793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Tracev((stderr, "inflate:       stored length %u\n",
337793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    state->length));
338793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            INITBITS();
339793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
340793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* copy stored block from input to output */
341793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            while (state->length != 0) {
342793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                copy = state->length;
343793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                PULL();
344793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                ROOM();
345793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if (copy > have) copy = have;
346793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if (copy > left) copy = left;
347793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                zmemcpy(put, next, copy);
348793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                have -= copy;
349793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                next += copy;
350793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                left -= copy;
351793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                put += copy;
352793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->length -= copy;
353793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
354793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Tracev((stderr, "inflate:       stored end\n"));
355793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->mode = TYPE;
356793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
357793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
358793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case TABLE:
359793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* get dynamic table entries descriptor */
360793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            NEEDBITS(14);
361793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->nlen = BITS(5) + 257;
362793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            DROPBITS(5);
363793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->ndist = BITS(5) + 1;
364793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            DROPBITS(5);
365793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->ncode = BITS(4) + 4;
366793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            DROPBITS(4);
367793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifndef PKZIP_BUG_WORKAROUND
368793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (state->nlen > 286 || state->ndist > 30) {
369793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                strm->msg = (char *)"too many length or distance symbols";
370793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->mode = BAD;
371793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
372793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
373793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
374793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Tracev((stderr, "inflate:       table sizes ok\n"));
375793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
376793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* get code length code lengths (not a typo) */
377793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->have = 0;
378793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            while (state->have < state->ncode) {
379793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                NEEDBITS(3);
380793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->lens[order[state->have++]] = (unsigned short)BITS(3);
381793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                DROPBITS(3);
382793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
383793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            while (state->have < 19)
384793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->lens[order[state->have++]] = 0;
385793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->next = state->codes;
386793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->lencode = (code const FAR *)(state->next);
387793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->lenbits = 7;
388793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            ret = inflate_table(CODES, state->lens, 19, &(state->next),
389793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                &(state->lenbits), state->work);
390793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (ret) {
391793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                strm->msg = (char *)"invalid code lengths set";
392793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->mode = BAD;
393793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
394793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
395793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Tracev((stderr, "inflate:       code lengths ok\n"));
396793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
397793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* get length and distance code code lengths */
398793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->have = 0;
399793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            while (state->have < state->nlen + state->ndist) {
400793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                for (;;) {
401793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    here = state->lencode[BITS(state->lenbits)];
402793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    if ((unsigned)(here.bits) <= bits) break;
403793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    PULLBYTE();
404793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
405793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if (here.val < 16) {
406793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    DROPBITS(here.bits);
407793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    state->lens[state->have++] = here.val;
408793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
409793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                else {
410793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    if (here.val == 16) {
411793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        NEEDBITS(here.bits + 2);
412793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        DROPBITS(here.bits);
413793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        if (state->have == 0) {
414793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                            strm->msg = (char *)"invalid bit length repeat";
415793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                            state->mode = BAD;
416793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                            break;
417793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        }
418793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        len = (unsigned)(state->lens[state->have - 1]);
419793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        copy = 3 + BITS(2);
420793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        DROPBITS(2);
421793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    }
422793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    else if (here.val == 17) {
423793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        NEEDBITS(here.bits + 3);
424793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        DROPBITS(here.bits);
425793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        len = 0;
426793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        copy = 3 + BITS(3);
427793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        DROPBITS(3);
428793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    }
429793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    else {
430793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        NEEDBITS(here.bits + 7);
431793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        DROPBITS(here.bits);
432793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        len = 0;
433793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        copy = 11 + BITS(7);
434793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        DROPBITS(7);
435793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    }
436793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    if (state->have + copy > state->nlen + state->ndist) {
437793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        strm->msg = (char *)"invalid bit length repeat";
438793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        state->mode = BAD;
439793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        break;
440793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    }
441793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    while (copy--)
442793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        state->lens[state->have++] = (unsigned short)len;
443793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
444793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
445793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
446793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* handle error breaks in while */
447793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (state->mode == BAD) break;
448793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
449793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* check for end-of-block code (better have one) */
450793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (state->lens[256] == 0) {
451793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                strm->msg = (char *)"invalid code -- missing end-of-block";
452793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->mode = BAD;
453793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
454793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
455793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
456793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* build code tables -- note: do not change the lenbits or distbits
457793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler               values here (9 and 6) without reading the comments in inftrees.h
458793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler               concerning the ENOUGH constants, which depend on those values */
459793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->next = state->codes;
460793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->lencode = (code const FAR *)(state->next);
461793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->lenbits = 9;
462793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
463793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                &(state->lenbits), state->work);
464793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (ret) {
465793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                strm->msg = (char *)"invalid literal/lengths set";
466793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->mode = BAD;
467793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
468793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
469793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->distcode = (code const FAR *)(state->next);
470793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->distbits = 6;
471793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
472793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                            &(state->next), &(state->distbits), state->work);
473793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (ret) {
474793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                strm->msg = (char *)"invalid distances set";
475793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->mode = BAD;
476793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
477793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
478793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Tracev((stderr, "inflate:       codes ok\n"));
479793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->mode = LEN;
480793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
481793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case LEN:
482793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* use inflate_fast() if we have enough input and output */
483793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (have >= 6 && left >= 258) {
484793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                RESTORE();
485793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if (state->whave < state->wsize)
486793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    state->whave = state->wsize - left;
487793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                inflate_fast(strm, state->wsize);
488793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                LOAD();
489793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
490793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
491793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
492793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* get a literal, length, or end-of-block code */
493793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            for (;;) {
494793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                here = state->lencode[BITS(state->lenbits)];
495793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if ((unsigned)(here.bits) <= bits) break;
496793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                PULLBYTE();
497793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
498793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (here.op && (here.op & 0xf0) == 0) {
499793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                last = here;
500793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                for (;;) {
501793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    here = state->lencode[last.val +
502793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                            (BITS(last.bits + last.op) >> last.bits)];
503793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    if ((unsigned)(last.bits + here.bits) <= bits) break;
504793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    PULLBYTE();
505793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
506793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                DROPBITS(last.bits);
507793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
508793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            DROPBITS(here.bits);
509793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->length = (unsigned)here.val;
510793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
511793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* process literal */
512793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (here.op == 0) {
513793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
514793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        "inflate:         literal '%c'\n" :
515793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        "inflate:         literal 0x%02x\n", here.val));
516793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                ROOM();
517793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                *put++ = (unsigned char)(state->length);
518793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                left--;
519793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->mode = LEN;
520793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
521793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
522793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
523793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* process end of block */
524793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (here.op & 32) {
525793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                Tracevv((stderr, "inflate:         end of block\n"));
526793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->mode = TYPE;
527793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
528793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
529793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
530793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* invalid code */
531793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (here.op & 64) {
532793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                strm->msg = (char *)"invalid literal/length code";
533793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->mode = BAD;
534793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
535793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
536793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
537793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* length code -- get extra bits, if any */
538793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->extra = (unsigned)(here.op) & 15;
539793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (state->extra != 0) {
540793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                NEEDBITS(state->extra);
541793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->length += BITS(state->extra);
542793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                DROPBITS(state->extra);
543793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
544793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Tracevv((stderr, "inflate:         length %u\n", state->length));
545793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
546793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* get distance code */
547793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            for (;;) {
548793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                here = state->distcode[BITS(state->distbits)];
549793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if ((unsigned)(here.bits) <= bits) break;
550793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                PULLBYTE();
551793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
552793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if ((here.op & 0xf0) == 0) {
553793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                last = here;
554793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                for (;;) {
555793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    here = state->distcode[last.val +
556793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                            (BITS(last.bits + last.op) >> last.bits)];
557793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    if ((unsigned)(last.bits + here.bits) <= bits) break;
558793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    PULLBYTE();
559793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
560793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                DROPBITS(last.bits);
561793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
562793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            DROPBITS(here.bits);
563793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (here.op & 64) {
564793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                strm->msg = (char *)"invalid distance code";
565793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->mode = BAD;
566793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
567793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
568793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->offset = (unsigned)here.val;
569793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
570793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* get distance extra bits, if any */
571793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            state->extra = (unsigned)(here.op) & 15;
572793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (state->extra != 0) {
573793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                NEEDBITS(state->extra);
574793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->offset += BITS(state->extra);
575793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                DROPBITS(state->extra);
576793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
577793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (state->offset > state->wsize - (state->whave < state->wsize ?
578793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                                left : 0)) {
579793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                strm->msg = (char *)"invalid distance too far back";
580793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->mode = BAD;
581793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
582793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
583793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
584793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
585793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* copy match from window to output */
586793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            do {
587793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                ROOM();
588793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                copy = state->wsize - state->offset;
589793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if (copy < left) {
590793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    from = put + copy;
591793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    copy = left - copy;
592793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
593793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                else {
594793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    from = put - state->offset;
595793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    copy = left;
596793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
597793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if (copy > state->length) copy = state->length;
598793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                state->length -= copy;
599793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                left -= copy;
600793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                do {
601793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    *put++ = *from++;
602793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                } while (--copy);
603793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            } while (state->length != 0);
604793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
605793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
606793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case DONE:
607793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            /* inflate stream terminated properly -- write leftover output */
608793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            ret = Z_STREAM_END;
609793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (left < state->wsize) {
610793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if (out(out_desc, state->window, state->wsize - left))
611793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    ret = Z_BUF_ERROR;
612793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
613793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            goto inf_leave;
614793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
615793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case BAD:
616793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            ret = Z_DATA_ERROR;
617793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            goto inf_leave;
618793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
619793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        default:                /* can't happen, but makes compilers happy */
620793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            ret = Z_STREAM_ERROR;
621793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            goto inf_leave;
622793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
623793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
624793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* Return unused input */
625793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  inf_leave:
626793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    strm->next_in = next;
627793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    strm->avail_in = have;
628793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return ret;
629793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
630793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
631793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerint ZEXPORT inflateBackEnd(strm)
632793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerz_streamp strm;
633793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
634793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
635793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return Z_STREAM_ERROR;
636793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ZFREE(strm, strm->state);
637793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    strm->state = Z_NULL;
638793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Tracev((stderr, "inflate: end\n"));
639793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return Z_OK;
640793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
641