1ab9e68a2SToomas Soome /* inflate.c -- zlib decompression 264c3d159SToomas 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; 13164c3d159SToomas 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 43364c3d159SToomas Soome # define UPDATE_CHECK(check, buf, len) \ 434ab9e68a2SToomas Soome (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) 435ab9e68a2SToomas Soome #else 43664c3d159SToomas 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; 68064c3d159SToomas 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; 70664c3d159SToomas 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; 71564c3d159SToomas 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 && 747*255bd2d6SMark Adler state->head->extra != Z_NULL && 748*255bd2d6SMark Adler (len = state->head->extra_len - state->length) < 749*255bd2d6SMark Adler state->head->extra_max) { 750ab9e68a2SToomas Soome zmemcpy(state->head->extra + len, next, 751ab9e68a2SToomas Soome len + copy > state->head->extra_max ? 752ab9e68a2SToomas Soome state->head->extra_max - len : copy); 753ab9e68a2SToomas Soome } 754ab9e68a2SToomas Soome if ((state->flags & 0x0200) && (state->wrap & 4)) 755ab9e68a2SToomas Soome state->check = crc32(state->check, next, copy); 756ab9e68a2SToomas Soome have -= copy; 757ab9e68a2SToomas Soome next += copy; 758ab9e68a2SToomas Soome state->length -= copy; 759ab9e68a2SToomas Soome } 760ab9e68a2SToomas Soome if (state->length) goto inf_leave; 761ab9e68a2SToomas Soome } 762ab9e68a2SToomas Soome state->length = 0; 763ab9e68a2SToomas Soome state->mode = NAME; 764ab9e68a2SToomas Soome /* FALLTHROUGH */ 765ab9e68a2SToomas Soome case NAME: 766ab9e68a2SToomas Soome if (state->flags & 0x0800) { 767ab9e68a2SToomas Soome if (have == 0) goto inf_leave; 768ab9e68a2SToomas Soome copy = 0; 769ab9e68a2SToomas Soome do { 770ab9e68a2SToomas Soome len = (unsigned)(next[copy++]); 771ab9e68a2SToomas Soome if (state->head != Z_NULL && 772ab9e68a2SToomas Soome state->head->name != Z_NULL && 773ab9e68a2SToomas Soome state->length < state->head->name_max) 774ab9e68a2SToomas Soome state->head->name[state->length++] = (Bytef)len; 775ab9e68a2SToomas Soome } while (len && copy < have); 776ab9e68a2SToomas Soome if ((state->flags & 0x0200) && (state->wrap & 4)) 777ab9e68a2SToomas Soome state->check = crc32(state->check, next, copy); 778ab9e68a2SToomas Soome have -= copy; 779ab9e68a2SToomas Soome next += copy; 780ab9e68a2SToomas Soome if (len) goto inf_leave; 781ab9e68a2SToomas Soome } 782ab9e68a2SToomas Soome else if (state->head != Z_NULL) 783ab9e68a2SToomas Soome state->head->name = Z_NULL; 784ab9e68a2SToomas Soome state->length = 0; 785ab9e68a2SToomas Soome state->mode = COMMENT; 786ab9e68a2SToomas Soome /* FALLTHROUGH */ 787ab9e68a2SToomas Soome case COMMENT: 788ab9e68a2SToomas Soome if (state->flags & 0x1000) { 789ab9e68a2SToomas Soome if (have == 0) goto inf_leave; 790ab9e68a2SToomas Soome copy = 0; 791ab9e68a2SToomas Soome do { 792ab9e68a2SToomas Soome len = (unsigned)(next[copy++]); 793ab9e68a2SToomas Soome if (state->head != Z_NULL && 794ab9e68a2SToomas Soome state->head->comment != Z_NULL && 795ab9e68a2SToomas Soome state->length < state->head->comm_max) 796ab9e68a2SToomas Soome state->head->comment[state->length++] = (Bytef)len; 797ab9e68a2SToomas Soome } while (len && copy < have); 798ab9e68a2SToomas Soome if ((state->flags & 0x0200) && (state->wrap & 4)) 799ab9e68a2SToomas Soome state->check = crc32(state->check, next, copy); 800ab9e68a2SToomas Soome have -= copy; 801ab9e68a2SToomas Soome next += copy; 802ab9e68a2SToomas Soome if (len) goto inf_leave; 803ab9e68a2SToomas Soome } 804ab9e68a2SToomas Soome else if (state->head != Z_NULL) 805ab9e68a2SToomas Soome state->head->comment = Z_NULL; 806ab9e68a2SToomas Soome state->mode = HCRC; 807ab9e68a2SToomas Soome /* FALLTHROUGH */ 808ab9e68a2SToomas Soome case HCRC: 809ab9e68a2SToomas Soome if (state->flags & 0x0200) { 810ab9e68a2SToomas Soome NEEDBITS(16); 811ab9e68a2SToomas Soome if ((state->wrap & 4) && hold != (state->check & 0xffff)) { 812ab9e68a2SToomas Soome strm->msg = (char *)"header crc mismatch"; 813ab9e68a2SToomas Soome state->mode = BAD; 814ab9e68a2SToomas Soome break; 815ab9e68a2SToomas Soome } 816ab9e68a2SToomas Soome INITBITS(); 817ab9e68a2SToomas Soome } 818ab9e68a2SToomas Soome if (state->head != Z_NULL) { 819ab9e68a2SToomas Soome state->head->hcrc = (int)((state->flags >> 9) & 1); 820ab9e68a2SToomas Soome state->head->done = 1; 821ab9e68a2SToomas Soome } 822ab9e68a2SToomas Soome strm->adler = state->check = crc32(0L, Z_NULL, 0); 823ab9e68a2SToomas Soome state->mode = TYPE; 824ab9e68a2SToomas Soome break; 825ab9e68a2SToomas Soome #endif 826ab9e68a2SToomas Soome case DICTID: 827ab9e68a2SToomas Soome NEEDBITS(32); 828ab9e68a2SToomas Soome strm->adler = state->check = ZSWAP32(hold); 829ab9e68a2SToomas Soome INITBITS(); 830ab9e68a2SToomas Soome state->mode = DICT; 831ab9e68a2SToomas Soome /* FALLTHROUGH */ 832ab9e68a2SToomas Soome case DICT: 833ab9e68a2SToomas Soome if (state->havedict == 0) { 834ab9e68a2SToomas Soome RESTORE(); 835ab9e68a2SToomas Soome return Z_NEED_DICT; 836ab9e68a2SToomas Soome } 837ab9e68a2SToomas Soome strm->adler = state->check = adler32(0L, Z_NULL, 0); 838ab9e68a2SToomas Soome state->mode = TYPE; 839ab9e68a2SToomas Soome /* FALLTHROUGH */ 840ab9e68a2SToomas Soome case TYPE: 841ab9e68a2SToomas Soome if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; 842ab9e68a2SToomas Soome /* FALLTHROUGH */ 843ab9e68a2SToomas Soome case TYPEDO: 844ab9e68a2SToomas Soome if (state->last) { 845ab9e68a2SToomas Soome BYTEBITS(); 846ab9e68a2SToomas Soome state->mode = CHECK; 847ab9e68a2SToomas Soome break; 848ab9e68a2SToomas Soome } 849ab9e68a2SToomas Soome NEEDBITS(3); 850ab9e68a2SToomas Soome state->last = BITS(1); 851ab9e68a2SToomas Soome DROPBITS(1); 852ab9e68a2SToomas Soome switch (BITS(2)) { 853ab9e68a2SToomas Soome case 0: /* stored block */ 854ab9e68a2SToomas Soome Tracev((stderr, "inflate: stored block%s\n", 855ab9e68a2SToomas Soome state->last ? " (last)" : "")); 856ab9e68a2SToomas Soome state->mode = STORED; 857ab9e68a2SToomas Soome break; 858ab9e68a2SToomas Soome case 1: /* fixed block */ 859ab9e68a2SToomas Soome fixedtables(state); 860ab9e68a2SToomas Soome Tracev((stderr, "inflate: fixed codes block%s\n", 861ab9e68a2SToomas Soome state->last ? " (last)" : "")); 862ab9e68a2SToomas Soome state->mode = LEN_; /* decode codes */ 863ab9e68a2SToomas Soome if (flush == Z_TREES) { 864ab9e68a2SToomas Soome DROPBITS(2); 865ab9e68a2SToomas Soome goto inf_leave; 866ab9e68a2SToomas Soome } 867ab9e68a2SToomas Soome break; 868ab9e68a2SToomas Soome case 2: /* dynamic block */ 869ab9e68a2SToomas Soome Tracev((stderr, "inflate: dynamic codes block%s\n", 870ab9e68a2SToomas Soome state->last ? " (last)" : "")); 871ab9e68a2SToomas Soome state->mode = TABLE; 872ab9e68a2SToomas Soome break; 873ab9e68a2SToomas Soome case 3: 874ab9e68a2SToomas Soome strm->msg = (char *)"invalid block type"; 875ab9e68a2SToomas Soome state->mode = BAD; 876ab9e68a2SToomas Soome } 877ab9e68a2SToomas Soome DROPBITS(2); 878ab9e68a2SToomas Soome break; 879ab9e68a2SToomas Soome case STORED: 880ab9e68a2SToomas Soome BYTEBITS(); /* go to byte boundary */ 881ab9e68a2SToomas Soome NEEDBITS(32); 882ab9e68a2SToomas Soome if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { 883ab9e68a2SToomas Soome strm->msg = (char *)"invalid stored block lengths"; 884ab9e68a2SToomas Soome state->mode = BAD; 885ab9e68a2SToomas Soome break; 886ab9e68a2SToomas Soome } 887ab9e68a2SToomas Soome state->length = (unsigned)hold & 0xffff; 888ab9e68a2SToomas Soome Tracev((stderr, "inflate: stored length %u\n", 889ab9e68a2SToomas Soome state->length)); 890ab9e68a2SToomas Soome INITBITS(); 891ab9e68a2SToomas Soome state->mode = COPY_; 892ab9e68a2SToomas Soome if (flush == Z_TREES) goto inf_leave; 893ab9e68a2SToomas Soome /* FALLTHROUGH */ 894ab9e68a2SToomas Soome case COPY_: 895ab9e68a2SToomas Soome state->mode = COPY; 896ab9e68a2SToomas Soome /* FALLTHROUGH */ 897ab9e68a2SToomas Soome case COPY: 898ab9e68a2SToomas Soome copy = state->length; 899ab9e68a2SToomas Soome if (copy) { 900ab9e68a2SToomas Soome if (copy > have) copy = have; 901ab9e68a2SToomas Soome if (copy > left) copy = left; 902ab9e68a2SToomas Soome if (copy == 0) goto inf_leave; 903ab9e68a2SToomas Soome zmemcpy(put, next, copy); 904ab9e68a2SToomas Soome have -= copy; 905ab9e68a2SToomas Soome next += copy; 906ab9e68a2SToomas Soome left -= copy; 907ab9e68a2SToomas Soome put += copy; 908ab9e68a2SToomas Soome state->length -= copy; 909ab9e68a2SToomas Soome break; 910ab9e68a2SToomas Soome } 911ab9e68a2SToomas Soome Tracev((stderr, "inflate: stored end\n")); 912ab9e68a2SToomas Soome state->mode = TYPE; 913ab9e68a2SToomas Soome break; 914ab9e68a2SToomas Soome case TABLE: 915ab9e68a2SToomas Soome NEEDBITS(14); 916ab9e68a2SToomas Soome state->nlen = BITS(5) + 257; 917ab9e68a2SToomas Soome DROPBITS(5); 918ab9e68a2SToomas Soome state->ndist = BITS(5) + 1; 919ab9e68a2SToomas Soome DROPBITS(5); 920ab9e68a2SToomas Soome state->ncode = BITS(4) + 4; 921ab9e68a2SToomas Soome DROPBITS(4); 922ab9e68a2SToomas Soome #ifndef PKZIP_BUG_WORKAROUND 923ab9e68a2SToomas Soome if (state->nlen > 286 || state->ndist > 30) { 924ab9e68a2SToomas Soome strm->msg = (char *)"too many length or distance symbols"; 925ab9e68a2SToomas Soome state->mode = BAD; 926ab9e68a2SToomas Soome break; 927ab9e68a2SToomas Soome } 928ab9e68a2SToomas Soome #endif 929ab9e68a2SToomas Soome Tracev((stderr, "inflate: table sizes ok\n")); 930ab9e68a2SToomas Soome state->have = 0; 931ab9e68a2SToomas Soome state->mode = LENLENS; 93264c3d159SToomas Soome /* fallthrough */ 933ab9e68a2SToomas Soome case LENLENS: 934ab9e68a2SToomas Soome while (state->have < state->ncode) { 935ab9e68a2SToomas Soome NEEDBITS(3); 936ab9e68a2SToomas Soome state->lens[order[state->have++]] = (unsigned short)BITS(3); 937ab9e68a2SToomas Soome DROPBITS(3); 938ab9e68a2SToomas Soome } 939ab9e68a2SToomas Soome while (state->have < 19) 940ab9e68a2SToomas Soome state->lens[order[state->have++]] = 0; 941ab9e68a2SToomas Soome state->next = state->codes; 942ab9e68a2SToomas Soome state->lencode = (const code FAR *)(state->next); 943ab9e68a2SToomas Soome state->lenbits = 7; 944ab9e68a2SToomas Soome ret = inflate_table(CODES, state->lens, 19, &(state->next), 945ab9e68a2SToomas Soome &(state->lenbits), state->work); 946ab9e68a2SToomas Soome if (ret) { 947ab9e68a2SToomas Soome strm->msg = (char *)"invalid code lengths set"; 948ab9e68a2SToomas Soome state->mode = BAD; 949ab9e68a2SToomas Soome break; 950ab9e68a2SToomas Soome } 951ab9e68a2SToomas Soome Tracev((stderr, "inflate: code lengths ok\n")); 952ab9e68a2SToomas Soome state->have = 0; 953ab9e68a2SToomas Soome state->mode = CODELENS; 95464c3d159SToomas Soome /* fallthrough */ 955ab9e68a2SToomas Soome case CODELENS: 956ab9e68a2SToomas Soome while (state->have < state->nlen + state->ndist) { 957ab9e68a2SToomas Soome for (;;) { 958ab9e68a2SToomas Soome here = state->lencode[BITS(state->lenbits)]; 959ab9e68a2SToomas Soome if ((unsigned)(here.bits) <= bits) break; 960ab9e68a2SToomas Soome PULLBYTE(); 961ab9e68a2SToomas Soome } 962ab9e68a2SToomas Soome if (here.val < 16) { 963ab9e68a2SToomas Soome DROPBITS(here.bits); 964ab9e68a2SToomas Soome state->lens[state->have++] = here.val; 965ab9e68a2SToomas Soome } 966ab9e68a2SToomas Soome else { 967ab9e68a2SToomas Soome if (here.val == 16) { 968ab9e68a2SToomas Soome NEEDBITS(here.bits + 2); 969ab9e68a2SToomas Soome DROPBITS(here.bits); 970ab9e68a2SToomas Soome if (state->have == 0) { 971ab9e68a2SToomas Soome strm->msg = (char *)"invalid bit length repeat"; 972ab9e68a2SToomas Soome state->mode = BAD; 973ab9e68a2SToomas Soome break; 974ab9e68a2SToomas Soome } 975ab9e68a2SToomas Soome len = state->lens[state->have - 1]; 976ab9e68a2SToomas Soome copy = 3 + BITS(2); 977ab9e68a2SToomas Soome DROPBITS(2); 978ab9e68a2SToomas Soome } 979ab9e68a2SToomas Soome else if (here.val == 17) { 980ab9e68a2SToomas Soome NEEDBITS(here.bits + 3); 981ab9e68a2SToomas Soome DROPBITS(here.bits); 982ab9e68a2SToomas Soome len = 0; 983ab9e68a2SToomas Soome copy = 3 + BITS(3); 984ab9e68a2SToomas Soome DROPBITS(3); 985ab9e68a2SToomas Soome } 986ab9e68a2SToomas Soome else { 987ab9e68a2SToomas Soome NEEDBITS(here.bits + 7); 988ab9e68a2SToomas Soome DROPBITS(here.bits); 989ab9e68a2SToomas Soome len = 0; 990ab9e68a2SToomas Soome copy = 11 + BITS(7); 991ab9e68a2SToomas Soome DROPBITS(7); 992ab9e68a2SToomas Soome } 993ab9e68a2SToomas Soome if (state->have + copy > state->nlen + state->ndist) { 994ab9e68a2SToomas Soome strm->msg = (char *)"invalid bit length repeat"; 995ab9e68a2SToomas Soome state->mode = BAD; 996ab9e68a2SToomas Soome break; 997ab9e68a2SToomas Soome } 998ab9e68a2SToomas Soome while (copy--) 999ab9e68a2SToomas Soome state->lens[state->have++] = (unsigned short)len; 1000ab9e68a2SToomas Soome } 1001ab9e68a2SToomas Soome } 1002ab9e68a2SToomas Soome 1003ab9e68a2SToomas Soome /* handle error breaks in while */ 1004ab9e68a2SToomas Soome if (state->mode == BAD) break; 1005ab9e68a2SToomas Soome 1006ab9e68a2SToomas Soome /* check for end-of-block code (better have one) */ 1007ab9e68a2SToomas Soome if (state->lens[256] == 0) { 1008ab9e68a2SToomas Soome strm->msg = (char *)"invalid code -- missing end-of-block"; 1009ab9e68a2SToomas Soome state->mode = BAD; 1010ab9e68a2SToomas Soome break; 1011ab9e68a2SToomas Soome } 1012ab9e68a2SToomas Soome 1013ab9e68a2SToomas Soome /* build code tables -- note: do not change the lenbits or distbits 1014ab9e68a2SToomas Soome values here (9 and 6) without reading the comments in inftrees.h 1015ab9e68a2SToomas Soome concerning the ENOUGH constants, which depend on those values */ 1016ab9e68a2SToomas Soome state->next = state->codes; 1017ab9e68a2SToomas Soome state->lencode = (const code FAR *)(state->next); 1018ab9e68a2SToomas Soome state->lenbits = 9; 1019ab9e68a2SToomas Soome ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), 1020ab9e68a2SToomas Soome &(state->lenbits), state->work); 1021ab9e68a2SToomas Soome if (ret) { 1022ab9e68a2SToomas Soome strm->msg = (char *)"invalid literal/lengths set"; 1023ab9e68a2SToomas Soome state->mode = BAD; 1024ab9e68a2SToomas Soome break; 1025ab9e68a2SToomas Soome } 1026ab9e68a2SToomas Soome state->distcode = (const code FAR *)(state->next); 1027ab9e68a2SToomas Soome state->distbits = 6; 1028ab9e68a2SToomas Soome ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, 1029ab9e68a2SToomas Soome &(state->next), &(state->distbits), state->work); 1030ab9e68a2SToomas Soome if (ret) { 1031ab9e68a2SToomas Soome strm->msg = (char *)"invalid distances set"; 1032ab9e68a2SToomas Soome state->mode = BAD; 1033ab9e68a2SToomas Soome break; 1034ab9e68a2SToomas Soome } 1035ab9e68a2SToomas Soome Tracev((stderr, "inflate: codes ok\n")); 1036ab9e68a2SToomas Soome state->mode = LEN_; 1037ab9e68a2SToomas Soome if (flush == Z_TREES) goto inf_leave; 1038ab9e68a2SToomas Soome /* FALLTHROUGH */ 1039ab9e68a2SToomas Soome case LEN_: 1040ab9e68a2SToomas Soome state->mode = LEN; 1041ab9e68a2SToomas Soome /* FALLTHROUGH */ 1042ab9e68a2SToomas Soome case LEN: 1043ab9e68a2SToomas Soome if (have >= 6 && left >= 258) { 1044ab9e68a2SToomas Soome RESTORE(); 1045ab9e68a2SToomas Soome inflate_fast(strm, out); 1046ab9e68a2SToomas Soome LOAD(); 1047ab9e68a2SToomas Soome if (state->mode == TYPE) 1048ab9e68a2SToomas Soome state->back = -1; 1049ab9e68a2SToomas Soome break; 1050ab9e68a2SToomas Soome } 1051ab9e68a2SToomas Soome state->back = 0; 1052ab9e68a2SToomas Soome for (;;) { 1053ab9e68a2SToomas Soome here = state->lencode[BITS(state->lenbits)]; 1054ab9e68a2SToomas Soome if ((unsigned)(here.bits) <= bits) break; 1055ab9e68a2SToomas Soome PULLBYTE(); 1056ab9e68a2SToomas Soome } 1057ab9e68a2SToomas Soome if (here.op && (here.op & 0xf0) == 0) { 1058ab9e68a2SToomas Soome last = here; 1059ab9e68a2SToomas Soome for (;;) { 1060ab9e68a2SToomas Soome here = state->lencode[last.val + 1061ab9e68a2SToomas Soome (BITS(last.bits + last.op) >> last.bits)]; 1062ab9e68a2SToomas Soome if ((unsigned)(last.bits + here.bits) <= bits) break; 1063ab9e68a2SToomas Soome PULLBYTE(); 1064ab9e68a2SToomas Soome } 1065ab9e68a2SToomas Soome DROPBITS(last.bits); 1066ab9e68a2SToomas Soome state->back += last.bits; 1067ab9e68a2SToomas Soome } 1068ab9e68a2SToomas Soome DROPBITS(here.bits); 1069ab9e68a2SToomas Soome state->back += here.bits; 1070ab9e68a2SToomas Soome state->length = (unsigned)here.val; 1071ab9e68a2SToomas Soome if ((int)(here.op) == 0) { 1072ab9e68a2SToomas Soome Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? 1073ab9e68a2SToomas Soome "inflate: literal '%c'\n" : 1074ab9e68a2SToomas Soome "inflate: literal 0x%02x\n", here.val)); 1075ab9e68a2SToomas Soome state->mode = LIT; 1076ab9e68a2SToomas Soome break; 1077ab9e68a2SToomas Soome } 1078ab9e68a2SToomas Soome if (here.op & 32) { 1079ab9e68a2SToomas Soome Tracevv((stderr, "inflate: end of block\n")); 1080ab9e68a2SToomas Soome state->back = -1; 1081ab9e68a2SToomas Soome state->mode = TYPE; 1082ab9e68a2SToomas Soome break; 1083ab9e68a2SToomas Soome } 1084ab9e68a2SToomas Soome if (here.op & 64) { 1085ab9e68a2SToomas Soome strm->msg = (char *)"invalid literal/length code"; 1086ab9e68a2SToomas Soome state->mode = BAD; 1087ab9e68a2SToomas Soome break; 1088ab9e68a2SToomas Soome } 1089ab9e68a2SToomas Soome state->extra = (unsigned)(here.op) & 15; 1090ab9e68a2SToomas Soome state->mode = LENEXT; 1091ab9e68a2SToomas Soome /* FALLTHROUGH */ 1092ab9e68a2SToomas Soome case LENEXT: 1093ab9e68a2SToomas Soome if (state->extra) { 1094ab9e68a2SToomas Soome NEEDBITS(state->extra); 1095ab9e68a2SToomas Soome state->length += BITS(state->extra); 1096ab9e68a2SToomas Soome DROPBITS(state->extra); 1097ab9e68a2SToomas Soome state->back += state->extra; 1098ab9e68a2SToomas Soome } 1099ab9e68a2SToomas Soome Tracevv((stderr, "inflate: length %u\n", state->length)); 1100ab9e68a2SToomas Soome state->was = state->length; 1101ab9e68a2SToomas Soome state->mode = DIST; 1102ab9e68a2SToomas Soome /* FALLTHROUGH */ 1103ab9e68a2SToomas Soome case DIST: 1104ab9e68a2SToomas Soome for (;;) { 1105ab9e68a2SToomas Soome here = state->distcode[BITS(state->distbits)]; 1106ab9e68a2SToomas Soome if ((unsigned)(here.bits) <= bits) break; 1107ab9e68a2SToomas Soome PULLBYTE(); 1108ab9e68a2SToomas Soome } 1109ab9e68a2SToomas Soome if ((here.op & 0xf0) == 0) { 1110ab9e68a2SToomas Soome last = here; 1111ab9e68a2SToomas Soome for (;;) { 1112ab9e68a2SToomas Soome here = state->distcode[last.val + 1113ab9e68a2SToomas Soome (BITS(last.bits + last.op) >> last.bits)]; 1114ab9e68a2SToomas Soome if ((unsigned)(last.bits + here.bits) <= bits) break; 1115ab9e68a2SToomas Soome PULLBYTE(); 1116ab9e68a2SToomas Soome } 1117ab9e68a2SToomas Soome DROPBITS(last.bits); 1118ab9e68a2SToomas Soome state->back += last.bits; 1119ab9e68a2SToomas Soome } 1120ab9e68a2SToomas Soome DROPBITS(here.bits); 1121ab9e68a2SToomas Soome state->back += here.bits; 1122ab9e68a2SToomas Soome if (here.op & 64) { 1123ab9e68a2SToomas Soome strm->msg = (char *)"invalid distance code"; 1124ab9e68a2SToomas Soome state->mode = BAD; 1125ab9e68a2SToomas Soome break; 1126ab9e68a2SToomas Soome } 1127ab9e68a2SToomas Soome state->offset = (unsigned)here.val; 1128ab9e68a2SToomas Soome state->extra = (unsigned)(here.op) & 15; 1129ab9e68a2SToomas Soome state->mode = DISTEXT; 1130ab9e68a2SToomas Soome /* FALLTHROUGH */ 1131ab9e68a2SToomas Soome case DISTEXT: 1132ab9e68a2SToomas Soome if (state->extra) { 1133ab9e68a2SToomas Soome NEEDBITS(state->extra); 1134ab9e68a2SToomas Soome state->offset += BITS(state->extra); 1135ab9e68a2SToomas Soome DROPBITS(state->extra); 1136ab9e68a2SToomas Soome state->back += state->extra; 1137ab9e68a2SToomas Soome } 1138ab9e68a2SToomas Soome #ifdef INFLATE_STRICT 1139ab9e68a2SToomas Soome if (state->offset > state->dmax) { 1140ab9e68a2SToomas Soome strm->msg = (char *)"invalid distance too far back"; 1141ab9e68a2SToomas Soome state->mode = BAD; 1142ab9e68a2SToomas Soome break; 1143ab9e68a2SToomas Soome } 1144ab9e68a2SToomas Soome #endif 1145ab9e68a2SToomas Soome Tracevv((stderr, "inflate: distance %u\n", state->offset)); 1146ab9e68a2SToomas Soome state->mode = MATCH; 1147ab9e68a2SToomas Soome /* FALLTHROUGH */ 1148ab9e68a2SToomas Soome case MATCH: 1149ab9e68a2SToomas Soome if (left == 0) goto inf_leave; 1150ab9e68a2SToomas Soome copy = out - left; 1151ab9e68a2SToomas Soome if (state->offset > copy) { /* copy from window */ 1152ab9e68a2SToomas Soome copy = state->offset - copy; 1153ab9e68a2SToomas Soome if (copy > state->whave) { 1154ab9e68a2SToomas Soome if (state->sane) { 1155ab9e68a2SToomas Soome strm->msg = (char *)"invalid distance too far back"; 1156ab9e68a2SToomas Soome state->mode = BAD; 1157ab9e68a2SToomas Soome break; 1158ab9e68a2SToomas Soome } 1159ab9e68a2SToomas Soome #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR 1160ab9e68a2SToomas Soome Trace((stderr, "inflate.c too far\n")); 1161ab9e68a2SToomas Soome copy -= state->whave; 1162ab9e68a2SToomas Soome if (copy > state->length) copy = state->length; 1163ab9e68a2SToomas Soome if (copy > left) copy = left; 1164ab9e68a2SToomas Soome left -= copy; 1165ab9e68a2SToomas Soome state->length -= copy; 1166ab9e68a2SToomas Soome do { 1167ab9e68a2SToomas Soome *put++ = 0; 1168ab9e68a2SToomas Soome } while (--copy); 1169ab9e68a2SToomas Soome if (state->length == 0) state->mode = LEN; 1170ab9e68a2SToomas Soome break; 1171ab9e68a2SToomas Soome #endif 1172ab9e68a2SToomas Soome } 1173ab9e68a2SToomas Soome if (copy > state->wnext) { 1174ab9e68a2SToomas Soome copy -= state->wnext; 1175ab9e68a2SToomas Soome from = state->window + (state->wsize - copy); 1176ab9e68a2SToomas Soome } 1177ab9e68a2SToomas Soome else 1178ab9e68a2SToomas Soome from = state->window + (state->wnext - copy); 1179ab9e68a2SToomas Soome if (copy > state->length) copy = state->length; 1180ab9e68a2SToomas Soome } 1181ab9e68a2SToomas Soome else { /* copy from output */ 1182ab9e68a2SToomas Soome from = put - state->offset; 1183ab9e68a2SToomas Soome copy = state->length; 1184ab9e68a2SToomas Soome } 1185ab9e68a2SToomas Soome if (copy > left) copy = left; 1186ab9e68a2SToomas Soome left -= copy; 1187ab9e68a2SToomas Soome state->length -= copy; 1188ab9e68a2SToomas Soome do { 1189ab9e68a2SToomas Soome *put++ = *from++; 1190ab9e68a2SToomas Soome } while (--copy); 1191ab9e68a2SToomas Soome if (state->length == 0) state->mode = LEN; 1192ab9e68a2SToomas Soome break; 1193ab9e68a2SToomas Soome case LIT: 1194ab9e68a2SToomas Soome if (left == 0) goto inf_leave; 1195ab9e68a2SToomas Soome *put++ = (unsigned char)(state->length); 1196ab9e68a2SToomas Soome left--; 1197ab9e68a2SToomas Soome state->mode = LEN; 1198ab9e68a2SToomas Soome break; 1199ab9e68a2SToomas Soome case CHECK: 1200ab9e68a2SToomas Soome if (state->wrap) { 1201ab9e68a2SToomas Soome NEEDBITS(32); 1202ab9e68a2SToomas Soome out -= left; 1203ab9e68a2SToomas Soome strm->total_out += out; 1204ab9e68a2SToomas Soome state->total += out; 1205ab9e68a2SToomas Soome if ((state->wrap & 4) && out) 1206ab9e68a2SToomas Soome strm->adler = state->check = 120764c3d159SToomas Soome UPDATE_CHECK(state->check, put - out, out); 1208ab9e68a2SToomas Soome out = left; 1209ab9e68a2SToomas Soome if ((state->wrap & 4) && ( 1210ab9e68a2SToomas Soome #ifdef GUNZIP 1211ab9e68a2SToomas Soome state->flags ? hold : 1212ab9e68a2SToomas Soome #endif 1213ab9e68a2SToomas Soome ZSWAP32(hold)) != state->check) { 1214ab9e68a2SToomas Soome strm->msg = (char *)"incorrect data check"; 1215ab9e68a2SToomas Soome state->mode = BAD; 1216ab9e68a2SToomas Soome break; 1217ab9e68a2SToomas Soome } 1218ab9e68a2SToomas Soome INITBITS(); 1219ab9e68a2SToomas Soome Tracev((stderr, "inflate: check matches trailer\n")); 1220ab9e68a2SToomas Soome } 1221ab9e68a2SToomas Soome #ifdef GUNZIP 1222ab9e68a2SToomas Soome state->mode = LENGTH; 1223ab9e68a2SToomas Soome /* FALLTHROUGH */ 1224ab9e68a2SToomas Soome case LENGTH: 1225ab9e68a2SToomas Soome if (state->wrap && state->flags) { 1226ab9e68a2SToomas Soome NEEDBITS(32); 122764c3d159SToomas Soome if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) { 1228ab9e68a2SToomas Soome strm->msg = (char *)"incorrect length check"; 1229ab9e68a2SToomas Soome state->mode = BAD; 1230ab9e68a2SToomas Soome break; 1231ab9e68a2SToomas Soome } 1232ab9e68a2SToomas Soome INITBITS(); 1233ab9e68a2SToomas Soome Tracev((stderr, "inflate: length matches trailer\n")); 1234ab9e68a2SToomas Soome } 1235ab9e68a2SToomas Soome #endif 1236ab9e68a2SToomas Soome state->mode = DONE; 1237ab9e68a2SToomas Soome /* FALLTHROUGH */ 1238ab9e68a2SToomas Soome case DONE: 1239ab9e68a2SToomas Soome ret = Z_STREAM_END; 1240ab9e68a2SToomas Soome goto inf_leave; 1241ab9e68a2SToomas Soome case BAD: 1242ab9e68a2SToomas Soome ret = Z_DATA_ERROR; 1243ab9e68a2SToomas Soome goto inf_leave; 1244ab9e68a2SToomas Soome case MEM: 1245ab9e68a2SToomas Soome return Z_MEM_ERROR; 1246ab9e68a2SToomas Soome case SYNC: 124764c3d159SToomas Soome /* fallthrough */ 1248ab9e68a2SToomas Soome default: 1249ab9e68a2SToomas Soome return Z_STREAM_ERROR; 1250ab9e68a2SToomas Soome } 1251ab9e68a2SToomas Soome 1252ab9e68a2SToomas Soome /* 1253ab9e68a2SToomas Soome Return from inflate(), updating the total counts and the check value. 1254ab9e68a2SToomas Soome If there was no progress during the inflate() call, return a buffer 1255ab9e68a2SToomas Soome error. Call updatewindow() to create and/or update the window state. 1256ab9e68a2SToomas Soome Note: a memory error from inflate() is non-recoverable. 1257ab9e68a2SToomas Soome */ 1258ab9e68a2SToomas Soome inf_leave: 1259ab9e68a2SToomas Soome RESTORE(); 1260ab9e68a2SToomas Soome if (state->wsize || (out != strm->avail_out && state->mode < BAD && 1261ab9e68a2SToomas Soome (state->mode < CHECK || flush != Z_FINISH))) 1262ab9e68a2SToomas Soome if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { 1263ab9e68a2SToomas Soome state->mode = MEM; 1264ab9e68a2SToomas Soome return Z_MEM_ERROR; 1265ab9e68a2SToomas Soome } 1266ab9e68a2SToomas Soome in -= strm->avail_in; 1267ab9e68a2SToomas Soome out -= strm->avail_out; 1268ab9e68a2SToomas Soome strm->total_in += in; 1269ab9e68a2SToomas Soome strm->total_out += out; 1270ab9e68a2SToomas Soome state->total += out; 1271ab9e68a2SToomas Soome if ((state->wrap & 4) && out) 1272ab9e68a2SToomas Soome strm->adler = state->check = 127364c3d159SToomas Soome UPDATE_CHECK(state->check, strm->next_out - out, out); 1274ab9e68a2SToomas Soome strm->data_type = (int)state->bits + (state->last ? 64 : 0) + 1275ab9e68a2SToomas Soome (state->mode == TYPE ? 128 : 0) + 1276ab9e68a2SToomas Soome (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); 1277ab9e68a2SToomas Soome if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) 1278ab9e68a2SToomas Soome ret = Z_BUF_ERROR; 1279ab9e68a2SToomas Soome return ret; 1280ab9e68a2SToomas Soome } 1281ab9e68a2SToomas Soome 1282ab9e68a2SToomas Soome int ZEXPORT inflateEnd(z_streamp strm) 1283ab9e68a2SToomas Soome { 1284ab9e68a2SToomas Soome struct inflate_state FAR *state; 1285ab9e68a2SToomas Soome if (inflateStateCheck(strm)) 1286ab9e68a2SToomas Soome return Z_STREAM_ERROR; 1287ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1288ab9e68a2SToomas Soome if (state->window != Z_NULL) ZFREE(strm, state->window); 1289ab9e68a2SToomas Soome ZFREE(strm, strm->state); 1290ab9e68a2SToomas Soome strm->state = Z_NULL; 1291ab9e68a2SToomas Soome Tracev((stderr, "inflate: end\n")); 1292ab9e68a2SToomas Soome return Z_OK; 1293ab9e68a2SToomas Soome } 1294ab9e68a2SToomas Soome 1295ab9e68a2SToomas Soome int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary, 1296ab9e68a2SToomas Soome uInt *dictLength) 1297ab9e68a2SToomas Soome { 1298ab9e68a2SToomas Soome struct inflate_state FAR *state; 1299ab9e68a2SToomas Soome 1300ab9e68a2SToomas Soome /* check state */ 1301ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 1302ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1303ab9e68a2SToomas Soome 1304ab9e68a2SToomas Soome /* copy dictionary */ 1305ab9e68a2SToomas Soome if (state->whave && dictionary != Z_NULL) { 1306ab9e68a2SToomas Soome zmemcpy(dictionary, state->window + state->wnext, 1307ab9e68a2SToomas Soome state->whave - state->wnext); 1308ab9e68a2SToomas Soome zmemcpy(dictionary + state->whave - state->wnext, 1309ab9e68a2SToomas Soome state->window, state->wnext); 1310ab9e68a2SToomas Soome } 1311ab9e68a2SToomas Soome if (dictLength != Z_NULL) 1312ab9e68a2SToomas Soome *dictLength = state->whave; 1313ab9e68a2SToomas Soome return Z_OK; 1314ab9e68a2SToomas Soome } 1315ab9e68a2SToomas Soome 1316ab9e68a2SToomas Soome int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, 1317ab9e68a2SToomas Soome uInt dictLength) 1318ab9e68a2SToomas Soome { 1319ab9e68a2SToomas Soome struct inflate_state FAR *state; 1320ab9e68a2SToomas Soome unsigned long dictid; 1321ab9e68a2SToomas Soome int ret; 1322ab9e68a2SToomas Soome 1323ab9e68a2SToomas Soome /* check state */ 1324ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 1325ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1326ab9e68a2SToomas Soome if (state->wrap != 0 && state->mode != DICT) 1327ab9e68a2SToomas Soome return Z_STREAM_ERROR; 1328ab9e68a2SToomas Soome 1329ab9e68a2SToomas Soome /* check for correct dictionary identifier */ 1330ab9e68a2SToomas Soome if (state->mode == DICT) { 1331ab9e68a2SToomas Soome dictid = adler32(0L, Z_NULL, 0); 1332ab9e68a2SToomas Soome dictid = adler32(dictid, dictionary, dictLength); 1333ab9e68a2SToomas Soome if (dictid != state->check) 1334ab9e68a2SToomas Soome return Z_DATA_ERROR; 1335ab9e68a2SToomas Soome } 1336ab9e68a2SToomas Soome 1337ab9e68a2SToomas Soome /* copy dictionary to window using updatewindow(), which will amend the 1338ab9e68a2SToomas Soome existing dictionary if appropriate */ 1339ab9e68a2SToomas Soome ret = updatewindow(strm, dictionary + dictLength, dictLength); 1340ab9e68a2SToomas Soome if (ret) { 1341ab9e68a2SToomas Soome state->mode = MEM; 1342ab9e68a2SToomas Soome return Z_MEM_ERROR; 1343ab9e68a2SToomas Soome } 1344ab9e68a2SToomas Soome state->havedict = 1; 1345ab9e68a2SToomas Soome Tracev((stderr, "inflate: dictionary set\n")); 1346ab9e68a2SToomas Soome return Z_OK; 1347ab9e68a2SToomas Soome } 1348ab9e68a2SToomas Soome 1349ab9e68a2SToomas Soome int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) 1350ab9e68a2SToomas Soome { 1351ab9e68a2SToomas Soome struct inflate_state FAR *state; 1352ab9e68a2SToomas Soome 1353ab9e68a2SToomas Soome /* check state */ 1354ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 1355ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1356ab9e68a2SToomas Soome if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; 1357ab9e68a2SToomas Soome 1358ab9e68a2SToomas Soome /* save header structure */ 1359ab9e68a2SToomas Soome state->head = head; 1360ab9e68a2SToomas Soome head->done = 0; 1361ab9e68a2SToomas Soome return Z_OK; 1362ab9e68a2SToomas Soome } 1363ab9e68a2SToomas Soome 1364ab9e68a2SToomas Soome /* 1365ab9e68a2SToomas Soome Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found 1366ab9e68a2SToomas Soome or when out of input. When called, *have is the number of pattern bytes 1367ab9e68a2SToomas Soome found in order so far, in 0..3. On return *have is updated to the new 1368ab9e68a2SToomas Soome state. If on return *have equals four, then the pattern was found and the 1369ab9e68a2SToomas Soome return value is how many bytes were read including the last byte of the 1370ab9e68a2SToomas Soome pattern. If *have is less than four, then the pattern has not been found 1371ab9e68a2SToomas Soome yet and the return value is len. In the latter case, syncsearch() can be 1372ab9e68a2SToomas Soome called again with more data and the *have state. *have is initialized to 1373ab9e68a2SToomas Soome zero for the first call. 1374ab9e68a2SToomas Soome */ 1375ab9e68a2SToomas Soome local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf, 1376ab9e68a2SToomas Soome unsigned len) 1377ab9e68a2SToomas Soome { 1378ab9e68a2SToomas Soome unsigned got; 1379ab9e68a2SToomas Soome unsigned next; 1380ab9e68a2SToomas Soome 1381ab9e68a2SToomas Soome got = *have; 1382ab9e68a2SToomas Soome next = 0; 1383ab9e68a2SToomas Soome while (next < len && got < 4) { 1384ab9e68a2SToomas Soome if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) 1385ab9e68a2SToomas Soome got++; 1386ab9e68a2SToomas Soome else if (buf[next]) 1387ab9e68a2SToomas Soome got = 0; 1388ab9e68a2SToomas Soome else 1389ab9e68a2SToomas Soome got = 4 - got; 1390ab9e68a2SToomas Soome next++; 1391ab9e68a2SToomas Soome } 1392ab9e68a2SToomas Soome *have = got; 1393ab9e68a2SToomas Soome return next; 1394ab9e68a2SToomas Soome } 1395ab9e68a2SToomas Soome 1396ab9e68a2SToomas Soome int ZEXPORT inflateSync(z_streamp strm) 1397ab9e68a2SToomas Soome { 1398ab9e68a2SToomas Soome unsigned len; /* number of bytes to look at or looked at */ 139964c3d159SToomas Soome int flags; /* temporary to save header status */ 1400ab9e68a2SToomas Soome unsigned long in, out; /* temporary to save total_in and total_out */ 1401ab9e68a2SToomas Soome unsigned char buf[4]; /* to restore bit buffer to byte string */ 1402ab9e68a2SToomas Soome struct inflate_state FAR *state; 1403ab9e68a2SToomas Soome 1404ab9e68a2SToomas Soome /* check parameters */ 1405ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 1406ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1407ab9e68a2SToomas Soome if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; 1408ab9e68a2SToomas Soome 1409ab9e68a2SToomas Soome /* if first time, start search in bit buffer */ 1410ab9e68a2SToomas Soome if (state->mode != SYNC) { 1411ab9e68a2SToomas Soome state->mode = SYNC; 1412ab9e68a2SToomas Soome state->hold <<= state->bits & 7; 1413ab9e68a2SToomas Soome state->bits -= state->bits & 7; 1414ab9e68a2SToomas Soome len = 0; 1415ab9e68a2SToomas Soome while (state->bits >= 8) { 1416ab9e68a2SToomas Soome buf[len++] = (unsigned char)(state->hold); 1417ab9e68a2SToomas Soome state->hold >>= 8; 1418ab9e68a2SToomas Soome state->bits -= 8; 1419ab9e68a2SToomas Soome } 1420ab9e68a2SToomas Soome state->have = 0; 1421ab9e68a2SToomas Soome syncsearch(&(state->have), buf, len); 1422ab9e68a2SToomas Soome } 1423ab9e68a2SToomas Soome 1424ab9e68a2SToomas Soome /* search available input */ 1425ab9e68a2SToomas Soome len = syncsearch(&(state->have), strm->next_in, strm->avail_in); 1426ab9e68a2SToomas Soome strm->avail_in -= len; 1427ab9e68a2SToomas Soome strm->next_in += len; 1428ab9e68a2SToomas Soome strm->total_in += len; 1429ab9e68a2SToomas Soome 1430ab9e68a2SToomas Soome /* return no joy or set up to restart inflate() on a new block */ 1431ab9e68a2SToomas Soome if (state->have != 4) return Z_DATA_ERROR; 143264c3d159SToomas Soome if (state->flags == -1) 143364c3d159SToomas Soome state->wrap = 0; /* if no header yet, treat as raw */ 143464c3d159SToomas Soome else 143564c3d159SToomas Soome state->wrap &= ~4; /* no point in computing a check value now */ 143664c3d159SToomas Soome flags = state->flags; 1437ab9e68a2SToomas Soome in = strm->total_in; out = strm->total_out; 1438ab9e68a2SToomas Soome inflateReset(strm); 1439ab9e68a2SToomas Soome strm->total_in = in; strm->total_out = out; 144064c3d159SToomas Soome state->flags = flags; 1441ab9e68a2SToomas Soome state->mode = TYPE; 1442ab9e68a2SToomas Soome return Z_OK; 1443ab9e68a2SToomas Soome } 1444ab9e68a2SToomas Soome 1445ab9e68a2SToomas Soome /* 1446ab9e68a2SToomas Soome Returns true if inflate is currently at the end of a block generated by 1447ab9e68a2SToomas Soome Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP 1448ab9e68a2SToomas Soome implementation to provide an additional safety check. PPP uses 1449ab9e68a2SToomas Soome Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored 1450ab9e68a2SToomas Soome block. When decompressing, PPP checks that at the end of input packet, 1451ab9e68a2SToomas Soome inflate is waiting for these length bytes. 1452ab9e68a2SToomas Soome */ 1453ab9e68a2SToomas Soome int ZEXPORT inflateSyncPoint(z_streamp strm) 1454ab9e68a2SToomas Soome { 1455ab9e68a2SToomas Soome struct inflate_state FAR *state; 1456ab9e68a2SToomas Soome 1457ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 1458ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1459ab9e68a2SToomas Soome return state->mode == STORED && state->bits == 0; 1460ab9e68a2SToomas Soome } 1461ab9e68a2SToomas Soome 1462ab9e68a2SToomas Soome int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) 1463ab9e68a2SToomas Soome { 1464ab9e68a2SToomas Soome struct inflate_state FAR *state; 1465ab9e68a2SToomas Soome struct inflate_state FAR *copy; 1466ab9e68a2SToomas Soome unsigned char FAR *window; 1467ab9e68a2SToomas Soome unsigned wsize; 1468ab9e68a2SToomas Soome 1469ab9e68a2SToomas Soome /* check input */ 1470ab9e68a2SToomas Soome if (inflateStateCheck(source) || dest == Z_NULL) 1471ab9e68a2SToomas Soome return Z_STREAM_ERROR; 1472ab9e68a2SToomas Soome state = (struct inflate_state FAR *)source->state; 1473ab9e68a2SToomas Soome 1474ab9e68a2SToomas Soome /* allocate space */ 1475ab9e68a2SToomas Soome copy = (struct inflate_state FAR *) 1476ab9e68a2SToomas Soome ZALLOC(source, 1, sizeof(struct inflate_state)); 1477ab9e68a2SToomas Soome if (copy == Z_NULL) return Z_MEM_ERROR; 1478ab9e68a2SToomas Soome window = Z_NULL; 1479ab9e68a2SToomas Soome if (state->window != Z_NULL) { 1480ab9e68a2SToomas Soome window = (unsigned char FAR *) 1481ab9e68a2SToomas Soome ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); 1482ab9e68a2SToomas Soome if (window == Z_NULL) { 1483ab9e68a2SToomas Soome ZFREE(source, copy); 1484ab9e68a2SToomas Soome return Z_MEM_ERROR; 1485ab9e68a2SToomas Soome } 1486ab9e68a2SToomas Soome } 1487ab9e68a2SToomas Soome 1488ab9e68a2SToomas Soome /* copy state */ 1489ab9e68a2SToomas Soome zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); 1490ab9e68a2SToomas Soome zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); 1491ab9e68a2SToomas Soome copy->strm = dest; 1492ab9e68a2SToomas Soome if (state->lencode >= state->codes && 1493ab9e68a2SToomas Soome state->lencode <= state->codes + ENOUGH - 1) { 1494ab9e68a2SToomas Soome copy->lencode = copy->codes + (state->lencode - state->codes); 1495ab9e68a2SToomas Soome copy->distcode = copy->codes + (state->distcode - state->codes); 1496ab9e68a2SToomas Soome } 1497ab9e68a2SToomas Soome copy->next = copy->codes + (state->next - state->codes); 1498ab9e68a2SToomas Soome if (window != Z_NULL) { 1499ab9e68a2SToomas Soome wsize = 1U << state->wbits; 1500ab9e68a2SToomas Soome zmemcpy(window, state->window, wsize); 1501ab9e68a2SToomas Soome } 1502ab9e68a2SToomas Soome copy->window = window; 1503ab9e68a2SToomas Soome dest->state = (struct internal_state FAR *)copy; 1504ab9e68a2SToomas Soome return Z_OK; 1505ab9e68a2SToomas Soome } 1506ab9e68a2SToomas Soome 1507ab9e68a2SToomas Soome int ZEXPORT inflateUndermine(z_streamp strm, int subvert) 1508ab9e68a2SToomas Soome { 1509ab9e68a2SToomas Soome struct inflate_state FAR *state; 1510ab9e68a2SToomas Soome 1511ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 1512ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1513ab9e68a2SToomas Soome #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR 1514ab9e68a2SToomas Soome state->sane = !subvert; 1515ab9e68a2SToomas Soome return Z_OK; 1516ab9e68a2SToomas Soome #else 1517ab9e68a2SToomas Soome (void)subvert; 1518ab9e68a2SToomas Soome state->sane = 1; 1519ab9e68a2SToomas Soome return Z_DATA_ERROR; 1520ab9e68a2SToomas Soome #endif 1521ab9e68a2SToomas Soome } 1522ab9e68a2SToomas Soome 1523ab9e68a2SToomas Soome int ZEXPORT inflateValidate(z_streamp strm, int check) 1524ab9e68a2SToomas Soome { 1525ab9e68a2SToomas Soome struct inflate_state FAR *state; 1526ab9e68a2SToomas Soome 1527ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return Z_STREAM_ERROR; 1528ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 152964c3d159SToomas Soome if (check && state->wrap) 1530ab9e68a2SToomas Soome state->wrap |= 4; 1531ab9e68a2SToomas Soome else 1532ab9e68a2SToomas Soome state->wrap &= ~4; 1533ab9e68a2SToomas Soome return Z_OK; 1534ab9e68a2SToomas Soome } 1535ab9e68a2SToomas Soome 1536ab9e68a2SToomas Soome long ZEXPORT inflateMark(z_streamp strm) 1537ab9e68a2SToomas Soome { 1538ab9e68a2SToomas Soome struct inflate_state FAR *state; 1539ab9e68a2SToomas Soome 1540ab9e68a2SToomas Soome if (inflateStateCheck(strm)) 1541ab9e68a2SToomas Soome return -(1L << 16); 1542ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1543ab9e68a2SToomas Soome return (long)(((unsigned long)((long)state->back)) << 16) + 1544ab9e68a2SToomas Soome (state->mode == COPY ? state->length : 1545ab9e68a2SToomas Soome (state->mode == MATCH ? state->was - state->length : 0)); 1546ab9e68a2SToomas Soome } 1547ab9e68a2SToomas Soome 1548ab9e68a2SToomas Soome unsigned long ZEXPORT inflateCodesUsed(z_streamp strm) 1549ab9e68a2SToomas Soome { 1550ab9e68a2SToomas Soome struct inflate_state FAR *state; 1551ab9e68a2SToomas Soome if (inflateStateCheck(strm)) return (unsigned long)-1; 1552ab9e68a2SToomas Soome state = (struct inflate_state FAR *)strm->state; 1553ab9e68a2SToomas Soome return (unsigned long)(state->next - state->codes); 1554ab9e68a2SToomas Soome } 1555