inflate.c revision 33904
1/* inflate.c -- zlib interface to inflate modules
2 * Copyright (C) 1995-1998 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6#include "zutil.h"
7#include "infblock.h"
8
9struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
10
11typedef enum {
12      METHOD,   /* waiting for method byte */
13      FLAG,     /* waiting for flag byte */
14      DICT4,    /* four dictionary check bytes to go */
15      DICT3,    /* three dictionary check bytes to go */
16      DICT2,    /* two dictionary check bytes to go */
17      DICT1,    /* one dictionary check byte to go */
18      DICT0,    /* waiting for inflateSetDictionary */
19      BLOCKS,   /* decompressing blocks */
20      CHECK4,   /* four check bytes to go */
21      CHECK3,   /* three check bytes to go */
22      CHECK2,   /* two check bytes to go */
23      CHECK1,   /* one check byte to go */
24      DONE,     /* finished check, done */
25      BAD}      /* got an error--stay here */
26inflate_mode;
27
28/* inflate private state */
29struct internal_state {
30
31  /* mode */
32  inflate_mode  mode;   /* current inflate mode */
33
34  /* mode dependent information */
35  union {
36    uInt method;        /* if FLAGS, method byte */
37    struct {
38      uLong was;                /* computed check value */
39      uLong need;               /* stream check value */
40    } check;            /* if CHECK, check values to compare */
41    uInt marker;        /* if BAD, inflateSync's marker bytes count */
42  } sub;        /* submode */
43
44  /* mode independent information */
45  int  nowrap;          /* flag for no wrapper */
46  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
47  inflate_blocks_statef
48    *blocks;            /* current inflate_blocks state */
49
50};
51
52
53int ZEXPORT inflateReset(z)
54z_streamp z;
55{
56  if (z == Z_NULL || z->state == Z_NULL)
57    return Z_STREAM_ERROR;
58  z->total_in = z->total_out = 0;
59  z->msg = Z_NULL;
60  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
61  inflate_blocks_reset(z->state->blocks, z, Z_NULL);
62  Tracev((stderr, "inflate: reset\n"));
63  return Z_OK;
64}
65
66
67int ZEXPORT inflateEnd(z)
68z_streamp z;
69{
70  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
71    return Z_STREAM_ERROR;
72  if (z->state->blocks != Z_NULL)
73    inflate_blocks_free(z->state->blocks, z);
74  ZFREE(z, z->state);
75  z->state = Z_NULL;
76  Tracev((stderr, "inflate: end\n"));
77  return Z_OK;
78}
79
80
81int ZEXPORT inflateInit2_(z, w, version, stream_size)
82z_streamp z;
83int w;
84const char *version;
85int stream_size;
86{
87  if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
88      stream_size != sizeof(z_stream))
89      return Z_VERSION_ERROR;
90
91  /* initialize state */
92  if (z == Z_NULL)
93    return Z_STREAM_ERROR;
94  z->msg = Z_NULL;
95  if (z->zalloc == Z_NULL)
96  {
97    z->zalloc = zcalloc;
98    z->opaque = (voidpf)0;
99  }
100  if (z->zfree == Z_NULL) z->zfree = zcfree;
101  if ((z->state = (struct internal_state FAR *)
102       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
103    return Z_MEM_ERROR;
104  z->state->blocks = Z_NULL;
105
106  /* handle undocumented nowrap option (no zlib header or check) */
107  z->state->nowrap = 0;
108  if (w < 0)
109  {
110    w = - w;
111    z->state->nowrap = 1;
112  }
113
114  /* set window size */
115  if (w < 8 || w > 15)
116  {
117    inflateEnd(z);
118    return Z_STREAM_ERROR;
119  }
120  z->state->wbits = (uInt)w;
121
122  /* create inflate_blocks state */
123  if ((z->state->blocks =
124      inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
125      == Z_NULL)
126  {
127    inflateEnd(z);
128    return Z_MEM_ERROR;
129  }
130  Tracev((stderr, "inflate: allocated\n"));
131
132  /* reset state */
133  inflateReset(z);
134  return Z_OK;
135}
136
137
138int ZEXPORT inflateInit_(z, version, stream_size)
139z_streamp z;
140const char *version;
141int stream_size;
142{
143  return inflateInit2_(z, DEF_WBITS, version, stream_size);
144}
145
146
147#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
148#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
149
150int ZEXPORT inflate(z, f)
151z_streamp z;
152int f;
153{
154  int r;
155  uInt b;
156
157  if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
158    return Z_STREAM_ERROR;
159  f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
160  r = Z_BUF_ERROR;
161  while (1) switch (z->state->mode)
162  {
163    case METHOD:
164      NEEDBYTE
165      if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
166      {
167        z->state->mode = BAD;
168        z->msg = (char*)"unknown compression method";
169        z->state->sub.marker = 5;       /* can't try inflateSync */
170        break;
171      }
172      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
173      {
174        z->state->mode = BAD;
175        z->msg = (char*)"invalid window size";
176        z->state->sub.marker = 5;       /* can't try inflateSync */
177        break;
178      }
179      z->state->mode = FLAG;
180    case FLAG:
181      NEEDBYTE
182      b = NEXTBYTE;
183      if (((z->state->sub.method << 8) + b) % 31)
184      {
185        z->state->mode = BAD;
186        z->msg = (char*)"incorrect header check";
187        z->state->sub.marker = 5;       /* can't try inflateSync */
188        break;
189      }
190      Tracev((stderr, "inflate: zlib header ok\n"));
191      if (!(b & PRESET_DICT))
192      {
193        z->state->mode = BLOCKS;
194        break;
195      }
196      z->state->mode = DICT4;
197    case DICT4:
198      NEEDBYTE
199      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
200      z->state->mode = DICT3;
201    case DICT3:
202      NEEDBYTE
203      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
204      z->state->mode = DICT2;
205    case DICT2:
206      NEEDBYTE
207      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
208      z->state->mode = DICT1;
209    case DICT1:
210      NEEDBYTE
211      z->state->sub.check.need += (uLong)NEXTBYTE;
212      z->adler = z->state->sub.check.need;
213      z->state->mode = DICT0;
214      return Z_NEED_DICT;
215    case DICT0:
216      z->state->mode = BAD;
217      z->msg = (char*)"need dictionary";
218      z->state->sub.marker = 0;       /* can try inflateSync */
219      return Z_STREAM_ERROR;
220    case BLOCKS:
221      r = inflate_blocks(z->state->blocks, z, r);
222      if (r == Z_DATA_ERROR)
223      {
224        z->state->mode = BAD;
225        z->state->sub.marker = 0;       /* can try inflateSync */
226        break;
227      }
228      if (r == Z_OK)
229        r = f;
230      if (r != Z_STREAM_END)
231        return r;
232      r = f;
233      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
234      if (z->state->nowrap)
235      {
236        z->state->mode = DONE;
237        break;
238      }
239      z->state->mode = CHECK4;
240    case CHECK4:
241      NEEDBYTE
242      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
243      z->state->mode = CHECK3;
244    case CHECK3:
245      NEEDBYTE
246      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
247      z->state->mode = CHECK2;
248    case CHECK2:
249      NEEDBYTE
250      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
251      z->state->mode = CHECK1;
252    case CHECK1:
253      NEEDBYTE
254      z->state->sub.check.need += (uLong)NEXTBYTE;
255
256      if (z->state->sub.check.was != z->state->sub.check.need)
257      {
258        z->state->mode = BAD;
259        z->msg = (char*)"incorrect data check";
260        z->state->sub.marker = 5;       /* can't try inflateSync */
261        break;
262      }
263      Tracev((stderr, "inflate: zlib check ok\n"));
264      z->state->mode = DONE;
265    case DONE:
266      return Z_STREAM_END;
267    case BAD:
268      return Z_DATA_ERROR;
269    default:
270      return Z_STREAM_ERROR;
271  }
272#ifdef NEED_DUMMY_RETURN
273  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
274#endif
275}
276
277
278int ZEXPORT inflateSetDictionary(z, dictionary, dictLength)
279z_streamp z;
280const Bytef *dictionary;
281uInt  dictLength;
282{
283  uInt length = dictLength;
284
285  if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
286    return Z_STREAM_ERROR;
287
288  if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
289  z->adler = 1L;
290
291  if (length >= ((uInt)1<<z->state->wbits))
292  {
293    length = (1<<z->state->wbits)-1;
294    dictionary += dictLength - length;
295  }
296  inflate_set_dictionary(z->state->blocks, dictionary, length);
297  z->state->mode = BLOCKS;
298  return Z_OK;
299}
300
301
302int ZEXPORT inflateSync(z)
303z_streamp z;
304{
305  uInt n;       /* number of bytes to look at */
306  Bytef *p;     /* pointer to bytes */
307  uInt m;       /* number of marker bytes found in a row */
308  uLong r, w;   /* temporaries to save total_in and total_out */
309
310  /* set up */
311  if (z == Z_NULL || z->state == Z_NULL)
312    return Z_STREAM_ERROR;
313  if (z->state->mode != BAD)
314  {
315    z->state->mode = BAD;
316    z->state->sub.marker = 0;
317  }
318  if ((n = z->avail_in) == 0)
319    return Z_BUF_ERROR;
320  p = z->next_in;
321  m = z->state->sub.marker;
322
323  /* search */
324  while (n && m < 4)
325  {
326    static const Byte mark[4] = {0, 0, 0xff, 0xff};
327    if (*p == mark[m])
328      m++;
329    else if (*p)
330      m = 0;
331    else
332      m = 4 - m;
333    p++, n--;
334  }
335
336  /* restore */
337  z->total_in += p - z->next_in;
338  z->next_in = p;
339  z->avail_in = n;
340  z->state->sub.marker = m;
341
342  /* return no joy or set up to restart on a new block */
343  if (m != 4)
344    return Z_DATA_ERROR;
345  r = z->total_in;  w = z->total_out;
346  inflateReset(z);
347  z->total_in = r;  z->total_out = w;
348  z->state->mode = BLOCKS;
349  return Z_OK;
350}
351
352
353/* Returns true if inflate is currently at the end of a block generated
354 * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
355 * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
356 * but removes the length bytes of the resulting empty stored block. When
357 * decompressing, PPP checks that at the end of input packet, inflate is
358 * waiting for these length bytes.
359 */
360int ZEXPORT inflateSyncPoint(z)
361z_streamp z;
362{
363  if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
364    return Z_STREAM_ERROR;
365  return inflate_blocks_sync_point(z->state->blocks);
366}
367