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