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