xref: /linux/lib/zlib_inflate/inflate.c (revision 3d5271f9883cba7b54762bc4fe027d4172f06db7)
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 <linux/zutil.h>
7 #include "infblock.h"
8 #include "infutil.h"
9 
10 int zlib_inflate_workspacesize(void)
11 {
12   return sizeof(struct inflate_workspace);
13 }
14 
15 
16 int zlib_inflateReset(
17 	z_streamp z
18 )
19 {
20   if (z == NULL || z->state == NULL || z->workspace == NULL)
21     return Z_STREAM_ERROR;
22   z->total_in = z->total_out = 0;
23   z->msg = NULL;
24   z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
25   zlib_inflate_blocks_reset(z->state->blocks, z, NULL);
26   return Z_OK;
27 }
28 
29 
30 int zlib_inflateEnd(
31 	z_streamp z
32 )
33 {
34   if (z == NULL || z->state == NULL || z->workspace == NULL)
35     return Z_STREAM_ERROR;
36   if (z->state->blocks != NULL)
37     zlib_inflate_blocks_free(z->state->blocks, z);
38   z->state = NULL;
39   return Z_OK;
40 }
41 
42 
43 int zlib_inflateInit2_(
44 	z_streamp z,
45 	int w,
46 	const char *version,
47 	int stream_size
48 )
49 {
50   if (version == NULL || version[0] != ZLIB_VERSION[0] ||
51       stream_size != sizeof(z_stream) || z->workspace == NULL)
52       return Z_VERSION_ERROR;
53 
54   /* initialize state */
55   z->msg = NULL;
56   z->state = &WS(z)->internal_state;
57   z->state->blocks = NULL;
58 
59   /* handle undocumented nowrap option (no zlib header or check) */
60   z->state->nowrap = 0;
61   if (w < 0)
62   {
63     w = - w;
64     z->state->nowrap = 1;
65   }
66 
67   /* set window size */
68   if (w < 8 || w > 15)
69   {
70     zlib_inflateEnd(z);
71     return Z_STREAM_ERROR;
72   }
73   z->state->wbits = (uInt)w;
74 
75   /* create inflate_blocks state */
76   if ((z->state->blocks =
77       zlib_inflate_blocks_new(z, z->state->nowrap ? NULL : zlib_adler32, (uInt)1 << w))
78       == NULL)
79   {
80     zlib_inflateEnd(z);
81     return Z_MEM_ERROR;
82   }
83 
84   /* reset state */
85   zlib_inflateReset(z);
86   return Z_OK;
87 }
88 
89 
90 /*
91  * At the end of a Deflate-compressed PPP packet, we expect to have seen
92  * a `stored' block type value but not the (zero) length bytes.
93  */
94 static int zlib_inflate_packet_flush(inflate_blocks_statef *s)
95 {
96     if (s->mode != LENS)
97 	return Z_DATA_ERROR;
98     s->mode = TYPE;
99     return Z_OK;
100 }
101 
102 
103 int zlib_inflateInit_(
104 	z_streamp z,
105 	const char *version,
106 	int stream_size
107 )
108 {
109   return zlib_inflateInit2_(z, DEF_WBITS, version, stream_size);
110 }
111 
112 #undef NEEDBYTE
113 #undef NEXTBYTE
114 #define NEEDBYTE {if(z->avail_in==0)goto empty;r=trv;}
115 #define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
116 
117 int zlib_inflate(
118 	z_streamp z,
119 	int f
120 )
121 {
122   int r, trv;
123   uInt b;
124 
125   if (z == NULL || z->state == NULL || z->next_in == NULL)
126     return Z_STREAM_ERROR;
127   trv = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
128   r = Z_BUF_ERROR;
129   while (1) switch (z->state->mode)
130   {
131     case METHOD:
132       NEEDBYTE
133       if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
134       {
135         z->state->mode = I_BAD;
136         z->msg = (char*)"unknown compression method";
137         z->state->sub.marker = 5;       /* can't try inflateSync */
138         break;
139       }
140       if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
141       {
142         z->state->mode = I_BAD;
143         z->msg = (char*)"invalid window size";
144         z->state->sub.marker = 5;       /* can't try inflateSync */
145         break;
146       }
147       z->state->mode = FLAG;
148     case FLAG:
149       NEEDBYTE
150       b = NEXTBYTE;
151       if (((z->state->sub.method << 8) + b) % 31)
152       {
153         z->state->mode = I_BAD;
154         z->msg = (char*)"incorrect header check";
155         z->state->sub.marker = 5;       /* can't try inflateSync */
156         break;
157       }
158       if (!(b & PRESET_DICT))
159       {
160         z->state->mode = BLOCKS;
161         break;
162       }
163       z->state->mode = DICT4;
164     case DICT4:
165       NEEDBYTE
166       z->state->sub.check.need = (uLong)NEXTBYTE << 24;
167       z->state->mode = DICT3;
168     case DICT3:
169       NEEDBYTE
170       z->state->sub.check.need += (uLong)NEXTBYTE << 16;
171       z->state->mode = DICT2;
172     case DICT2:
173       NEEDBYTE
174       z->state->sub.check.need += (uLong)NEXTBYTE << 8;
175       z->state->mode = DICT1;
176     case DICT1:
177       NEEDBYTE
178       z->state->sub.check.need += (uLong)NEXTBYTE;
179       z->adler = z->state->sub.check.need;
180       z->state->mode = DICT0;
181       return Z_NEED_DICT;
182     case DICT0:
183       z->state->mode = I_BAD;
184       z->msg = (char*)"need dictionary";
185       z->state->sub.marker = 0;       /* can try inflateSync */
186       return Z_STREAM_ERROR;
187     case BLOCKS:
188       r = zlib_inflate_blocks(z->state->blocks, z, r);
189       if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0)
190 	  r = zlib_inflate_packet_flush(z->state->blocks);
191       if (r == Z_DATA_ERROR)
192       {
193         z->state->mode = I_BAD;
194         z->state->sub.marker = 0;       /* can try inflateSync */
195         break;
196       }
197       if (r == Z_OK)
198         r = trv;
199       if (r != Z_STREAM_END)
200         return r;
201       r = trv;
202       zlib_inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
203       if (z->state->nowrap)
204       {
205         z->state->mode = I_DONE;
206         break;
207       }
208       z->state->mode = CHECK4;
209     case CHECK4:
210       NEEDBYTE
211       z->state->sub.check.need = (uLong)NEXTBYTE << 24;
212       z->state->mode = CHECK3;
213     case CHECK3:
214       NEEDBYTE
215       z->state->sub.check.need += (uLong)NEXTBYTE << 16;
216       z->state->mode = CHECK2;
217     case CHECK2:
218       NEEDBYTE
219       z->state->sub.check.need += (uLong)NEXTBYTE << 8;
220       z->state->mode = CHECK1;
221     case CHECK1:
222       NEEDBYTE
223       z->state->sub.check.need += (uLong)NEXTBYTE;
224 
225       if (z->state->sub.check.was != z->state->sub.check.need)
226       {
227         z->state->mode = I_BAD;
228         z->msg = (char*)"incorrect data check";
229         z->state->sub.marker = 5;       /* can't try inflateSync */
230         break;
231       }
232       z->state->mode = I_DONE;
233     case I_DONE:
234       return Z_STREAM_END;
235     case I_BAD:
236       return Z_DATA_ERROR;
237     default:
238       return Z_STREAM_ERROR;
239   }
240  empty:
241   if (f != Z_PACKET_FLUSH)
242     return r;
243   z->state->mode = I_BAD;
244   z->msg = (char *)"need more for packet flush";
245   z->state->sub.marker = 0;       /* can try inflateSync */
246   return Z_DATA_ERROR;
247 }
248