1ab9e68a2SToomas Soome /* inflate.c -- zlib decompression 2*64c3d159SToomas Soome * Copyright (C) 1995-2022 Mark Adler 3ab9e68a2SToomas Soome * For conditions of distribution and use, see copyright notice in zlib.h 4ab9e68a2SToomas Soome */ 5ab9e68a2SToomas Soome 6ab9e68a2SToomas Soome /* 7ab9e68a2SToomas Soome * Change history: 8ab9e68a2SToomas Soome * 9ab9e68a2SToomas Soome * 1.2.beta0 24 Nov 2002 10ab9e68a2SToomas Soome * - First version -- complete rewrite of inflate to simplify code, avoid 11ab9e68a2SToomas Soome * creation of window when not needed, minimize use of window when it is 12ab9e68a2SToomas Soome * needed, make inffast.c even faster, implement gzip decoding, and to 13ab9e68a2SToomas Soome * improve code readability and style over the previous zlib inflate code 14ab9e68a2SToomas Soome * 15ab9e68a2SToomas Soome * 1.2.beta1 25 Nov 2002 16ab9e68a2SToomas Soome * - Use pointers for available input and output checking in inffast.c 17ab9e68a2SToomas Soome * - Remove input and output counters in inffast.c 18ab9e68a2SToomas Soome * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 19ab9e68a2SToomas Soome * - Remove unnecessary second byte pull from length extra in inffast.c 20ab9e68a2SToomas Soome * - Unroll direct copy to three copies per loop in inffast.c 21ab9e68a2SToomas Soome * 22ab9e68a2SToomas Soome * 1.2.beta2 4 Dec 2002 23ab9e68a2SToomas Soome * - Change external routine names to reduce potential conflicts 24ab9e68a2SToomas Soome * - Correct filename to inffixed.h for fixed tables in inflate.c 25ab9e68a2SToomas Soome * - Make hbuf[] unsigned char to match parameter type in inflate.c 26ab9e68a2SToomas Soome * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) 27ab9e68a2SToomas Soome * to avoid negation problem on Alphas (64 bit) in inflate.c 28ab9e68a2SToomas Soome * 29ab9e68a2SToomas Soome * 1.2.beta3 22 Dec 2002 30ab9e68a2SToomas Soome * - Add comments on state->bits assertion in inffast.c 31ab9e68a2SToomas Soome * - Add comments on op field in inftrees.h 32ab9e68a2SToomas Soome * - Fix bug in reuse of allocated window after inflateReset() 33ab9e68a2SToomas Soome * - Remove bit fields--back to byte structure for speed 34ab9e68a2SToomas Soome * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths 35ab9e68a2SToomas Soome * - Change post-increments to pre-increments in inflate_fast(), PPC biased? 36ab9e68a2SToomas Soome * - Add compile time option, POSTINC, to use post-increments instead (Intel?) 37ab9e68a2SToomas Soome * - Make MATCH copy in inflate() much faster for when inflate_fast() not used 38ab9e68a2SToomas Soome * - Use local copies of stream next and avail values, as well as local bit 39ab9e68a2SToomas Soome * buffer and bit count in inflate()--for speed when inflate_fast() not used 40ab9e68a2SToomas Soome * 41ab9e68a2SToomas Soome * 1.2.beta4 1 Jan 2003 42ab9e68a2SToomas Soome * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings 43ab9e68a2SToomas Soome * - Move a comment on output buffer sizes from inffast.c to inflate.c 44ab9e68a2SToomas Soome * - Add comments in inffast.c to introduce the inflate_fast() routine 45ab9e68a2SToomas Soome * - Rearrange window copies in inflate_fast() for speed and simplification 46ab9e68a2SToomas Soome * - Unroll last copy for window match in inflate_fast() 47ab9e68a2SToomas Soome * - Use local copies of window variables in inflate_fast() for speed 48ab9e68a2SToomas Soome * - Pull out common wnext == 0 case for speed in inflate_fast() 49ab9e68a2SToomas Soome * - Make op and len in inflate_fast() unsigned for consistency 50ab9e68a2SToomas Soome * - Add FAR to lcode and dcode declarations in inflate_fast() 51ab9e68a2SToomas Soome * - Simplified bad distance check in inflate_fast() 52ab9e68a2SToomas Soome * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new 53ab9e68a2SToomas Soome * source file infback.c to provide a call-back interface to inflate for 54ab9e68a2SToomas Soome * programs like gzip and unzip -- uses window as output buffer to avoid 55ab9e68a2SToomas Soome * window copying 56ab9e68a2SToomas Soome * 57ab9e68a2SToomas Soome * 1.2.beta5 1 Jan 2003 58ab9e68a2SToomas Soome * - Improved inflateBack() interface to allow the caller to provide initial 59ab9e68a2SToomas Soome * input in strm. 60ab9e68a2SToomas Soome * - Fixed stored blocks bug in inflateBack() 61ab9e68a2SToomas Soome * 62ab9e68a2SToomas Soome * 1.2.beta6 4 Jan 2003 63ab9e68a2SToomas Soome * - Added comments in inffast.c on effectiveness of POSTINC 64ab9e68a2SToomas Soome * - Typecasting all around to reduce compiler warnings 65ab9e68a2SToomas Soome * - Changed loops from while (1) or do {} while (1) to for (;;), again to 66ab9e68a2SToomas Soome * make compilers happy 67ab9e68a2SToomas Soome * - Changed type of window in inflateBackInit() to unsigned char * 68ab9e68a2SToomas Soome * 69ab9e68a2SToomas Soome * 1.2.beta7 27 Jan 2003 70ab9e68a2SToomas Soome * - Changed many types to unsigned or unsigned short to avoid warnings 71ab9e68a2SToomas Soome * - Added inflateCopy() function 72ab9e68a2SToomas Soome * 73ab9e68a2SToomas Soome * 1.2.0 9 Mar 2003 74ab9e68a2SToomas Soome * - Changed inflateBack() interface to provide separate opaque descriptors 75ab9e68a2SToomas Soome * for the in() and out() functions 76ab9e68a2SToomas Soome * - Changed inflateBack() argument and in_func typedef to swap the length 77ab9e68a2SToomas Soome * and buffer address return values for the input function 78ab9e68a2SToomas Soome * - Check next_in and next_out for Z_NULL on entry to inflate() 79ab9e68a2SToomas Soome * 80ab9e68a2SToomas Soome * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. 81ab9e68a2SToomas Soome */ 82ab9e68a2SToomas Soome 83ab9e68a2SToomas Soome #include "zutil.h" 84ab9e68a2SToomas Soome #include "inftrees.h" 85ab9e68a2SToomas Soome #include "inflate.h" 86ab9e68a2SToomas Soome #include "inffast.h" 87ab9e68a2SToomas Soome 88ab9e68a2SToomas Soome #ifdef MAKEFIXED 89ab9e68a2SToomas Soome # ifndef BUILDFIXED 90ab9e68a2SToomas Soome # define BUILDFIXED 91ab9e68a2SToomas Soome # endif 92ab9e68a2SToomas Soome #endif 93ab9e68a2SToomas Soome 94ab9e68a2SToomas Soome /* function prototypes */ 95ab9e68a2SToomas Soome local int inflateStateCheck OF((z_streamp strm)); 96ab9e68a2SToomas Soome local void fixedtables OF((struct inflate_state FAR *state)); 97ab9e68a2SToomas Soome local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, 98ab9e68a2SToomas Soome unsigned copy)); 99ab9e68a2SToomas Soome #ifdef BUILDFIXED 100ab9e68a2SToomas Soome void makefixed OF((void)); 101ab9e68a2SToomas Soome #endif 102ab9e68a2SToomas Soome local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, 103ab9e68a2SToomas Soome unsigned len)); 104ab9e68a2SToomas Soome 105ab9e68a2SToomas Soome local int inflateStateCheck(z_streamp strm) 106ab9e68a2SToomas Soome { 107ab9e68a2SToomas Soome struct inflate_state FAR *state; 108ab9e68a2SToomas Soome if (strm == Z_NULL || 109ab9e68a2SToomas Soome strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) 110ab9e68a2SToomas Soome return 1; 111ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 112ab9e68a2SToomas Soome if (state == Z_NULL || state->strm != strm || 113ab9e68a2SToomas Soome state->mode < HEAD || state->mode > SYNC) 114ab9e68a2SToomas Soome return 1; 115ab9e68a2SToomas Soome return 0; 116ab9e68a2SToomas Soome } 117ab9e68a2SToomas Soome 118ab9e68a2SToomas Soome int ZEXPORT inflateResetKeep(z_streamp strm) 119ab9e68a2SToomas Soome { 120ab9e68a2SToomas Soome struct inflate_state FAR *state; 121ab9e68a2SToomas Soome 122ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 123ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 124ab9e68a2SToomas Soome strm->total_in = strm->total_out = state->total = 0; 125ab9e68a2SToomas Soome strm->msg = Z_NULL; 126ab9e68a2SToomas Soome if (state->wrap) /* to support ill-conceived Java test suite */ 127ab9e68a2SToomas Soome strm->adler = state->wrap & 1; 128ab9e68a2SToomas Soome state->mode = HEAD; 129ab9e68a2SToomas Soome state->last = 0; 130ab9e68a2SToomas Soome state->havedict = 0; 131*64c3d159SToomas Soome state->flags = -1; 132ab9e68a2SToomas Soome state->dmax = 32768U; 133ab9e68a2SToomas Soome state->head = Z_NULL; 134ab9e68a2SToomas Soome state->hold = 0; 135ab9e68a2SToomas Soome state->bits = 0; 136ab9e68a2SToomas Soome state->lencode = state->distcode = state->next = state->codes; 137ab9e68a2SToomas Soome state->sane = 1; 138ab9e68a2SToomas Soome state->back = -1; 139ab9e68a2SToomas Soome Tracev((stderr, "inflate: reset\n")); 140ab9e68a2SToomas Soome return Z_OK; 141ab9e68a2SToomas Soome } 142ab9e68a2SToomas Soome 143ab9e68a2SToomas Soome int ZEXPORT inflateReset(z_streamp strm) 144ab9e68a2SToomas Soome { 145ab9e68a2SToomas Soome struct inflate_state FAR *state; 146ab9e68a2SToomas Soome 147ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 148ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 149ab9e68a2SToomas Soome state->wsize = 0; 150ab9e68a2SToomas Soome state->whave = 0; 151ab9e68a2SToomas Soome state->wnext = 0; 152ab9e68a2SToomas Soome return inflateResetKeep(strm); 153ab9e68a2SToomas Soome } 154ab9e68a2SToomas Soome 155ab9e68a2SToomas Soome int ZEXPORT inflateReset2(z_streamp strm, int windowBits) 156ab9e68a2SToomas Soome { 157ab9e68a2SToomas Soome int wrap; 158ab9e68a2SToomas Soome struct inflate_state FAR *state; 159ab9e68a2SToomas Soome 160ab9e68a2SToomas Soome /* get the state */ 161ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 162ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 163ab9e68a2SToomas Soome 164ab9e68a2SToomas Soome /* extract wrap request from windowBits parameter */ 165ab9e68a2SToomas Soome if (windowBits < 0) { 166ab9e68a2SToomas Soome wrap = 0; 167ab9e68a2SToomas Soome windowBits = -windowBits; 168ab9e68a2SToomas Soome } 169ab9e68a2SToomas Soome else { 170ab9e68a2SToomas Soome wrap = (windowBits >> 4) + 5; 171ab9e68a2SToomas Soome #ifdef GUNZIP 172ab9e68a2SToomas Soome if (windowBits < 48) 173ab9e68a2SToomas Soome windowBits &= 15; 174ab9e68a2SToomas Soome #endif 175ab9e68a2SToomas Soome } 176ab9e68a2SToomas Soome 177ab9e68a2SToomas Soome /* set number of window bits, free window if different */ 178ab9e68a2SToomas Soome if (windowBits && (windowBits < 8 || windowBits > 15)) 179ab9e68a2SToomas Soome return Z_STREAM_ERROR; 180ab9e68a2SToomas Soome if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { 181ab9e68a2SToomas Soome ZFREE(strm, state->window); 182ab9e68a2SToomas Soome state->window = Z_NULL; 183ab9e68a2SToomas Soome } 184ab9e68a2SToomas Soome 185ab9e68a2SToomas Soome /* update state and reset the rest of it */ 186ab9e68a2SToomas Soome state->wrap = wrap; 187ab9e68a2SToomas Soome state->wbits = (unsigned)windowBits; 188ab9e68a2SToomas Soome return inflateReset(strm); 189ab9e68a2SToomas Soome } 190ab9e68a2SToomas Soome 191ab9e68a2SToomas Soome int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, 192ab9e68a2SToomas Soome int stream_size) 193ab9e68a2SToomas Soome { 194ab9e68a2SToomas Soome int ret; 195ab9e68a2SToomas Soome struct inflate_state FAR *state; 196ab9e68a2SToomas Soome 197ab9e68a2SToomas Soome if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || 198ab9e68a2SToomas Soome stream_size != (int)(sizeof(z_stream))) 199ab9e68a2SToomas Soome return Z_VERSION_ERROR; 200ab9e68a2SToomas Soome if (strm == Z_NULL) return Z_STREAM_ERROR; 201ab9e68a2SToomas Soome strm->msg = Z_NULL; /* in case we return an error */ 202ab9e68a2SToomas Soome if (strm->zalloc == (alloc_func)0) { 203ab9e68a2SToomas Soome #ifdef Z_SOLO 204ab9e68a2SToomas Soome return Z_STREAM_ERROR; 205ab9e68a2SToomas Soome #else 206ab9e68a2SToomas Soome strm->zalloc = zcalloc; 207ab9e68a2SToomas Soome strm->opaque = (voidpf)0; 208ab9e68a2SToomas Soome #endif 209ab9e68a2SToomas Soome } 210ab9e68a2SToomas Soome if (strm->zfree == (free_func)0) 211ab9e68a2SToomas Soome #ifdef Z_SOLO 212ab9e68a2SToomas Soome return Z_STREAM_ERROR; 213ab9e68a2SToomas Soome #else 214ab9e68a2SToomas Soome strm->zfree = zcfree; 215ab9e68a2SToomas Soome #endif 216ab9e68a2SToomas Soome state = (struct inflate_state FAR *) 217ab9e68a2SToomas Soome ZALLOC(strm, 1, sizeof(struct inflate_state)); 218ab9e68a2SToomas Soome if (state == Z_NULL) return Z_MEM_ERROR; 219ab9e68a2SToomas Soome Tracev((stderr, "inflate: allocated\n")); 220ab9e68a2SToomas Soome strm->state = (struct internal_state FAR *)state; 221ab9e68a2SToomas Soome state->strm = strm; 222ab9e68a2SToomas Soome state->window = Z_NULL; 223ab9e68a2SToomas Soome state->mode = HEAD; /* to pass state test in inflateReset2() */ 224ab9e68a2SToomas Soome ret = inflateReset2(strm, windowBits); 225ab9e68a2SToomas Soome if (ret != Z_OK) { 226ab9e68a2SToomas Soome ZFREE(strm, state); 227ab9e68a2SToomas Soome strm->state = Z_NULL; 228ab9e68a2SToomas Soome } 229ab9e68a2SToomas Soome return ret; 230ab9e68a2SToomas Soome } 231ab9e68a2SToomas Soome 232ab9e68a2SToomas Soome int ZEXPORT inflateInit_(z_streamp strm, const char *version, int stream_size) 233ab9e68a2SToomas Soome { 234ab9e68a2SToomas Soome return inflateInit2_(strm, DEF_WBITS, version, stream_size); 235ab9e68a2SToomas Soome } 236ab9e68a2SToomas Soome 237ab9e68a2SToomas Soome int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) 238ab9e68a2SToomas Soome { 239ab9e68a2SToomas Soome struct inflate_state FAR *state; 240ab9e68a2SToomas Soome 241ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 242ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 243ab9e68a2SToomas Soome if (bits < 0) { 244ab9e68a2SToomas Soome state->hold = 0; 245ab9e68a2SToomas Soome state->bits = 0; 246ab9e68a2SToomas Soome return Z_OK; 247ab9e68a2SToomas Soome } 248ab9e68a2SToomas Soome if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; 249ab9e68a2SToomas Soome value &= (1L << bits) - 1; 250ab9e68a2SToomas Soome state->hold += (unsigned)value << state->bits; 251ab9e68a2SToomas Soome state->bits += (uInt)bits; 252ab9e68a2SToomas Soome return Z_OK; 253ab9e68a2SToomas Soome } 254ab9e68a2SToomas Soome 255ab9e68a2SToomas Soome /* 256ab9e68a2SToomas Soome Return state with length and distance decoding tables and index sizes set to 257ab9e68a2SToomas Soome fixed code decoding. Normally this returns fixed tables from inffixed.h. 258ab9e68a2SToomas Soome If BUILDFIXED is defined, then instead this routine builds the tables the 259ab9e68a2SToomas Soome first time it's called, and returns those tables the first time and 260ab9e68a2SToomas Soome thereafter. This reduces the size of the code by about 2K bytes, in 261ab9e68a2SToomas Soome exchange for a little execution time. However, BUILDFIXED should not be 262ab9e68a2SToomas Soome used for threaded applications, since the rewriting of the tables and virgin 263ab9e68a2SToomas Soome may not be thread-safe. 264ab9e68a2SToomas Soome */ 265ab9e68a2SToomas Soome local void fixedtables(struct inflate_state FAR *state) 266ab9e68a2SToomas Soome { 267ab9e68a2SToomas Soome #ifdef BUILDFIXED 268ab9e68a2SToomas Soome static int virgin = 1; 269ab9e68a2SToomas Soome static code *lenfix, *distfix; 270ab9e68a2SToomas Soome static code fixed[544]; 271ab9e68a2SToomas Soome 272ab9e68a2SToomas Soome /* build fixed huffman tables if first call (may not be thread safe) */ 273ab9e68a2SToomas Soome if (virgin) { 274ab9e68a2SToomas Soome unsigned sym, bits; 275ab9e68a2SToomas Soome static code *next; 276ab9e68a2SToomas Soome 277ab9e68a2SToomas Soome /* literal/length table */ 278ab9e68a2SToomas Soome sym = 0; 279ab9e68a2SToomas Soome while (sym < 144) state->lens[sym++] = 8; 280ab9e68a2SToomas Soome while (sym < 256) state->lens[sym++] = 9; 281ab9e68a2SToomas Soome while (sym < 280) state->lens[sym++] = 7; 282ab9e68a2SToomas Soome while (sym < 288) state->lens[sym++] = 8; 283ab9e68a2SToomas Soome next = fixed; 284ab9e68a2SToomas Soome lenfix = next; 285ab9e68a2SToomas Soome bits = 9; 286ab9e68a2SToomas Soome inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); 287ab9e68a2SToomas Soome 288ab9e68a2SToomas Soome /* distance table */ 289ab9e68a2SToomas Soome sym = 0; 290ab9e68a2SToomas Soome while (sym < 32) state->lens[sym++] = 5; 291ab9e68a2SToomas Soome distfix = next; 292ab9e68a2SToomas Soome bits = 5; 293ab9e68a2SToomas Soome inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); 294ab9e68a2SToomas Soome 295ab9e68a2SToomas Soome /* do this just once */ 296ab9e68a2SToomas Soome virgin = 0; 297ab9e68a2SToomas Soome } 298ab9e68a2SToomas Soome #else /* !BUILDFIXED */ 299ab9e68a2SToomas Soome # include "inffixed.h" 300ab9e68a2SToomas Soome #endif /* BUILDFIXED */ 301ab9e68a2SToomas Soome state->lencode = lenfix; 302ab9e68a2SToomas Soome state->lenbits = 9; 303ab9e68a2SToomas Soome state->distcode = distfix; 304ab9e68a2SToomas Soome state->distbits = 5; 305ab9e68a2SToomas Soome } 306ab9e68a2SToomas Soome 307ab9e68a2SToomas Soome #ifdef MAKEFIXED 308ab9e68a2SToomas Soome #include <stdio.h> 309ab9e68a2SToomas Soome 310ab9e68a2SToomas Soome /* 311ab9e68a2SToomas Soome Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also 312ab9e68a2SToomas Soome defines BUILDFIXED, so the tables are built on the fly. makefixed() writes 313ab9e68a2SToomas Soome those tables to stdout, which would be piped to inffixed.h. A small program 314ab9e68a2SToomas Soome can simply call makefixed to do this: 315ab9e68a2SToomas Soome 316ab9e68a2SToomas Soome void makefixed(void); 317ab9e68a2SToomas Soome 318ab9e68a2SToomas Soome int main(void) 319ab9e68a2SToomas Soome { 320ab9e68a2SToomas Soome makefixed(); 321ab9e68a2SToomas Soome return 0; 322ab9e68a2SToomas Soome } 323ab9e68a2SToomas Soome 324ab9e68a2SToomas Soome Then that can be linked with zlib built with MAKEFIXED defined and run: 325ab9e68a2SToomas Soome 326ab9e68a2SToomas Soome a.out > inffixed.h 327ab9e68a2SToomas Soome */ 328ab9e68a2SToomas Soome void makefixed(void) 329ab9e68a2SToomas Soome { 330ab9e68a2SToomas Soome unsigned low, size; 331ab9e68a2SToomas Soome struct inflate_state state; 332ab9e68a2SToomas Soome 333ab9e68a2SToomas Soome fixedtables(&state); 334ab9e68a2SToomas Soome puts(" /* inffixed.h -- table for decoding fixed codes"); 335ab9e68a2SToomas Soome puts(" * Generated automatically by makefixed()."); 336ab9e68a2SToomas Soome puts(" */"); 337ab9e68a2SToomas Soome puts(""); 338ab9e68a2SToomas Soome puts(" /* WARNING: this file should *not* be used by applications."); 339ab9e68a2SToomas Soome puts(" It is part of the implementation of this library and is"); 340ab9e68a2SToomas Soome puts(" subject to change. Applications should only use zlib.h."); 341ab9e68a2SToomas Soome puts(" */"); 342ab9e68a2SToomas Soome puts(""); 343ab9e68a2SToomas Soome size = 1U << 9; 344ab9e68a2SToomas Soome printf(" static const code lenfix[%u] = {", size); 345ab9e68a2SToomas Soome low = 0; 346ab9e68a2SToomas Soome for (;;) { 347ab9e68a2SToomas Soome if ((low % 7) == 0) printf("\n "); 348ab9e68a2SToomas Soome printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, 349ab9e68a2SToomas Soome state.lencode[low].bits, state.lencode[low].val); 350ab9e68a2SToomas Soome if (++low == size) break; 351ab9e68a2SToomas Soome putchar(','); 352ab9e68a2SToomas Soome } 353ab9e68a2SToomas Soome puts("\n };"); 354ab9e68a2SToomas Soome size = 1U << 5; 355ab9e68a2SToomas Soome printf("\n static const code distfix[%u] = {", size); 356ab9e68a2SToomas Soome low = 0; 357ab9e68a2SToomas Soome for (;;) { 358ab9e68a2SToomas Soome if ((low % 6) == 0) printf("\n "); 359ab9e68a2SToomas Soome printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, 360ab9e68a2SToomas Soome state.distcode[low].val); 361ab9e68a2SToomas Soome if (++low == size) break; 362ab9e68a2SToomas Soome putchar(','); 363ab9e68a2SToomas Soome } 364ab9e68a2SToomas Soome puts("\n };"); 365ab9e68a2SToomas Soome } 366ab9e68a2SToomas Soome #endif /* MAKEFIXED */ 367ab9e68a2SToomas Soome 368ab9e68a2SToomas Soome /* 369ab9e68a2SToomas Soome Update the window with the last wsize (normally 32K) bytes written before 370ab9e68a2SToomas Soome returning. If window does not exist yet, create it. This is only called 371ab9e68a2SToomas Soome when a window is already in use, or when output has been written during this 372ab9e68a2SToomas Soome inflate call, but the end of the deflate stream has not been reached yet. 373ab9e68a2SToomas Soome It is also called to create a window for dictionary data when a dictionary 374ab9e68a2SToomas Soome is loaded. 375ab9e68a2SToomas Soome 376ab9e68a2SToomas Soome Providing output buffers larger than 32K to inflate() should provide a speed 377ab9e68a2SToomas Soome advantage, since only the last 32K of output is copied to the sliding window 378ab9e68a2SToomas Soome upon return from inflate(), and since all distances after the first 32K of 379ab9e68a2SToomas Soome output will fall in the output data, making match copies simpler and faster. 380ab9e68a2SToomas Soome The advantage may be dependent on the size of the processor's data caches. 381ab9e68a2SToomas Soome */ 382ab9e68a2SToomas Soome local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy) 383ab9e68a2SToomas Soome { 384ab9e68a2SToomas Soome struct inflate_state FAR *state; 385ab9e68a2SToomas Soome unsigned dist; 386ab9e68a2SToomas Soome 387ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 388ab9e68a2SToomas Soome 389ab9e68a2SToomas Soome /* if it hasn't been done already, allocate space for the window */ 390ab9e68a2SToomas Soome if (state->window == Z_NULL) { 391ab9e68a2SToomas Soome state->window = (unsigned char FAR *) 392ab9e68a2SToomas Soome ZALLOC(strm, 1U << state->wbits, 393ab9e68a2SToomas Soome sizeof(unsigned char)); 394ab9e68a2SToomas Soome if (state->window == Z_NULL) return 1; 395ab9e68a2SToomas Soome } 396ab9e68a2SToomas Soome 397ab9e68a2SToomas Soome /* if window not in use yet, initialize */ 398ab9e68a2SToomas Soome if (state->wsize == 0) { 399ab9e68a2SToomas Soome state->wsize = 1U << state->wbits; 400ab9e68a2SToomas Soome state->wnext = 0; 401ab9e68a2SToomas Soome state->whave = 0; 402ab9e68a2SToomas Soome } 403ab9e68a2SToomas Soome 404ab9e68a2SToomas Soome /* copy state->wsize or less output bytes into the circular window */ 405ab9e68a2SToomas Soome if (copy >= state->wsize) { 406ab9e68a2SToomas Soome zmemcpy(state->window, end - state->wsize, state->wsize); 407ab9e68a2SToomas Soome state->wnext = 0; 408ab9e68a2SToomas Soome state->whave = state->wsize; 409ab9e68a2SToomas Soome } 410ab9e68a2SToomas Soome else { 411ab9e68a2SToomas Soome dist = state->wsize - state->wnext; 412ab9e68a2SToomas Soome if (dist > copy) dist = copy; 413ab9e68a2SToomas Soome zmemcpy(state->window + state->wnext, end - copy, dist); 414ab9e68a2SToomas Soome copy -= dist; 415ab9e68a2SToomas Soome if (copy) { 416ab9e68a2SToomas Soome zmemcpy(state->window, end - copy, copy); 417ab9e68a2SToomas Soome state->wnext = copy; 418ab9e68a2SToomas Soome state->whave = state->wsize; 419ab9e68a2SToomas Soome } 420ab9e68a2SToomas Soome else { 421ab9e68a2SToomas Soome state->wnext += dist; 422ab9e68a2SToomas Soome if (state->wnext == state->wsize) state->wnext = 0; 423ab9e68a2SToomas Soome if (state->whave < state->wsize) state->whave += dist; 424ab9e68a2SToomas Soome } 425ab9e68a2SToomas Soome } 426ab9e68a2SToomas Soome return 0; 427ab9e68a2SToomas Soome } 428ab9e68a2SToomas Soome 429ab9e68a2SToomas Soome /* Macros for inflate(): */ 430ab9e68a2SToomas Soome 431ab9e68a2SToomas Soome /* check function to use adler32() for zlib or crc32() for gzip */ 432ab9e68a2SToomas Soome #ifdef GUNZIP 433*64c3d159SToomas Soome # define UPDATE_CHECK(check, buf, len) \ 434ab9e68a2SToomas Soome (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) 435ab9e68a2SToomas Soome #else 436*64c3d159SToomas Soome # define UPDATE_CHECK(check, buf, len) adler32(check, buf, len) 437ab9e68a2SToomas Soome #endif 438ab9e68a2SToomas Soome 439ab9e68a2SToomas Soome /* check macros for header crc */ 440ab9e68a2SToomas Soome #ifdef GUNZIP 441ab9e68a2SToomas Soome # define CRC2(check, word) \ 442ab9e68a2SToomas Soome do { \ 443ab9e68a2SToomas Soome hbuf[0] = (unsigned char)(word); \ 444ab9e68a2SToomas Soome hbuf[1] = (unsigned char)((word) >> 8); \ 445ab9e68a2SToomas Soome check = crc32(check, hbuf, 2); \ 446ab9e68a2SToomas Soome } while (0) 447ab9e68a2SToomas Soome 448ab9e68a2SToomas Soome # define CRC4(check, word) \ 449ab9e68a2SToomas Soome do { \ 450ab9e68a2SToomas Soome hbuf[0] = (unsigned char)(word); \ 451ab9e68a2SToomas Soome hbuf[1] = (unsigned char)((word) >> 8); \ 452ab9e68a2SToomas Soome hbuf[2] = (unsigned char)((word) >> 16); \ 453ab9e68a2SToomas Soome hbuf[3] = (unsigned char)((word) >> 24); \ 454ab9e68a2SToomas Soome check = crc32(check, hbuf, 4); \ 455ab9e68a2SToomas Soome } while (0) 456ab9e68a2SToomas Soome #endif 457ab9e68a2SToomas Soome 458ab9e68a2SToomas Soome /* Load registers with state in inflate() for speed */ 459ab9e68a2SToomas Soome #define LOAD() \ 460ab9e68a2SToomas Soome do { \ 461ab9e68a2SToomas Soome put = strm->next_out; \ 462ab9e68a2SToomas Soome left = strm->avail_out; \ 463ab9e68a2SToomas Soome next = strm->next_in; \ 464ab9e68a2SToomas Soome have = strm->avail_in; \ 465ab9e68a2SToomas Soome hold = state->hold; \ 466ab9e68a2SToomas Soome bits = state->bits; \ 467ab9e68a2SToomas Soome } while (0) 468ab9e68a2SToomas Soome 469ab9e68a2SToomas Soome /* Restore state from registers in inflate() */ 470ab9e68a2SToomas Soome #define RESTORE() \ 471ab9e68a2SToomas Soome do { \ 472ab9e68a2SToomas Soome strm->next_out = put; \ 473ab9e68a2SToomas Soome strm->avail_out = left; \ 474ab9e68a2SToomas Soome strm->next_in = next; \ 475ab9e68a2SToomas Soome strm->avail_in = have; \ 476ab9e68a2SToomas Soome state->hold = hold; \ 477ab9e68a2SToomas Soome state->bits = bits; \ 478ab9e68a2SToomas Soome } while (0) 479ab9e68a2SToomas Soome 480ab9e68a2SToomas Soome /* Clear the input bit accumulator */ 481ab9e68a2SToomas Soome #define INITBITS() \ 482ab9e68a2SToomas Soome do { \ 483ab9e68a2SToomas Soome hold = 0; \ 484ab9e68a2SToomas Soome bits = 0; \ 485ab9e68a2SToomas Soome } while (0) 486ab9e68a2SToomas Soome 487ab9e68a2SToomas Soome /* Get a byte of input into the bit accumulator, or return from inflate() 488ab9e68a2SToomas Soome if there is no input available. */ 489ab9e68a2SToomas Soome #define PULLBYTE() \ 490ab9e68a2SToomas Soome do { \ 491ab9e68a2SToomas Soome if (have == 0) goto inf_leave; \ 492ab9e68a2SToomas Soome have--; \ 493ab9e68a2SToomas Soome hold += (unsigned long)(*next++) << bits; \ 494ab9e68a2SToomas Soome bits += 8; \ 495ab9e68a2SToomas Soome } while (0) 496ab9e68a2SToomas Soome 497ab9e68a2SToomas Soome /* Assure that there are at least n bits in the bit accumulator. If there is 498ab9e68a2SToomas Soome not enough available input to do that, then return from inflate(). */ 499ab9e68a2SToomas Soome #define NEEDBITS(n) \ 500ab9e68a2SToomas Soome do { \ 501ab9e68a2SToomas Soome while (bits < (unsigned)(n)) \ 502ab9e68a2SToomas Soome PULLBYTE(); \ 503ab9e68a2SToomas Soome } while (0) 504ab9e68a2SToomas Soome 505ab9e68a2SToomas Soome /* Return the low n bits of the bit accumulator (n < 16) */ 506ab9e68a2SToomas Soome #define BITS(n) \ 507ab9e68a2SToomas Soome ((unsigned)hold & ((1U << (n)) - 1)) 508ab9e68a2SToomas Soome 509ab9e68a2SToomas Soome /* Remove n bits from the bit accumulator */ 510ab9e68a2SToomas Soome #define DROPBITS(n) \ 511ab9e68a2SToomas Soome do { \ 512ab9e68a2SToomas Soome hold >>= (n); \ 513ab9e68a2SToomas Soome bits -= (unsigned)(n); \ 514ab9e68a2SToomas Soome } while (0) 515ab9e68a2SToomas Soome 516ab9e68a2SToomas Soome /* Remove zero to seven bits as needed to go to a byte boundary */ 517ab9e68a2SToomas Soome #define BYTEBITS() \ 518ab9e68a2SToomas Soome do { \ 519ab9e68a2SToomas Soome hold >>= bits & 7; \ 520ab9e68a2SToomas Soome bits -= bits & 7; \ 521ab9e68a2SToomas Soome } while (0) 522ab9e68a2SToomas Soome 523ab9e68a2SToomas Soome /* 524ab9e68a2SToomas Soome inflate() uses a state machine to process as much input data and generate as 525ab9e68a2SToomas Soome much output data as possible before returning. The state machine is 526ab9e68a2SToomas Soome structured roughly as follows: 527ab9e68a2SToomas Soome 528ab9e68a2SToomas Soome for (;;) switch (state) { 529ab9e68a2SToomas Soome ... 530ab9e68a2SToomas Soome case STATEn: 531ab9e68a2SToomas Soome if (not enough input data or output space to make progress) 532ab9e68a2SToomas Soome return; 533ab9e68a2SToomas Soome ... make progress ... 534ab9e68a2SToomas Soome state = STATEm; 535ab9e68a2SToomas Soome break; 536ab9e68a2SToomas Soome ... 537ab9e68a2SToomas Soome } 538ab9e68a2SToomas Soome 539ab9e68a2SToomas Soome so when inflate() is called again, the same case is attempted again, and 540ab9e68a2SToomas Soome if the appropriate resources are provided, the machine proceeds to the 541ab9e68a2SToomas Soome next state. The NEEDBITS() macro is usually the way the state evaluates 542ab9e68a2SToomas Soome whether it can proceed or should return. NEEDBITS() does the return if 543ab9e68a2SToomas Soome the requested bits are not available. The typical use of the BITS macros 544ab9e68a2SToomas Soome is: 545ab9e68a2SToomas Soome 546ab9e68a2SToomas Soome NEEDBITS(n); 547ab9e68a2SToomas Soome ... do something with BITS(n) ... 548ab9e68a2SToomas Soome DROPBITS(n); 549ab9e68a2SToomas Soome 550ab9e68a2SToomas Soome where NEEDBITS(n) either returns from inflate() if there isn't enough 551ab9e68a2SToomas Soome input left to load n bits into the accumulator, or it continues. BITS(n) 552ab9e68a2SToomas Soome gives the low n bits in the accumulator. When done, DROPBITS(n) drops 553ab9e68a2SToomas Soome the low n bits off the accumulator. INITBITS() clears the accumulator 554ab9e68a2SToomas Soome and sets the number of available bits to zero. BYTEBITS() discards just 555ab9e68a2SToomas Soome enough bits to put the accumulator on a byte boundary. After BYTEBITS() 556ab9e68a2SToomas Soome and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. 557ab9e68a2SToomas Soome 558ab9e68a2SToomas Soome NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return 559ab9e68a2SToomas Soome if there is no input available. The decoding of variable length codes uses 560ab9e68a2SToomas Soome PULLBYTE() directly in order to pull just enough bytes to decode the next 561ab9e68a2SToomas Soome code, and no more. 562ab9e68a2SToomas Soome 563ab9e68a2SToomas Soome Some states loop until they get enough input, making sure that enough 564ab9e68a2SToomas Soome state information is maintained to continue the loop where it left off 565ab9e68a2SToomas Soome if NEEDBITS() returns in the loop. For example, want, need, and keep 566ab9e68a2SToomas Soome would all have to actually be part of the saved state in case NEEDBITS() 567ab9e68a2SToomas Soome returns: 568ab9e68a2SToomas Soome 569ab9e68a2SToomas Soome case STATEw: 570ab9e68a2SToomas Soome while (want < need) { 571ab9e68a2SToomas Soome NEEDBITS(n); 572ab9e68a2SToomas Soome keep[want++] = BITS(n); 573ab9e68a2SToomas Soome DROPBITS(n); 574ab9e68a2SToomas Soome } 575ab9e68a2SToomas Soome state = STATEx; 576ab9e68a2SToomas Soome case STATEx: 577ab9e68a2SToomas Soome 578ab9e68a2SToomas Soome As shown above, if the next state is also the next case, then the break 579ab9e68a2SToomas Soome is omitted. 580ab9e68a2SToomas Soome 581ab9e68a2SToomas Soome A state may also return if there is not enough output space available to 582ab9e68a2SToomas Soome complete that state. Those states are copying stored data, writing a 583ab9e68a2SToomas Soome literal byte, and copying a matching string. 584ab9e68a2SToomas Soome 585ab9e68a2SToomas Soome When returning, a "goto inf_leave" is used to update the total counters, 586ab9e68a2SToomas Soome update the check value, and determine whether any progress has been made 587ab9e68a2SToomas Soome during that inflate() call in order to return the proper return code. 588ab9e68a2SToomas Soome Progress is defined as a change in either strm->avail_in or strm->avail_out. 589ab9e68a2SToomas Soome When there is a window, goto inf_leave will update the window with the last 590ab9e68a2SToomas Soome output written. If a goto inf_leave occurs in the middle of decompression 591ab9e68a2SToomas Soome and there is no window currently, goto inf_leave will create one and copy 592ab9e68a2SToomas Soome output to the window for the next call of inflate(). 593ab9e68a2SToomas Soome 594ab9e68a2SToomas Soome In this implementation, the flush parameter of inflate() only affects the 595ab9e68a2SToomas Soome return code (per zlib.h). inflate() always writes as much as possible to 596ab9e68a2SToomas Soome strm->next_out, given the space available and the provided input--the effect 597ab9e68a2SToomas Soome documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers 598ab9e68a2SToomas Soome the allocation of and copying into a sliding window until necessary, which 599ab9e68a2SToomas Soome provides the effect documented in zlib.h for Z_FINISH when the entire input 600ab9e68a2SToomas Soome stream available. So the only thing the flush parameter actually does is: 601ab9e68a2SToomas Soome when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it 602ab9e68a2SToomas Soome will return Z_BUF_ERROR if it has not reached the end of the stream. 603ab9e68a2SToomas Soome */ 604ab9e68a2SToomas Soome 605ab9e68a2SToomas Soome int ZEXPORT inflate(z_streamp strm, int flush) 606ab9e68a2SToomas Soome { 607ab9e68a2SToomas Soome struct inflate_state FAR *state; 608ab9e68a2SToomas Soome z_const unsigned char FAR *next; /* next input */ 609ab9e68a2SToomas Soome unsigned char FAR *put; /* next output */ 610ab9e68a2SToomas Soome unsigned have, left; /* available input and output */ 611ab9e68a2SToomas Soome unsigned long hold; /* bit buffer */ 612ab9e68a2SToomas Soome unsigned bits; /* bits in bit buffer */ 613ab9e68a2SToomas Soome unsigned in, out; /* save starting available input and output */ 614ab9e68a2SToomas Soome unsigned copy; /* number of stored or match bytes to copy */ 615ab9e68a2SToomas Soome unsigned char FAR *from; /* where to copy match bytes from */ 616ab9e68a2SToomas Soome code here; /* current decoding table entry */ 617ab9e68a2SToomas Soome code last; /* parent table entry */ 618ab9e68a2SToomas Soome unsigned len; /* length to copy for repeats, bits to drop */ 619ab9e68a2SToomas Soome int ret; /* return code */ 620ab9e68a2SToomas Soome #ifdef GUNZIP 621ab9e68a2SToomas Soome unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ 622ab9e68a2SToomas Soome #endif 623ab9e68a2SToomas Soome static const unsigned short order[19] = /* permutation of code lengths */ 624ab9e68a2SToomas Soome {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; 625ab9e68a2SToomas Soome 626ab9e68a2SToomas Soome if (inflateStateCheck(strm) || strm->next_out == Z_NULL || 627ab9e68a2SToomas Soome (strm->next_in == Z_NULL && strm->avail_in != 0)) 628ab9e68a2SToomas Soome return Z_STREAM_ERROR; 629ab9e68a2SToomas Soome 630ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 631ab9e68a2SToomas Soome if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ 632ab9e68a2SToomas Soome LOAD(); 633ab9e68a2SToomas Soome in = have; 634ab9e68a2SToomas Soome out = left; 635ab9e68a2SToomas Soome ret = Z_OK; 636ab9e68a2SToomas Soome for (;;) 637ab9e68a2SToomas Soome switch (state->mode) { 638ab9e68a2SToomas Soome case HEAD: 639ab9e68a2SToomas Soome if (state->wrap == 0) { 640ab9e68a2SToomas Soome state->mode = TYPEDO; 641ab9e68a2SToomas Soome break; 642ab9e68a2SToomas Soome } 643ab9e68a2SToomas Soome NEEDBITS(16); 644ab9e68a2SToomas Soome #ifdef GUNZIP 645ab9e68a2SToomas Soome if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ 646ab9e68a2SToomas Soome if (state->wbits == 0) 647ab9e68a2SToomas Soome state->wbits = 15; 648ab9e68a2SToomas Soome state->check = crc32(0L, Z_NULL, 0); 649ab9e68a2SToomas Soome CRC2(state->check, hold); 650ab9e68a2SToomas Soome INITBITS(); 651ab9e68a2SToomas Soome state->mode = FLAGS; 652ab9e68a2SToomas Soome break; 653ab9e68a2SToomas Soome } 654ab9e68a2SToomas Soome if (state->head != Z_NULL) 655ab9e68a2SToomas Soome state->head->done = -1; 656ab9e68a2SToomas Soome if (!(state->wrap & 1) || /* check if zlib header allowed */ 657ab9e68a2SToomas Soome #else 658ab9e68a2SToomas Soome if ( 659ab9e68a2SToomas Soome #endif 660ab9e68a2SToomas Soome ((BITS(8) << 8) + (hold >> 8)) % 31) { 661ab9e68a2SToomas Soome strm->msg = (char *)"incorrect header check"; 662ab9e68a2SToomas Soome state->mode = BAD; 663ab9e68a2SToomas Soome break; 664ab9e68a2SToomas Soome } 665ab9e68a2SToomas Soome if (BITS(4) != Z_DEFLATED) { 666ab9e68a2SToomas Soome strm->msg = (char *)"unknown compression method"; 667ab9e68a2SToomas Soome state->mode = BAD; 668ab9e68a2SToomas Soome break; 669ab9e68a2SToomas Soome } 670ab9e68a2SToomas Soome DROPBITS(4); 671ab9e68a2SToomas Soome len = BITS(4) + 8; 672ab9e68a2SToomas Soome if (state->wbits == 0) 673ab9e68a2SToomas Soome state->wbits = len; 674ab9e68a2SToomas Soome if (len > 15 || len > state->wbits) { 675ab9e68a2SToomas Soome strm->msg = (char *)"invalid window size"; 676ab9e68a2SToomas Soome state->mode = BAD; 677ab9e68a2SToomas Soome break; 678ab9e68a2SToomas Soome } 679ab9e68a2SToomas Soome state->dmax = 1U << len; 680*64c3d159SToomas Soome state->flags = 0; /* indicate zlib header */ 681ab9e68a2SToomas Soome Tracev((stderr, "inflate: zlib header ok\n")); 682ab9e68a2SToomas Soome strm->adler = state->check = adler32(0L, Z_NULL, 0); 683ab9e68a2SToomas Soome state->mode = hold & 0x200 ? DICTID : TYPE; 684ab9e68a2SToomas Soome INITBITS(); 685ab9e68a2SToomas Soome break; 686ab9e68a2SToomas Soome #ifdef GUNZIP 687ab9e68a2SToomas Soome case FLAGS: 688ab9e68a2SToomas Soome NEEDBITS(16); 689ab9e68a2SToomas Soome state->flags = (int)(hold); 690ab9e68a2SToomas Soome if ((state->flags & 0xff) != Z_DEFLATED) { 691ab9e68a2SToomas Soome strm->msg = (char *)"unknown compression method"; 692ab9e68a2SToomas Soome state->mode = BAD; 693ab9e68a2SToomas Soome break; 694ab9e68a2SToomas Soome } 695ab9e68a2SToomas Soome if (state->flags & 0xe000) { 696ab9e68a2SToomas Soome strm->msg = (char *)"unknown header flags set"; 697ab9e68a2SToomas Soome state->mode = BAD; 698ab9e68a2SToomas Soome break; 699ab9e68a2SToomas Soome } 700ab9e68a2SToomas Soome if (state->head != Z_NULL) 701ab9e68a2SToomas Soome state->head->text = (int)((hold >> 8) & 1); 702ab9e68a2SToomas Soome if ((state->flags & 0x0200) && (state->wrap & 4)) 703ab9e68a2SToomas Soome CRC2(state->check, hold); 704ab9e68a2SToomas Soome INITBITS(); 705ab9e68a2SToomas Soome state->mode = TIME; 706*64c3d159SToomas Soome /* fallthrough */ 707ab9e68a2SToomas Soome case TIME: 708ab9e68a2SToomas Soome NEEDBITS(32); 709ab9e68a2SToomas Soome if (state->head != Z_NULL) 710ab9e68a2SToomas Soome state->head->time = hold; 711ab9e68a2SToomas Soome if ((state->flags & 0x0200) && (state->wrap & 4)) 712ab9e68a2SToomas Soome CRC4(state->check, hold); 713ab9e68a2SToomas Soome INITBITS(); 714ab9e68a2SToomas Soome state->mode = OS; 715*64c3d159SToomas Soome /* fallthrough */ 716ab9e68a2SToomas Soome case OS: 717ab9e68a2SToomas Soome NEEDBITS(16); 718ab9e68a2SToomas Soome if (state->head != Z_NULL) { 719ab9e68a2SToomas Soome state->head->xflags = (int)(hold & 0xff); 720ab9e68a2SToomas Soome state->head->os = (int)(hold >> 8); 721ab9e68a2SToomas Soome } 722ab9e68a2SToomas Soome if ((state->flags & 0x0200) && (state->wrap & 4)) 723ab9e68a2SToomas Soome CRC2(state->check, hold); 724ab9e68a2SToomas Soome INITBITS(); 725ab9e68a2SToomas Soome state->mode = EXLEN; 726ab9e68a2SToomas Soome /* FALLTHROUGH */ 727ab9e68a2SToomas Soome case EXLEN: 728ab9e68a2SToomas Soome if (state->flags & 0x0400) { 729ab9e68a2SToomas Soome NEEDBITS(16); 730ab9e68a2SToomas Soome state->length = (unsigned)(hold); 731ab9e68a2SToomas Soome if (state->head != Z_NULL) 732ab9e68a2SToomas Soome state->head->extra_len = (unsigned)hold; 733ab9e68a2SToomas Soome if ((state->flags & 0x0200) && (state->wrap & 4)) 734ab9e68a2SToomas Soome CRC2(state->check, hold); 735ab9e68a2SToomas Soome INITBITS(); 736ab9e68a2SToomas Soome } 737ab9e68a2SToomas Soome else if (state->head != Z_NULL) 738ab9e68a2SToomas Soome state->head->extra = Z_NULL; 739ab9e68a2SToomas Soome state->mode = EXTRA; 740ab9e68a2SToomas Soome /* FALLTHROUGH */ 741ab9e68a2SToomas Soome case EXTRA: 742ab9e68a2SToomas Soome if (state->flags & 0x0400) { 743ab9e68a2SToomas Soome copy = state->length; 744ab9e68a2SToomas Soome if (copy > have) copy = have; 745ab9e68a2SToomas Soome if (copy) { 746ab9e68a2SToomas Soome if (state->head != Z_NULL && 747ab9e68a2SToomas Soome state->head->extra != Z_NULL) { 748ab9e68a2SToomas Soome len = state->head->extra_len - state->length; 749ab9e68a2SToomas Soome zmemcpy(state->head->extra + len, next, 750ab9e68a2SToomas Soome len + copy > state->head->extra_max ? 751ab9e68a2SToomas Soome state->head->extra_max - len : copy); 752ab9e68a2SToomas Soome } 753ab9e68a2SToomas Soome if ((state->flags & 0x0200) && (state->wrap & 4)) 754ab9e68a2SToomas Soome state->check = crc32(state->check, next, copy); 755ab9e68a2SToomas Soome have -= copy; 756ab9e68a2SToomas Soome next += copy; 757ab9e68a2SToomas Soome state->length -= copy; 758ab9e68a2SToomas Soome } 759ab9e68a2SToomas Soome if (state->length) goto inf_leave; 760ab9e68a2SToomas Soome } 761ab9e68a2SToomas Soome state->length = 0; 762ab9e68a2SToomas Soome state->mode = NAME; 763ab9e68a2SToomas Soome /* FALLTHROUGH */ 764ab9e68a2SToomas Soome case NAME: 765ab9e68a2SToomas Soome if (state->flags & 0x0800) { 766ab9e68a2SToomas Soome if (have == 0) goto inf_leave; 767ab9e68a2SToomas Soome copy = 0; 768ab9e68a2SToomas Soome do { 769ab9e68a2SToomas Soome len = (unsigned)(next[copy++]); 770ab9e68a2SToomas Soome if (state->head != Z_NULL && 771ab9e68a2SToomas Soome state->head->name != Z_NULL && 772ab9e68a2SToomas Soome state->length < state->head->name_max) 773ab9e68a2SToomas Soome state->head->name[state->length++] = (Bytef)len; 774ab9e68a2SToomas Soome } while (len && copy < have); 775ab9e68a2SToomas Soome if ((state->flags & 0x0200) && (state->wrap & 4)) 776ab9e68a2SToomas Soome state->check = crc32(state->check, next, copy); 777ab9e68a2SToomas Soome have -= copy; 778ab9e68a2SToomas Soome next += copy; 779ab9e68a2SToomas Soome if (len) goto inf_leave; 780ab9e68a2SToomas Soome } 781ab9e68a2SToomas Soome else if (state->head != Z_NULL) 782ab9e68a2SToomas Soome state->head->name = Z_NULL; 783ab9e68a2SToomas Soome state->length = 0; 784ab9e68a2SToomas Soome state->mode = COMMENT; 785ab9e68a2SToomas Soome /* FALLTHROUGH */ 786ab9e68a2SToomas Soome case COMMENT: 787ab9e68a2SToomas Soome if (state->flags & 0x1000) { 788ab9e68a2SToomas Soome if (have == 0) goto inf_leave; 789ab9e68a2SToomas Soome copy = 0; 790ab9e68a2SToomas Soome do { 791ab9e68a2SToomas Soome len = (unsigned)(next[copy++]); 792ab9e68a2SToomas Soome if (state->head != Z_NULL && 793ab9e68a2SToomas Soome state->head->comment != Z_NULL && 794ab9e68a2SToomas Soome state->length < state->head->comm_max) 795ab9e68a2SToomas Soome state->head->comment[state->length++] = (Bytef)len; 796ab9e68a2SToomas Soome } while (len && copy < have); 797ab9e68a2SToomas Soome if ((state->flags & 0x0200) && (state->wrap & 4)) 798ab9e68a2SToomas Soome state->check = crc32(state->check, next, copy); 799ab9e68a2SToomas Soome have -= copy; 800ab9e68a2SToomas Soome next += copy; 801ab9e68a2SToomas Soome if (len) goto inf_leave; 802ab9e68a2SToomas Soome } 803ab9e68a2SToomas Soome else if (state->head != Z_NULL) 804ab9e68a2SToomas Soome state->head->comment = Z_NULL; 805ab9e68a2SToomas Soome state->mode = HCRC; 806ab9e68a2SToomas Soome /* FALLTHROUGH */ 807ab9e68a2SToomas Soome case HCRC: 808ab9e68a2SToomas Soome if (state->flags & 0x0200) { 809ab9e68a2SToomas Soome NEEDBITS(16); 810ab9e68a2SToomas Soome if ((state->wrap & 4) && hold != (state->check & 0xffff)) { 811ab9e68a2SToomas Soome strm->msg = (char *)"header crc mismatch"; 812ab9e68a2SToomas Soome state->mode = BAD; 813ab9e68a2SToomas Soome break; 814ab9e68a2SToomas Soome } 815ab9e68a2SToomas Soome INITBITS(); 816ab9e68a2SToomas Soome } 817ab9e68a2SToomas Soome if (state->head != Z_NULL) { 818ab9e68a2SToomas Soome state->head->hcrc = (int)((state->flags >> 9) & 1); 819ab9e68a2SToomas Soome state->head->done = 1; 820ab9e68a2SToomas Soome } 821ab9e68a2SToomas Soome strm->adler = state->check = crc32(0L, Z_NULL, 0); 822ab9e68a2SToomas Soome state->mode = TYPE; 823ab9e68a2SToomas Soome break; 824ab9e68a2SToomas Soome #endif 825ab9e68a2SToomas Soome case DICTID: 826ab9e68a2SToomas Soome NEEDBITS(32); 827ab9e68a2SToomas Soome strm->adler = state->check = ZSWAP32(hold); 828ab9e68a2SToomas Soome INITBITS(); 829ab9e68a2SToomas Soome state->mode = DICT; 830ab9e68a2SToomas Soome /* FALLTHROUGH */ 831ab9e68a2SToomas Soome case DICT: 832ab9e68a2SToomas Soome if (state->havedict == 0) { 833ab9e68a2SToomas Soome RESTORE(); 834ab9e68a2SToomas Soome return Z_NEED_DICT; 835ab9e68a2SToomas Soome } 836ab9e68a2SToomas Soome strm->adler = state->check = adler32(0L, Z_NULL, 0); 837ab9e68a2SToomas Soome state->mode = TYPE; 838ab9e68a2SToomas Soome /* FALLTHROUGH */ 839ab9e68a2SToomas Soome case TYPE: 840ab9e68a2SToomas Soome if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; 841ab9e68a2SToomas Soome /* FALLTHROUGH */ 842ab9e68a2SToomas Soome case TYPEDO: 843ab9e68a2SToomas Soome if (state->last) { 844ab9e68a2SToomas Soome BYTEBITS(); 845ab9e68a2SToomas Soome state->mode = CHECK; 846ab9e68a2SToomas Soome break; 847ab9e68a2SToomas Soome } 848ab9e68a2SToomas Soome NEEDBITS(3); 849ab9e68a2SToomas Soome state->last = BITS(1); 850ab9e68a2SToomas Soome DROPBITS(1); 851ab9e68a2SToomas Soome switch (BITS(2)) { 852ab9e68a2SToomas Soome case 0: /* stored block */ 853ab9e68a2SToomas Soome Tracev((stderr, "inflate: stored block%s\n", 854ab9e68a2SToomas Soome state->last ? " (last)" : "")); 855ab9e68a2SToomas Soome state->mode = STORED; 856ab9e68a2SToomas Soome break; 857ab9e68a2SToomas Soome case 1: /* fixed block */ 858ab9e68a2SToomas Soome fixedtables(state); 859ab9e68a2SToomas Soome Tracev((stderr, "inflate: fixed codes block%s\n", 860ab9e68a2SToomas Soome state->last ? " (last)" : "")); 861ab9e68a2SToomas Soome state->mode = LEN_; /* decode codes */ 862ab9e68a2SToomas Soome if (flush == Z_TREES) { 863ab9e68a2SToomas Soome DROPBITS(2); 864ab9e68a2SToomas Soome goto inf_leave; 865ab9e68a2SToomas Soome } 866ab9e68a2SToomas Soome break; 867ab9e68a2SToomas Soome case 2: /* dynamic block */ 868ab9e68a2SToomas Soome Tracev((stderr, "inflate: dynamic codes block%s\n", 869ab9e68a2SToomas Soome state->last ? " (last)" : "")); 870ab9e68a2SToomas Soome state->mode = TABLE; 871ab9e68a2SToomas Soome break; 872ab9e68a2SToomas Soome case 3: 873ab9e68a2SToomas Soome strm->msg = (char *)"invalid block type"; 874ab9e68a2SToomas Soome state->mode = BAD; 875ab9e68a2SToomas Soome } 876ab9e68a2SToomas Soome DROPBITS(2); 877ab9e68a2SToomas Soome break; 878ab9e68a2SToomas Soome case STORED: 879ab9e68a2SToomas Soome BYTEBITS(); /* go to byte boundary */ 880ab9e68a2SToomas Soome NEEDBITS(32); 881ab9e68a2SToomas Soome if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { 882ab9e68a2SToomas Soome strm->msg = (char *)"invalid stored block lengths"; 883ab9e68a2SToomas Soome state->mode = BAD; 884ab9e68a2SToomas Soome break; 885ab9e68a2SToomas Soome } 886ab9e68a2SToomas Soome state->length = (unsigned)hold & 0xffff; 887ab9e68a2SToomas Soome Tracev((stderr, "inflate: stored length %u\n", 888ab9e68a2SToomas Soome state->length)); 889ab9e68a2SToomas Soome INITBITS(); 890ab9e68a2SToomas Soome state->mode = COPY_; 891ab9e68a2SToomas Soome if (flush == Z_TREES) goto inf_leave; 892ab9e68a2SToomas Soome /* FALLTHROUGH */ 893ab9e68a2SToomas Soome case COPY_: 894ab9e68a2SToomas Soome state->mode = COPY; 895ab9e68a2SToomas Soome /* FALLTHROUGH */ 896ab9e68a2SToomas Soome case COPY: 897ab9e68a2SToomas Soome copy = state->length; 898ab9e68a2SToomas Soome if (copy) { 899ab9e68a2SToomas Soome if (copy > have) copy = have; 900ab9e68a2SToomas Soome if (copy > left) copy = left; 901ab9e68a2SToomas Soome if (copy == 0) goto inf_leave; 902ab9e68a2SToomas Soome zmemcpy(put, next, copy); 903ab9e68a2SToomas Soome have -= copy; 904ab9e68a2SToomas Soome next += copy; 905ab9e68a2SToomas Soome left -= copy; 906ab9e68a2SToomas Soome put += copy; 907ab9e68a2SToomas Soome state->length -= copy; 908ab9e68a2SToomas Soome break; 909ab9e68a2SToomas Soome } 910ab9e68a2SToomas Soome Tracev((stderr, "inflate: stored end\n")); 911ab9e68a2SToomas Soome state->mode = TYPE; 912ab9e68a2SToomas Soome break; 913ab9e68a2SToomas Soome case TABLE: 914ab9e68a2SToomas Soome NEEDBITS(14); 915ab9e68a2SToomas Soome state->nlen = BITS(5) + 257; 916ab9e68a2SToomas Soome DROPBITS(5); 917ab9e68a2SToomas Soome state->ndist = BITS(5) + 1; 918ab9e68a2SToomas Soome DROPBITS(5); 919ab9e68a2SToomas Soome state->ncode = BITS(4) + 4; 920ab9e68a2SToomas Soome DROPBITS(4); 921ab9e68a2SToomas Soome #ifndef PKZIP_BUG_WORKAROUND 922ab9e68a2SToomas Soome if (state->nlen > 286 || state->ndist > 30) { 923ab9e68a2SToomas Soome strm->msg = (char *)"too many length or distance symbols"; 924ab9e68a2SToomas Soome state->mode = BAD; 925ab9e68a2SToomas Soome break; 926ab9e68a2SToomas Soome } 927ab9e68a2SToomas Soome #endif 928ab9e68a2SToomas Soome Tracev((stderr, "inflate: table sizes ok\n")); 929ab9e68a2SToomas Soome state->have = 0; 930ab9e68a2SToomas Soome state->mode = LENLENS; 931*64c3d159SToomas Soome /* fallthrough */ 932ab9e68a2SToomas Soome case LENLENS: 933ab9e68a2SToomas Soome while (state->have < state->ncode) { 934ab9e68a2SToomas Soome NEEDBITS(3); 935ab9e68a2SToomas Soome state->lens[order[state->have++]] = (unsigned short)BITS(3); 936ab9e68a2SToomas Soome DROPBITS(3); 937ab9e68a2SToomas Soome } 938ab9e68a2SToomas Soome while (state->have < 19) 939ab9e68a2SToomas Soome state->lens[order[state->have++]] = 0; 940ab9e68a2SToomas Soome state->next = state->codes; 941ab9e68a2SToomas Soome state->lencode = (const code FAR *)(state->next); 942ab9e68a2SToomas Soome state->lenbits = 7; 943ab9e68a2SToomas Soome ret = inflate_table(CODES, state->lens, 19, &(state->next), 944ab9e68a2SToomas Soome &(state->lenbits), state->work); 945ab9e68a2SToomas Soome if (ret) { 946ab9e68a2SToomas Soome strm->msg = (char *)"invalid code lengths set"; 947ab9e68a2SToomas Soome state->mode = BAD; 948ab9e68a2SToomas Soome break; 949ab9e68a2SToomas Soome } 950ab9e68a2SToomas Soome Tracev((stderr, "inflate: code lengths ok\n")); 951ab9e68a2SToomas Soome state->have = 0; 952ab9e68a2SToomas Soome state->mode = CODELENS; 953*64c3d159SToomas Soome /* fallthrough */ 954ab9e68a2SToomas Soome case CODELENS: 955ab9e68a2SToomas Soome while (state->have < state->nlen + state->ndist) { 956ab9e68a2SToomas Soome for (;;) { 957ab9e68a2SToomas Soome here = state->lencode[BITS(state->lenbits)]; 958ab9e68a2SToomas Soome if ((unsigned)(here.bits) <= bits) break; 959ab9e68a2SToomas Soome PULLBYTE(); 960ab9e68a2SToomas Soome } 961ab9e68a2SToomas Soome if (here.val < 16) { 962ab9e68a2SToomas Soome DROPBITS(here.bits); 963ab9e68a2SToomas Soome state->lens[state->have++] = here.val; 964ab9e68a2SToomas Soome } 965ab9e68a2SToomas Soome else { 966ab9e68a2SToomas Soome if (here.val == 16) { 967ab9e68a2SToomas Soome NEEDBITS(here.bits + 2); 968ab9e68a2SToomas Soome DROPBITS(here.bits); 969ab9e68a2SToomas Soome if (state->have == 0) { 970ab9e68a2SToomas Soome strm->msg = (char *)"invalid bit length repeat"; 971ab9e68a2SToomas Soome state->mode = BAD; 972ab9e68a2SToomas Soome break; 973ab9e68a2SToomas Soome } 974ab9e68a2SToomas Soome len = state->lens[state->have - 1]; 975ab9e68a2SToomas Soome copy = 3 + BITS(2); 976ab9e68a2SToomas Soome DROPBITS(2); 977ab9e68a2SToomas Soome } 978ab9e68a2SToomas Soome else if (here.val == 17) { 979ab9e68a2SToomas Soome NEEDBITS(here.bits + 3); 980ab9e68a2SToomas Soome DROPBITS(here.bits); 981ab9e68a2SToomas Soome len = 0; 982ab9e68a2SToomas Soome copy = 3 + BITS(3); 983ab9e68a2SToomas Soome DROPBITS(3); 984ab9e68a2SToomas Soome } 985ab9e68a2SToomas Soome else { 986ab9e68a2SToomas Soome NEEDBITS(here.bits + 7); 987ab9e68a2SToomas Soome DROPBITS(here.bits); 988ab9e68a2SToomas Soome len = 0; 989ab9e68a2SToomas Soome copy = 11 + BITS(7); 990ab9e68a2SToomas Soome DROPBITS(7); 991ab9e68a2SToomas Soome } 992ab9e68a2SToomas Soome if (state->have + copy > state->nlen + state->ndist) { 993ab9e68a2SToomas Soome strm->msg = (char *)"invalid bit length repeat"; 994ab9e68a2SToomas Soome state->mode = BAD; 995ab9e68a2SToomas Soome break; 996ab9e68a2SToomas Soome } 997ab9e68a2SToomas Soome while (copy--) 998ab9e68a2SToomas Soome state->lens[state->have++] = (unsigned short)len; 999ab9e68a2SToomas Soome } 1000ab9e68a2SToomas Soome } 1001ab9e68a2SToomas Soome 1002ab9e68a2SToomas Soome /* handle error breaks in while */ 1003ab9e68a2SToomas Soome if (state->mode == BAD) break; 1004ab9e68a2SToomas Soome 1005ab9e68a2SToomas Soome /* check for end-of-block code (better have one) */ 1006ab9e68a2SToomas Soome if (state->lens[256] == 0) { 1007ab9e68a2SToomas Soome strm->msg = (char *)"invalid code -- missing end-of-block"; 1008ab9e68a2SToomas Soome state->mode = BAD; 1009ab9e68a2SToomas Soome break; 1010ab9e68a2SToomas Soome } 1011ab9e68a2SToomas Soome 1012ab9e68a2SToomas Soome /* build code tables -- note: do not change the lenbits or distbits 1013ab9e68a2SToomas Soome values here (9 and 6) without reading the comments in inftrees.h 1014ab9e68a2SToomas Soome concerning the ENOUGH constants, which depend on those values */ 1015ab9e68a2SToomas Soome state->next = state->codes; 1016ab9e68a2SToomas Soome state->lencode = (const code FAR *)(state->next); 1017ab9e68a2SToomas Soome state->lenbits = 9; 1018ab9e68a2SToomas Soome ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), 1019ab9e68a2SToomas Soome &(state->lenbits), state->work); 1020ab9e68a2SToomas Soome if (ret) { 1021ab9e68a2SToomas Soome strm->msg = (char *)"invalid literal/lengths set"; 1022ab9e68a2SToomas Soome state->mode = BAD; 1023ab9e68a2SToomas Soome break; 1024ab9e68a2SToomas Soome } 1025ab9e68a2SToomas Soome state->distcode = (const code FAR *)(state->next); 1026ab9e68a2SToomas Soome state->distbits = 6; 1027ab9e68a2SToomas Soome ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, 1028ab9e68a2SToomas Soome &(state->next), &(state->distbits), state->work); 1029ab9e68a2SToomas Soome if (ret) { 1030ab9e68a2SToomas Soome strm->msg = (char *)"invalid distances set"; 1031ab9e68a2SToomas Soome state->mode = BAD; 1032ab9e68a2SToomas Soome break; 1033ab9e68a2SToomas Soome } 1034ab9e68a2SToomas Soome Tracev((stderr, "inflate: codes ok\n")); 1035ab9e68a2SToomas Soome state->mode = LEN_; 1036ab9e68a2SToomas Soome if (flush == Z_TREES) goto inf_leave; 1037ab9e68a2SToomas Soome /* FALLTHROUGH */ 1038ab9e68a2SToomas Soome case LEN_: 1039ab9e68a2SToomas Soome state->mode = LEN; 1040ab9e68a2SToomas Soome /* FALLTHROUGH */ 1041ab9e68a2SToomas Soome case LEN: 1042ab9e68a2SToomas Soome if (have >= 6 && left >= 258) { 1043ab9e68a2SToomas Soome RESTORE(); 1044ab9e68a2SToomas Soome inflate_fast(strm, out); 1045ab9e68a2SToomas Soome LOAD(); 1046ab9e68a2SToomas Soome if (state->mode == TYPE) 1047ab9e68a2SToomas Soome state->back = -1; 1048ab9e68a2SToomas Soome break; 1049ab9e68a2SToomas Soome } 1050ab9e68a2SToomas Soome state->back = 0; 1051ab9e68a2SToomas Soome for (;;) { 1052ab9e68a2SToomas Soome here = state->lencode[BITS(state->lenbits)]; 1053ab9e68a2SToomas Soome if ((unsigned)(here.bits) <= bits) break; 1054ab9e68a2SToomas Soome PULLBYTE(); 1055ab9e68a2SToomas Soome } 1056ab9e68a2SToomas Soome if (here.op && (here.op & 0xf0) == 0) { 1057ab9e68a2SToomas Soome last = here; 1058ab9e68a2SToomas Soome for (;;) { 1059ab9e68a2SToomas Soome here = state->lencode[last.val + 1060ab9e68a2SToomas Soome (BITS(last.bits + last.op) >> last.bits)]; 1061ab9e68a2SToomas Soome if ((unsigned)(last.bits + here.bits) <= bits) break; 1062ab9e68a2SToomas Soome PULLBYTE(); 1063ab9e68a2SToomas Soome } 1064ab9e68a2SToomas Soome DROPBITS(last.bits); 1065ab9e68a2SToomas Soome state->back += last.bits; 1066ab9e68a2SToomas Soome } 1067ab9e68a2SToomas Soome DROPBITS(here.bits); 1068ab9e68a2SToomas Soome state->back += here.bits; 1069ab9e68a2SToomas Soome state->length = (unsigned)here.val; 1070ab9e68a2SToomas Soome if ((int)(here.op) == 0) { 1071ab9e68a2SToomas Soome Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? 1072ab9e68a2SToomas Soome "inflate: literal '%c'\n" : 1073ab9e68a2SToomas Soome "inflate: literal 0x%02x\n", here.val)); 1074ab9e68a2SToomas Soome state->mode = LIT; 1075ab9e68a2SToomas Soome break; 1076ab9e68a2SToomas Soome } 1077ab9e68a2SToomas Soome if (here.op & 32) { 1078ab9e68a2SToomas Soome Tracevv((stderr, "inflate: end of block\n")); 1079ab9e68a2SToomas Soome state->back = -1; 1080ab9e68a2SToomas Soome state->mode = TYPE; 1081ab9e68a2SToomas Soome break; 1082ab9e68a2SToomas Soome } 1083ab9e68a2SToomas Soome if (here.op & 64) { 1084ab9e68a2SToomas Soome strm->msg = (char *)"invalid literal/length code"; 1085ab9e68a2SToomas Soome state->mode = BAD; 1086ab9e68a2SToomas Soome break; 1087ab9e68a2SToomas Soome } 1088ab9e68a2SToomas Soome state->extra = (unsigned)(here.op) & 15; 1089ab9e68a2SToomas Soome state->mode = LENEXT; 1090ab9e68a2SToomas Soome /* FALLTHROUGH */ 1091ab9e68a2SToomas Soome case LENEXT: 1092ab9e68a2SToomas Soome if (state->extra) { 1093ab9e68a2SToomas Soome NEEDBITS(state->extra); 1094ab9e68a2SToomas Soome state->length += BITS(state->extra); 1095ab9e68a2SToomas Soome DROPBITS(state->extra); 1096ab9e68a2SToomas Soome state->back += state->extra; 1097ab9e68a2SToomas Soome } 1098ab9e68a2SToomas Soome Tracevv((stderr, "inflate: length %u\n", state->length)); 1099ab9e68a2SToomas Soome state->was = state->length; 1100ab9e68a2SToomas Soome state->mode = DIST; 1101ab9e68a2SToomas Soome /* FALLTHROUGH */ 1102ab9e68a2SToomas Soome case DIST: 1103ab9e68a2SToomas Soome for (;;) { 1104ab9e68a2SToomas Soome here = state->distcode[BITS(state->distbits)]; 1105ab9e68a2SToomas Soome if ((unsigned)(here.bits) <= bits) break; 1106ab9e68a2SToomas Soome PULLBYTE(); 1107ab9e68a2SToomas Soome } 1108ab9e68a2SToomas Soome if ((here.op & 0xf0) == 0) { 1109ab9e68a2SToomas Soome last = here; 1110ab9e68a2SToomas Soome for (;;) { 1111ab9e68a2SToomas Soome here = state->distcode[last.val + 1112ab9e68a2SToomas Soome (BITS(last.bits + last.op) >> last.bits)]; 1113ab9e68a2SToomas Soome if ((unsigned)(last.bits + here.bits) <= bits) break; 1114ab9e68a2SToomas Soome PULLBYTE(); 1115ab9e68a2SToomas Soome } 1116ab9e68a2SToomas Soome DROPBITS(last.bits); 1117ab9e68a2SToomas Soome state->back += last.bits; 1118ab9e68a2SToomas Soome } 1119ab9e68a2SToomas Soome DROPBITS(here.bits); 1120ab9e68a2SToomas Soome state->back += here.bits; 1121ab9e68a2SToomas Soome if (here.op & 64) { 1122ab9e68a2SToomas Soome strm->msg = (char *)"invalid distance code"; 1123ab9e68a2SToomas Soome state->mode = BAD; 1124ab9e68a2SToomas Soome break; 1125ab9e68a2SToomas Soome } 1126ab9e68a2SToomas Soome state->offset = (unsigned)here.val; 1127ab9e68a2SToomas Soome state->extra = (unsigned)(here.op) & 15; 1128ab9e68a2SToomas Soome state->mode = DISTEXT; 1129ab9e68a2SToomas Soome /* FALLTHROUGH */ 1130ab9e68a2SToomas Soome case DISTEXT: 1131ab9e68a2SToomas Soome if (state->extra) { 1132ab9e68a2SToomas Soome NEEDBITS(state->extra); 1133ab9e68a2SToomas Soome state->offset += BITS(state->extra); 1134ab9e68a2SToomas Soome DROPBITS(state->extra); 1135ab9e68a2SToomas Soome state->back += state->extra; 1136ab9e68a2SToomas Soome } 1137ab9e68a2SToomas Soome #ifdef INFLATE_STRICT 1138ab9e68a2SToomas Soome if (state->offset > state->dmax) { 1139ab9e68a2SToomas Soome strm->msg = (char *)"invalid distance too far back"; 1140ab9e68a2SToomas Soome state->mode = BAD; 1141ab9e68a2SToomas Soome break; 1142ab9e68a2SToomas Soome } 1143ab9e68a2SToomas Soome #endif 1144ab9e68a2SToomas Soome Tracevv((stderr, "inflate: distance %u\n", state->offset)); 1145ab9e68a2SToomas Soome state->mode = MATCH; 1146ab9e68a2SToomas Soome /* FALLTHROUGH */ 1147ab9e68a2SToomas Soome case MATCH: 1148ab9e68a2SToomas Soome if (left == 0) goto inf_leave; 1149ab9e68a2SToomas Soome copy = out - left; 1150ab9e68a2SToomas Soome if (state->offset > copy) { /* copy from window */ 1151ab9e68a2SToomas Soome copy = state->offset - copy; 1152ab9e68a2SToomas Soome if (copy > state->whave) { 1153ab9e68a2SToomas Soome if (state->sane) { 1154ab9e68a2SToomas Soome strm->msg = (char *)"invalid distance too far back"; 1155ab9e68a2SToomas Soome state->mode = BAD; 1156ab9e68a2SToomas Soome break; 1157ab9e68a2SToomas Soome } 1158ab9e68a2SToomas Soome #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR 1159ab9e68a2SToomas Soome Trace((stderr, "inflate.c too far\n")); 1160ab9e68a2SToomas Soome copy -= state->whave; 1161ab9e68a2SToomas Soome if (copy > state->length) copy = state->length; 1162ab9e68a2SToomas Soome if (copy > left) copy = left; 1163ab9e68a2SToomas Soome left -= copy; 1164ab9e68a2SToomas Soome state->length -= copy; 1165ab9e68a2SToomas Soome do { 1166ab9e68a2SToomas Soome *put++ = 0; 1167ab9e68a2SToomas Soome } while (--copy); 1168ab9e68a2SToomas Soome if (state->length == 0) state->mode = LEN; 1169ab9e68a2SToomas Soome break; 1170ab9e68a2SToomas Soome #endif 1171ab9e68a2SToomas Soome } 1172ab9e68a2SToomas Soome if (copy > state->wnext) { 1173ab9e68a2SToomas Soome copy -= state->wnext; 1174ab9e68a2SToomas Soome from = state->window + (state->wsize - copy); 1175ab9e68a2SToomas Soome } 1176ab9e68a2SToomas Soome else 1177ab9e68a2SToomas Soome from = state->window + (state->wnext - copy); 1178ab9e68a2SToomas Soome if (copy > state->length) copy = state->length; 1179ab9e68a2SToomas Soome } 1180ab9e68a2SToomas Soome else { /* copy from output */ 1181ab9e68a2SToomas Soome from = put - state->offset; 1182ab9e68a2SToomas Soome copy = state->length; 1183ab9e68a2SToomas Soome } 1184ab9e68a2SToomas Soome if (copy > left) copy = left; 1185ab9e68a2SToomas Soome left -= copy; 1186ab9e68a2SToomas Soome state->length -= copy; 1187ab9e68a2SToomas Soome do { 1188ab9e68a2SToomas Soome *put++ = *from++; 1189ab9e68a2SToomas Soome } while (--copy); 1190ab9e68a2SToomas Soome if (state->length == 0) state->mode = LEN; 1191ab9e68a2SToomas Soome break; 1192ab9e68a2SToomas Soome case LIT: 1193ab9e68a2SToomas Soome if (left == 0) goto inf_leave; 1194ab9e68a2SToomas Soome *put++ = (unsigned char)(state->length); 1195ab9e68a2SToomas Soome left--; 1196ab9e68a2SToomas Soome state->mode = LEN; 1197ab9e68a2SToomas Soome break; 1198ab9e68a2SToomas Soome case CHECK: 1199ab9e68a2SToomas Soome if (state->wrap) { 1200ab9e68a2SToomas Soome NEEDBITS(32); 1201ab9e68a2SToomas Soome out -= left; 1202ab9e68a2SToomas Soome strm->total_out += out; 1203ab9e68a2SToomas Soome state->total += out; 1204ab9e68a2SToomas Soome if ((state->wrap & 4) && out) 1205ab9e68a2SToomas Soome strm->adler = state->check = 1206*64c3d159SToomas Soome UPDATE_CHECK(state->check, put - out, out); 1207ab9e68a2SToomas Soome out = left; 1208ab9e68a2SToomas Soome if ((state->wrap & 4) && ( 1209ab9e68a2SToomas Soome #ifdef GUNZIP 1210ab9e68a2SToomas Soome state->flags ? hold : 1211ab9e68a2SToomas Soome #endif 1212ab9e68a2SToomas Soome ZSWAP32(hold)) != state->check) { 1213ab9e68a2SToomas Soome strm->msg = (char *)"incorrect data check"; 1214ab9e68a2SToomas Soome state->mode = BAD; 1215ab9e68a2SToomas Soome break; 1216ab9e68a2SToomas Soome } 1217ab9e68a2SToomas Soome INITBITS(); 1218ab9e68a2SToomas Soome Tracev((stderr, "inflate: check matches trailer\n")); 1219ab9e68a2SToomas Soome } 1220ab9e68a2SToomas Soome #ifdef GUNZIP 1221ab9e68a2SToomas Soome state->mode = LENGTH; 1222ab9e68a2SToomas Soome /* FALLTHROUGH */ 1223ab9e68a2SToomas Soome case LENGTH: 1224ab9e68a2SToomas Soome if (state->wrap && state->flags) { 1225ab9e68a2SToomas Soome NEEDBITS(32); 1226*64c3d159SToomas Soome if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) { 1227ab9e68a2SToomas Soome strm->msg = (char *)"incorrect length check"; 1228ab9e68a2SToomas Soome state->mode = BAD; 1229ab9e68a2SToomas Soome break; 1230ab9e68a2SToomas Soome } 1231ab9e68a2SToomas Soome INITBITS(); 1232ab9e68a2SToomas Soome Tracev((stderr, "inflate: length matches trailer\n")); 1233ab9e68a2SToomas Soome } 1234ab9e68a2SToomas Soome #endif 1235ab9e68a2SToomas Soome state->mode = DONE; 1236ab9e68a2SToomas Soome /* FALLTHROUGH */ 1237ab9e68a2SToomas Soome case DONE: 1238ab9e68a2SToomas Soome ret = Z_STREAM_END; 1239ab9e68a2SToomas Soome goto inf_leave; 1240ab9e68a2SToomas Soome case BAD: 1241ab9e68a2SToomas Soome ret = Z_DATA_ERROR; 1242ab9e68a2SToomas Soome goto inf_leave; 1243ab9e68a2SToomas Soome case MEM: 1244ab9e68a2SToomas Soome return Z_MEM_ERROR; 1245ab9e68a2SToomas Soome case SYNC: 1246*64c3d159SToomas Soome /* fallthrough */ 1247ab9e68a2SToomas Soome default: 1248ab9e68a2SToomas Soome return Z_STREAM_ERROR; 1249ab9e68a2SToomas Soome } 1250ab9e68a2SToomas Soome 1251ab9e68a2SToomas Soome /* 1252ab9e68a2SToomas Soome Return from inflate(), updating the total counts and the check value. 1253ab9e68a2SToomas Soome If there was no progress during the inflate() call, return a buffer 1254ab9e68a2SToomas Soome error. Call updatewindow() to create and/or update the window state. 1255ab9e68a2SToomas Soome Note: a memory error from inflate() is non-recoverable. 1256ab9e68a2SToomas Soome */ 1257ab9e68a2SToomas Soome inf_leave: 1258ab9e68a2SToomas Soome RESTORE(); 1259ab9e68a2SToomas Soome if (state->wsize || (out != strm->avail_out && state->mode < BAD && 1260ab9e68a2SToomas Soome (state->mode < CHECK || flush != Z_FINISH))) 1261ab9e68a2SToomas Soome if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { 1262ab9e68a2SToomas Soome state->mode = MEM; 1263ab9e68a2SToomas Soome return Z_MEM_ERROR; 1264ab9e68a2SToomas Soome } 1265ab9e68a2SToomas Soome in -= strm->avail_in; 1266ab9e68a2SToomas Soome out -= strm->avail_out; 1267ab9e68a2SToomas Soome strm->total_in += in; 1268ab9e68a2SToomas Soome strm->total_out += out; 1269ab9e68a2SToomas Soome state->total += out; 1270ab9e68a2SToomas Soome if ((state->wrap & 4) && out) 1271ab9e68a2SToomas Soome strm->adler = state->check = 1272*64c3d159SToomas Soome UPDATE_CHECK(state->check, strm->next_out - out, out); 1273ab9e68a2SToomas Soome strm->data_type = (int)state->bits + (state->last ? 64 : 0) + 1274ab9e68a2SToomas Soome (state->mode == TYPE ? 128 : 0) + 1275ab9e68a2SToomas Soome (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); 1276ab9e68a2SToomas Soome if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) 1277ab9e68a2SToomas Soome ret = Z_BUF_ERROR; 1278ab9e68a2SToomas Soome return ret; 1279ab9e68a2SToomas Soome } 1280ab9e68a2SToomas Soome 1281ab9e68a2SToomas Soome int ZEXPORT inflateEnd(z_streamp strm) 1282ab9e68a2SToomas Soome { 1283ab9e68a2SToomas Soome struct inflate_state FAR *state; 1284ab9e68a2SToomas Soome if (inflateStateCheck(strm)) 1285ab9e68a2SToomas Soome return Z_STREAM_ERROR; 1286ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1287ab9e68a2SToomas Soome if (state->window != Z_NULL) ZFREE(strm, state->window); 1288ab9e68a2SToomas Soome ZFREE(strm, strm->state); 1289ab9e68a2SToomas Soome strm->state = Z_NULL; 1290ab9e68a2SToomas Soome Tracev((stderr, "inflate: end\n")); 1291ab9e68a2SToomas Soome return Z_OK; 1292ab9e68a2SToomas Soome } 1293ab9e68a2SToomas Soome 1294ab9e68a2SToomas Soome int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary, 1295ab9e68a2SToomas Soome uInt *dictLength) 1296ab9e68a2SToomas Soome { 1297ab9e68a2SToomas Soome struct inflate_state FAR *state; 1298ab9e68a2SToomas Soome 1299ab9e68a2SToomas Soome /* check state */ 1300ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 1301ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1302ab9e68a2SToomas Soome 1303ab9e68a2SToomas Soome /* copy dictionary */ 1304ab9e68a2SToomas Soome if (state->whave && dictionary != Z_NULL) { 1305ab9e68a2SToomas Soome zmemcpy(dictionary, state->window + state->wnext, 1306ab9e68a2SToomas Soome state->whave - state->wnext); 1307ab9e68a2SToomas Soome zmemcpy(dictionary + state->whave - state->wnext, 1308ab9e68a2SToomas Soome state->window, state->wnext); 1309ab9e68a2SToomas Soome } 1310ab9e68a2SToomas Soome if (dictLength != Z_NULL) 1311ab9e68a2SToomas Soome *dictLength = state->whave; 1312ab9e68a2SToomas Soome return Z_OK; 1313ab9e68a2SToomas Soome } 1314ab9e68a2SToomas Soome 1315ab9e68a2SToomas Soome int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, 1316ab9e68a2SToomas Soome uInt dictLength) 1317ab9e68a2SToomas Soome { 1318ab9e68a2SToomas Soome struct inflate_state FAR *state; 1319ab9e68a2SToomas Soome unsigned long dictid; 1320ab9e68a2SToomas Soome int ret; 1321ab9e68a2SToomas Soome 1322ab9e68a2SToomas Soome /* check state */ 1323ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 1324ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1325ab9e68a2SToomas Soome if (state->wrap != 0 && state->mode != DICT) 1326ab9e68a2SToomas Soome return Z_STREAM_ERROR; 1327ab9e68a2SToomas Soome 1328ab9e68a2SToomas Soome /* check for correct dictionary identifier */ 1329ab9e68a2SToomas Soome if (state->mode == DICT) { 1330ab9e68a2SToomas Soome dictid = adler32(0L, Z_NULL, 0); 1331ab9e68a2SToomas Soome dictid = adler32(dictid, dictionary, dictLength); 1332ab9e68a2SToomas Soome if (dictid != state->check) 1333ab9e68a2SToomas Soome return Z_DATA_ERROR; 1334ab9e68a2SToomas Soome } 1335ab9e68a2SToomas Soome 1336ab9e68a2SToomas Soome /* copy dictionary to window using updatewindow(), which will amend the 1337ab9e68a2SToomas Soome existing dictionary if appropriate */ 1338ab9e68a2SToomas Soome ret = updatewindow(strm, dictionary + dictLength, dictLength); 1339ab9e68a2SToomas Soome if (ret) { 1340ab9e68a2SToomas Soome state->mode = MEM; 1341ab9e68a2SToomas Soome return Z_MEM_ERROR; 1342ab9e68a2SToomas Soome } 1343ab9e68a2SToomas Soome state->havedict = 1; 1344ab9e68a2SToomas Soome Tracev((stderr, "inflate: dictionary set\n")); 1345ab9e68a2SToomas Soome return Z_OK; 1346ab9e68a2SToomas Soome } 1347ab9e68a2SToomas Soome 1348ab9e68a2SToomas Soome int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) 1349ab9e68a2SToomas Soome { 1350ab9e68a2SToomas Soome struct inflate_state FAR *state; 1351ab9e68a2SToomas Soome 1352ab9e68a2SToomas Soome /* check state */ 1353ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 1354ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1355ab9e68a2SToomas Soome if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; 1356ab9e68a2SToomas Soome 1357ab9e68a2SToomas Soome /* save header structure */ 1358ab9e68a2SToomas Soome state->head = head; 1359ab9e68a2SToomas Soome head->done = 0; 1360ab9e68a2SToomas Soome return Z_OK; 1361ab9e68a2SToomas Soome } 1362ab9e68a2SToomas Soome 1363ab9e68a2SToomas Soome /* 1364ab9e68a2SToomas Soome Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found 1365ab9e68a2SToomas Soome or when out of input. When called, *have is the number of pattern bytes 1366ab9e68a2SToomas Soome found in order so far, in 0..3. On return *have is updated to the new 1367ab9e68a2SToomas Soome state. If on return *have equals four, then the pattern was found and the 1368ab9e68a2SToomas Soome return value is how many bytes were read including the last byte of the 1369ab9e68a2SToomas Soome pattern. If *have is less than four, then the pattern has not been found 1370ab9e68a2SToomas Soome yet and the return value is len. In the latter case, syncsearch() can be 1371ab9e68a2SToomas Soome called again with more data and the *have state. *have is initialized to 1372ab9e68a2SToomas Soome zero for the first call. 1373ab9e68a2SToomas Soome */ 1374ab9e68a2SToomas Soome local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf, 1375ab9e68a2SToomas Soome unsigned len) 1376ab9e68a2SToomas Soome { 1377ab9e68a2SToomas Soome unsigned got; 1378ab9e68a2SToomas Soome unsigned next; 1379ab9e68a2SToomas Soome 1380ab9e68a2SToomas Soome got = *have; 1381ab9e68a2SToomas Soome next = 0; 1382ab9e68a2SToomas Soome while (next < len && got < 4) { 1383ab9e68a2SToomas Soome if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) 1384ab9e68a2SToomas Soome got++; 1385ab9e68a2SToomas Soome else if (buf[next]) 1386ab9e68a2SToomas Soome got = 0; 1387ab9e68a2SToomas Soome else 1388ab9e68a2SToomas Soome got = 4 - got; 1389ab9e68a2SToomas Soome next++; 1390ab9e68a2SToomas Soome } 1391ab9e68a2SToomas Soome *have = got; 1392ab9e68a2SToomas Soome return next; 1393ab9e68a2SToomas Soome } 1394ab9e68a2SToomas Soome 1395ab9e68a2SToomas Soome int ZEXPORT inflateSync(z_streamp strm) 1396ab9e68a2SToomas Soome { 1397ab9e68a2SToomas Soome unsigned len; /* number of bytes to look at or looked at */ 1398*64c3d159SToomas Soome int flags; /* temporary to save header status */ 1399ab9e68a2SToomas Soome unsigned long in, out; /* temporary to save total_in and total_out */ 1400ab9e68a2SToomas Soome unsigned char buf[4]; /* to restore bit buffer to byte string */ 1401ab9e68a2SToomas Soome struct inflate_state FAR *state; 1402ab9e68a2SToomas Soome 1403ab9e68a2SToomas Soome /* check parameters */ 1404ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 1405ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1406ab9e68a2SToomas Soome if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; 1407ab9e68a2SToomas Soome 1408ab9e68a2SToomas Soome /* if first time, start search in bit buffer */ 1409ab9e68a2SToomas Soome if (state->mode != SYNC) { 1410ab9e68a2SToomas Soome state->mode = SYNC; 1411ab9e68a2SToomas Soome state->hold <<= state->bits & 7; 1412ab9e68a2SToomas Soome state->bits -= state->bits & 7; 1413ab9e68a2SToomas Soome len = 0; 1414ab9e68a2SToomas Soome while (state->bits >= 8) { 1415ab9e68a2SToomas Soome buf[len++] = (unsigned char)(state->hold); 1416ab9e68a2SToomas Soome state->hold >>= 8; 1417ab9e68a2SToomas Soome state->bits -= 8; 1418ab9e68a2SToomas Soome } 1419ab9e68a2SToomas Soome state->have = 0; 1420ab9e68a2SToomas Soome syncsearch(&(state->have), buf, len); 1421ab9e68a2SToomas Soome } 1422ab9e68a2SToomas Soome 1423ab9e68a2SToomas Soome /* search available input */ 1424ab9e68a2SToomas Soome len = syncsearch(&(state->have), strm->next_in, strm->avail_in); 1425ab9e68a2SToomas Soome strm->avail_in -= len; 1426ab9e68a2SToomas Soome strm->next_in += len; 1427ab9e68a2SToomas Soome strm->total_in += len; 1428ab9e68a2SToomas Soome 1429ab9e68a2SToomas Soome /* return no joy or set up to restart inflate() on a new block */ 1430ab9e68a2SToomas Soome if (state->have != 4) return Z_DATA_ERROR; 1431*64c3d159SToomas Soome if (state->flags == -1) 1432*64c3d159SToomas Soome state->wrap = 0; /* if no header yet, treat as raw */ 1433*64c3d159SToomas Soome else 1434*64c3d159SToomas Soome state->wrap &= ~4; /* no point in computing a check value now */ 1435*64c3d159SToomas Soome flags = state->flags; 1436ab9e68a2SToomas Soome in = strm->total_in; out = strm->total_out; 1437ab9e68a2SToomas Soome inflateReset(strm); 1438ab9e68a2SToomas Soome strm->total_in = in; strm->total_out = out; 1439*64c3d159SToomas Soome state->flags = flags; 1440ab9e68a2SToomas Soome state->mode = TYPE; 1441ab9e68a2SToomas Soome return Z_OK; 1442ab9e68a2SToomas Soome } 1443ab9e68a2SToomas Soome 1444ab9e68a2SToomas Soome /* 1445ab9e68a2SToomas Soome Returns true if inflate is currently at the end of a block generated by 1446ab9e68a2SToomas Soome Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP 1447ab9e68a2SToomas Soome implementation to provide an additional safety check. PPP uses 1448ab9e68a2SToomas Soome Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored 1449ab9e68a2SToomas Soome block. When decompressing, PPP checks that at the end of input packet, 1450ab9e68a2SToomas Soome inflate is waiting for these length bytes. 1451ab9e68a2SToomas Soome */ 1452ab9e68a2SToomas Soome int ZEXPORT inflateSyncPoint(z_streamp strm) 1453ab9e68a2SToomas Soome { 1454ab9e68a2SToomas Soome struct inflate_state FAR *state; 1455ab9e68a2SToomas Soome 1456ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 1457ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1458ab9e68a2SToomas Soome return state->mode == STORED && state->bits == 0; 1459ab9e68a2SToomas Soome } 1460ab9e68a2SToomas Soome 1461ab9e68a2SToomas Soome int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) 1462ab9e68a2SToomas Soome { 1463ab9e68a2SToomas Soome struct inflate_state FAR *state; 1464ab9e68a2SToomas Soome struct inflate_state FAR *copy; 1465ab9e68a2SToomas Soome unsigned char FAR *window; 1466ab9e68a2SToomas Soome unsigned wsize; 1467ab9e68a2SToomas Soome 1468ab9e68a2SToomas Soome /* check input */ 1469ab9e68a2SToomas Soome if (inflateStateCheck(source) || dest == Z_NULL) 1470ab9e68a2SToomas Soome return Z_STREAM_ERROR; 1471ab9e68a2SToomas Soome state = (struct inflate_state FAR *)source->state; 1472ab9e68a2SToomas Soome 1473ab9e68a2SToomas Soome /* allocate space */ 1474ab9e68a2SToomas Soome copy = (struct inflate_state FAR *) 1475ab9e68a2SToomas Soome ZALLOC(source, 1, sizeof(struct inflate_state)); 1476ab9e68a2SToomas Soome if (copy == Z_NULL) return Z_MEM_ERROR; 1477ab9e68a2SToomas Soome window = Z_NULL; 1478ab9e68a2SToomas Soome if (state->window != Z_NULL) { 1479ab9e68a2SToomas Soome window = (unsigned char FAR *) 1480ab9e68a2SToomas Soome ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); 1481ab9e68a2SToomas Soome if (window == Z_NULL) { 1482ab9e68a2SToomas Soome ZFREE(source, copy); 1483ab9e68a2SToomas Soome return Z_MEM_ERROR; 1484ab9e68a2SToomas Soome } 1485ab9e68a2SToomas Soome } 1486ab9e68a2SToomas Soome 1487ab9e68a2SToomas Soome /* copy state */ 1488ab9e68a2SToomas Soome zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); 1489ab9e68a2SToomas Soome zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); 1490ab9e68a2SToomas Soome copy->strm = dest; 1491ab9e68a2SToomas Soome if (state->lencode >= state->codes && 1492ab9e68a2SToomas Soome state->lencode <= state->codes + ENOUGH - 1) { 1493ab9e68a2SToomas Soome copy->lencode = copy->codes + (state->lencode - state->codes); 1494ab9e68a2SToomas Soome copy->distcode = copy->codes + (state->distcode - state->codes); 1495ab9e68a2SToomas Soome } 1496ab9e68a2SToomas Soome copy->next = copy->codes + (state->next - state->codes); 1497ab9e68a2SToomas Soome if (window != Z_NULL) { 1498ab9e68a2SToomas Soome wsize = 1U << state->wbits; 1499ab9e68a2SToomas Soome zmemcpy(window, state->window, wsize); 1500ab9e68a2SToomas Soome } 1501ab9e68a2SToomas Soome copy->window = window; 1502ab9e68a2SToomas Soome dest->state = (struct internal_state FAR *)copy; 1503ab9e68a2SToomas Soome return Z_OK; 1504ab9e68a2SToomas Soome } 1505ab9e68a2SToomas Soome 1506ab9e68a2SToomas Soome int ZEXPORT inflateUndermine(z_streamp strm, int subvert) 1507ab9e68a2SToomas Soome { 1508ab9e68a2SToomas Soome struct inflate_state FAR *state; 1509ab9e68a2SToomas Soome 1510ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 1511ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1512ab9e68a2SToomas Soome #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR 1513ab9e68a2SToomas Soome state->sane = !subvert; 1514ab9e68a2SToomas Soome return Z_OK; 1515ab9e68a2SToomas Soome #else 1516ab9e68a2SToomas Soome (void)subvert; 1517ab9e68a2SToomas Soome state->sane = 1; 1518ab9e68a2SToomas Soome return Z_DATA_ERROR; 1519ab9e68a2SToomas Soome #endif 1520ab9e68a2SToomas Soome } 1521ab9e68a2SToomas Soome 1522ab9e68a2SToomas Soome int ZEXPORT inflateValidate(z_streamp strm, int check) 1523ab9e68a2SToomas Soome { 1524ab9e68a2SToomas Soome struct inflate_state FAR *state; 1525ab9e68a2SToomas Soome 1526ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 1527ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1528*64c3d159SToomas Soome if (check && state->wrap) 1529ab9e68a2SToomas Soome state->wrap |= 4; 1530ab9e68a2SToomas Soome else 1531ab9e68a2SToomas Soome state->wrap &= ~4; 1532ab9e68a2SToomas Soome return Z_OK; 1533ab9e68a2SToomas Soome } 1534ab9e68a2SToomas Soome 1535ab9e68a2SToomas Soome long ZEXPORT inflateMark(z_streamp strm) 1536ab9e68a2SToomas Soome { 1537ab9e68a2SToomas Soome struct inflate_state FAR *state; 1538ab9e68a2SToomas Soome 1539ab9e68a2SToomas Soome if (inflateStateCheck(strm)) 1540ab9e68a2SToomas Soome return -(1L << 16); 1541ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1542ab9e68a2SToomas Soome return (long)(((unsigned long)((long)state->back)) << 16) + 1543ab9e68a2SToomas Soome (state->mode == COPY ? state->length : 1544ab9e68a2SToomas Soome (state->mode == MATCH ? state->was - state->length : 0)); 1545ab9e68a2SToomas Soome } 1546ab9e68a2SToomas Soome 1547ab9e68a2SToomas Soome unsigned long ZEXPORT inflateCodesUsed(z_streamp strm) 1548ab9e68a2SToomas Soome { 1549ab9e68a2SToomas Soome struct inflate_state FAR *state; 1550ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return (unsigned long)-1; 1551ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1552ab9e68a2SToomas Soome return (unsigned long)(state->next - state->codes); 1553ab9e68a2SToomas Soome } 1554