xref: /onnv-gate/usr/src/uts/common/zmod/inflate.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
3*0Sstevel@tonic-gate  * Use is subject to license terms.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate 
6*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*0Sstevel@tonic-gate 
8*0Sstevel@tonic-gate /*
9*0Sstevel@tonic-gate  * inflate.c -- zlib interface to inflate modules
10*0Sstevel@tonic-gate  * Copyright (C) 1995-1998 Mark Adler
11*0Sstevel@tonic-gate  * For conditions of distribution and use, see copyright notice in zlib.h
12*0Sstevel@tonic-gate  */
13*0Sstevel@tonic-gate 
14*0Sstevel@tonic-gate #include "zutil.h"
15*0Sstevel@tonic-gate #include "infblock.h"
16*0Sstevel@tonic-gate 
17*0Sstevel@tonic-gate typedef enum {
18*0Sstevel@tonic-gate       METHOD,   /* waiting for method byte */
19*0Sstevel@tonic-gate       FLAG,     /* waiting for flag byte */
20*0Sstevel@tonic-gate       DICT4,    /* four dictionary check bytes to go */
21*0Sstevel@tonic-gate       DICT3,    /* three dictionary check bytes to go */
22*0Sstevel@tonic-gate       DICT2,    /* two dictionary check bytes to go */
23*0Sstevel@tonic-gate       DICT1,    /* one dictionary check byte to go */
24*0Sstevel@tonic-gate       DICT0,    /* waiting for inflateSetDictionary */
25*0Sstevel@tonic-gate       BLOCKS,   /* decompressing blocks */
26*0Sstevel@tonic-gate       CHECK4,   /* four check bytes to go */
27*0Sstevel@tonic-gate       CHECK3,   /* three check bytes to go */
28*0Sstevel@tonic-gate       CHECK2,   /* two check bytes to go */
29*0Sstevel@tonic-gate       CHECK1,   /* one check byte to go */
30*0Sstevel@tonic-gate       DONE,     /* finished check, done */
31*0Sstevel@tonic-gate       BAD}      /* got an error--stay here */
32*0Sstevel@tonic-gate inflate_mode;
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate /* inflate private state */
35*0Sstevel@tonic-gate struct internal_state {
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate   /* mode */
38*0Sstevel@tonic-gate   inflate_mode  mode;   /* current inflate mode */
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate   /* mode dependent information */
41*0Sstevel@tonic-gate   union {
42*0Sstevel@tonic-gate     uInt method;        /* if FLAGS, method byte */
43*0Sstevel@tonic-gate     struct {
44*0Sstevel@tonic-gate       uLong was;                /* computed check value */
45*0Sstevel@tonic-gate       uLong need;               /* stream check value */
46*0Sstevel@tonic-gate     } check;            /* if CHECK, check values to compare */
47*0Sstevel@tonic-gate     uInt marker;        /* if BAD, inflateSync's marker bytes count */
48*0Sstevel@tonic-gate   } sub;        /* submode */
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate   /* mode independent information */
51*0Sstevel@tonic-gate   int  nowrap;          /* flag for no wrapper */
52*0Sstevel@tonic-gate   uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
53*0Sstevel@tonic-gate   inflate_blocks_statef
54*0Sstevel@tonic-gate     *blocks;            /* current inflate_blocks state */
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate };
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate int ZEXPORT inflateReset(z)
60*0Sstevel@tonic-gate z_streamp z;
61*0Sstevel@tonic-gate {
62*0Sstevel@tonic-gate   if (z == Z_NULL || z->state == Z_NULL)
63*0Sstevel@tonic-gate     return Z_STREAM_ERROR;
64*0Sstevel@tonic-gate   z->total_in = z->total_out = 0;
65*0Sstevel@tonic-gate   z->msg = Z_NULL;
66*0Sstevel@tonic-gate   z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
67*0Sstevel@tonic-gate   inflate_blocks_reset(z->state->blocks, z, Z_NULL);
68*0Sstevel@tonic-gate   Tracev((stderr, "inflate: reset\n"));
69*0Sstevel@tonic-gate   return Z_OK;
70*0Sstevel@tonic-gate }
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate int ZEXPORT inflateEnd(z)
74*0Sstevel@tonic-gate z_streamp z;
75*0Sstevel@tonic-gate {
76*0Sstevel@tonic-gate   if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
77*0Sstevel@tonic-gate     return Z_STREAM_ERROR;
78*0Sstevel@tonic-gate   if (z->state->blocks != Z_NULL)
79*0Sstevel@tonic-gate     (void) inflate_blocks_free(z->state->blocks, z);
80*0Sstevel@tonic-gate   ZFREE(z, z->state);
81*0Sstevel@tonic-gate   z->state = Z_NULL;
82*0Sstevel@tonic-gate   Tracev((stderr, "inflate: end\n"));
83*0Sstevel@tonic-gate   return Z_OK;
84*0Sstevel@tonic-gate }
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate 
87*0Sstevel@tonic-gate int ZEXPORT inflateInit2_(z, w, version, stream_size)
88*0Sstevel@tonic-gate z_streamp z;
89*0Sstevel@tonic-gate int w;
90*0Sstevel@tonic-gate const char *version;
91*0Sstevel@tonic-gate int stream_size;
92*0Sstevel@tonic-gate {
93*0Sstevel@tonic-gate   if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
94*0Sstevel@tonic-gate       stream_size != sizeof(z_stream))
95*0Sstevel@tonic-gate       return Z_VERSION_ERROR;
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate   /* initialize state */
98*0Sstevel@tonic-gate   if (z == Z_NULL)
99*0Sstevel@tonic-gate     return Z_STREAM_ERROR;
100*0Sstevel@tonic-gate   z->msg = Z_NULL;
101*0Sstevel@tonic-gate   if (z->zalloc == Z_NULL)
102*0Sstevel@tonic-gate   {
103*0Sstevel@tonic-gate     z->zalloc = zcalloc;
104*0Sstevel@tonic-gate     z->opaque = (voidpf)0;
105*0Sstevel@tonic-gate   }
106*0Sstevel@tonic-gate   if (z->zfree == Z_NULL) z->zfree = zcfree;
107*0Sstevel@tonic-gate   if ((z->state = (struct internal_state FAR *)
108*0Sstevel@tonic-gate        ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
109*0Sstevel@tonic-gate     return Z_MEM_ERROR;
110*0Sstevel@tonic-gate   z->state->blocks = Z_NULL;
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate   /* handle undocumented nowrap option (no zlib header or check) */
113*0Sstevel@tonic-gate   z->state->nowrap = 0;
114*0Sstevel@tonic-gate   if (w < 0)
115*0Sstevel@tonic-gate   {
116*0Sstevel@tonic-gate     w = - w;
117*0Sstevel@tonic-gate     z->state->nowrap = 1;
118*0Sstevel@tonic-gate   }
119*0Sstevel@tonic-gate 
120*0Sstevel@tonic-gate   /* set window size */
121*0Sstevel@tonic-gate   if (w < 8 || w > 15)
122*0Sstevel@tonic-gate   {
123*0Sstevel@tonic-gate     (void) inflateEnd(z);
124*0Sstevel@tonic-gate     return Z_STREAM_ERROR;
125*0Sstevel@tonic-gate   }
126*0Sstevel@tonic-gate   z->state->wbits = (uInt)w;
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate   /* create inflate_blocks state */
129*0Sstevel@tonic-gate   if ((z->state->blocks =
130*0Sstevel@tonic-gate       inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
131*0Sstevel@tonic-gate       == Z_NULL)
132*0Sstevel@tonic-gate   {
133*0Sstevel@tonic-gate     (void) inflateEnd(z);
134*0Sstevel@tonic-gate     return Z_MEM_ERROR;
135*0Sstevel@tonic-gate   }
136*0Sstevel@tonic-gate   Tracev((stderr, "inflate: allocated\n"));
137*0Sstevel@tonic-gate 
138*0Sstevel@tonic-gate   /* reset state */
139*0Sstevel@tonic-gate   (void) inflateReset(z);
140*0Sstevel@tonic-gate   return Z_OK;
141*0Sstevel@tonic-gate }
142*0Sstevel@tonic-gate 
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate int ZEXPORT inflateInit_(z, version, stream_size)
145*0Sstevel@tonic-gate z_streamp z;
146*0Sstevel@tonic-gate const char *version;
147*0Sstevel@tonic-gate int stream_size;
148*0Sstevel@tonic-gate {
149*0Sstevel@tonic-gate   return inflateInit2_(z, DEF_WBITS, version, stream_size);
150*0Sstevel@tonic-gate }
151*0Sstevel@tonic-gate 
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate #define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
154*0Sstevel@tonic-gate #define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate int ZEXPORT inflate(z, f)
157*0Sstevel@tonic-gate z_streamp z;
158*0Sstevel@tonic-gate int f;
159*0Sstevel@tonic-gate {
160*0Sstevel@tonic-gate   int r;
161*0Sstevel@tonic-gate   uInt b;
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate   if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
164*0Sstevel@tonic-gate     return Z_STREAM_ERROR;
165*0Sstevel@tonic-gate   f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
166*0Sstevel@tonic-gate   r = Z_BUF_ERROR;
167*0Sstevel@tonic-gate   /*CONSTCOND*/
168*0Sstevel@tonic-gate   while (1) switch (z->state->mode)
169*0Sstevel@tonic-gate   {
170*0Sstevel@tonic-gate     case METHOD:
171*0Sstevel@tonic-gate       NEEDBYTE
172*0Sstevel@tonic-gate       if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
173*0Sstevel@tonic-gate       {
174*0Sstevel@tonic-gate         z->state->mode = BAD;
175*0Sstevel@tonic-gate         z->msg = (char*)"unknown compression method";
176*0Sstevel@tonic-gate         z->state->sub.marker = 5;       /* can't try inflateSync */
177*0Sstevel@tonic-gate         break;
178*0Sstevel@tonic-gate       }
179*0Sstevel@tonic-gate       if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
180*0Sstevel@tonic-gate       {
181*0Sstevel@tonic-gate         z->state->mode = BAD;
182*0Sstevel@tonic-gate         z->msg = (char*)"invalid window size";
183*0Sstevel@tonic-gate         z->state->sub.marker = 5;       /* can't try inflateSync */
184*0Sstevel@tonic-gate         break;
185*0Sstevel@tonic-gate       }
186*0Sstevel@tonic-gate       z->state->mode = FLAG;
187*0Sstevel@tonic-gate       /*FALLTHRU*/
188*0Sstevel@tonic-gate     case FLAG:
189*0Sstevel@tonic-gate       NEEDBYTE
190*0Sstevel@tonic-gate       b = NEXTBYTE;
191*0Sstevel@tonic-gate       if (((z->state->sub.method << 8) + b) % 31)
192*0Sstevel@tonic-gate       {
193*0Sstevel@tonic-gate         z->state->mode = BAD;
194*0Sstevel@tonic-gate         z->msg = (char*)"incorrect header check";
195*0Sstevel@tonic-gate         z->state->sub.marker = 5;       /* can't try inflateSync */
196*0Sstevel@tonic-gate         break;
197*0Sstevel@tonic-gate       }
198*0Sstevel@tonic-gate       Tracev((stderr, "inflate: zlib header ok\n"));
199*0Sstevel@tonic-gate       if (!(b & PRESET_DICT))
200*0Sstevel@tonic-gate       {
201*0Sstevel@tonic-gate         z->state->mode = BLOCKS;
202*0Sstevel@tonic-gate         break;
203*0Sstevel@tonic-gate       }
204*0Sstevel@tonic-gate       z->state->mode = DICT4;
205*0Sstevel@tonic-gate       /*FALLTHRU*/
206*0Sstevel@tonic-gate     case DICT4:
207*0Sstevel@tonic-gate       NEEDBYTE
208*0Sstevel@tonic-gate       z->state->sub.check.need = (uLong)NEXTBYTE << 24;
209*0Sstevel@tonic-gate       z->state->mode = DICT3;
210*0Sstevel@tonic-gate       /*FALLTHRU*/
211*0Sstevel@tonic-gate     case DICT3:
212*0Sstevel@tonic-gate       NEEDBYTE
213*0Sstevel@tonic-gate       z->state->sub.check.need += (uLong)NEXTBYTE << 16;
214*0Sstevel@tonic-gate       z->state->mode = DICT2;
215*0Sstevel@tonic-gate       /*FALLTHRU*/
216*0Sstevel@tonic-gate     case DICT2:
217*0Sstevel@tonic-gate       NEEDBYTE
218*0Sstevel@tonic-gate       z->state->sub.check.need += (uLong)NEXTBYTE << 8;
219*0Sstevel@tonic-gate       z->state->mode = DICT1;
220*0Sstevel@tonic-gate       /*FALLTHRU*/
221*0Sstevel@tonic-gate     case DICT1:
222*0Sstevel@tonic-gate       NEEDBYTE
223*0Sstevel@tonic-gate       z->state->sub.check.need += (uLong)NEXTBYTE;
224*0Sstevel@tonic-gate       z->adler = z->state->sub.check.need;
225*0Sstevel@tonic-gate       z->state->mode = DICT0;
226*0Sstevel@tonic-gate       return Z_NEED_DICT;
227*0Sstevel@tonic-gate     case DICT0:
228*0Sstevel@tonic-gate       z->state->mode = BAD;
229*0Sstevel@tonic-gate       z->msg = (char*)"need dictionary";
230*0Sstevel@tonic-gate       z->state->sub.marker = 0;       /* can try inflateSync */
231*0Sstevel@tonic-gate       return Z_STREAM_ERROR;
232*0Sstevel@tonic-gate     case BLOCKS:
233*0Sstevel@tonic-gate       r = inflate_blocks(z->state->blocks, z, r);
234*0Sstevel@tonic-gate       if (r == Z_DATA_ERROR)
235*0Sstevel@tonic-gate       {
236*0Sstevel@tonic-gate         z->state->mode = BAD;
237*0Sstevel@tonic-gate         z->state->sub.marker = 0;       /* can try inflateSync */
238*0Sstevel@tonic-gate         break;
239*0Sstevel@tonic-gate       }
240*0Sstevel@tonic-gate       if (r == Z_OK)
241*0Sstevel@tonic-gate         r = f;
242*0Sstevel@tonic-gate       if (r != Z_STREAM_END)
243*0Sstevel@tonic-gate         return r;
244*0Sstevel@tonic-gate       r = f;
245*0Sstevel@tonic-gate       inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
246*0Sstevel@tonic-gate       if (z->state->nowrap)
247*0Sstevel@tonic-gate       {
248*0Sstevel@tonic-gate         z->state->mode = DONE;
249*0Sstevel@tonic-gate         break;
250*0Sstevel@tonic-gate       }
251*0Sstevel@tonic-gate       z->state->mode = CHECK4;
252*0Sstevel@tonic-gate       /*FALLTHRU*/
253*0Sstevel@tonic-gate     case CHECK4:
254*0Sstevel@tonic-gate       NEEDBYTE
255*0Sstevel@tonic-gate       z->state->sub.check.need = (uLong)NEXTBYTE << 24;
256*0Sstevel@tonic-gate       z->state->mode = CHECK3;
257*0Sstevel@tonic-gate       /*FALLTHRU*/
258*0Sstevel@tonic-gate     case CHECK3:
259*0Sstevel@tonic-gate       NEEDBYTE
260*0Sstevel@tonic-gate       z->state->sub.check.need += (uLong)NEXTBYTE << 16;
261*0Sstevel@tonic-gate       z->state->mode = CHECK2;
262*0Sstevel@tonic-gate       /*FALLTHRU*/
263*0Sstevel@tonic-gate     case CHECK2:
264*0Sstevel@tonic-gate       NEEDBYTE
265*0Sstevel@tonic-gate       z->state->sub.check.need += (uLong)NEXTBYTE << 8;
266*0Sstevel@tonic-gate       z->state->mode = CHECK1;
267*0Sstevel@tonic-gate       /*FALLTHRU*/
268*0Sstevel@tonic-gate     case CHECK1:
269*0Sstevel@tonic-gate       NEEDBYTE
270*0Sstevel@tonic-gate       z->state->sub.check.need += (uLong)NEXTBYTE;
271*0Sstevel@tonic-gate 
272*0Sstevel@tonic-gate       if (z->state->sub.check.was != z->state->sub.check.need)
273*0Sstevel@tonic-gate       {
274*0Sstevel@tonic-gate         z->state->mode = BAD;
275*0Sstevel@tonic-gate         z->msg = (char*)"incorrect data check";
276*0Sstevel@tonic-gate         z->state->sub.marker = 5;       /* can't try inflateSync */
277*0Sstevel@tonic-gate         break;
278*0Sstevel@tonic-gate       }
279*0Sstevel@tonic-gate       Tracev((stderr, "inflate: zlib check ok\n"));
280*0Sstevel@tonic-gate       z->state->mode = DONE;
281*0Sstevel@tonic-gate       /*FALLTHRU*/
282*0Sstevel@tonic-gate     case DONE:
283*0Sstevel@tonic-gate       return Z_STREAM_END;
284*0Sstevel@tonic-gate     case BAD:
285*0Sstevel@tonic-gate       return Z_DATA_ERROR;
286*0Sstevel@tonic-gate     default:
287*0Sstevel@tonic-gate       return Z_STREAM_ERROR;
288*0Sstevel@tonic-gate   }
289*0Sstevel@tonic-gate   /*NOTREACHED*/
290*0Sstevel@tonic-gate }
291