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