error Z_STREAM_ERROR; error Z_STREAM_END; error Z_NEED_DICT; error Z_ERRNO; error Z_STREAM_ERROR; error Z_DATA_ERROR; error Z_MEM_ERROR; error Z_BUF_ERROR; error Z_VERSION_ERROR; pub Flush = enum { NO_FLUSH, PARTIAL_FLUSH, SYNC_FLUSH, FULL_FLUSH, FINISH, BLOCK, TREES, }; const code = struct { /// operation, extra bits, table bits op: u8, /// bits in this part of the code bits: u8, /// offset in table or code value val: u16, }; /// State maintained between inflate() calls -- approximately 7K bytes, not /// including the allocated sliding window, which is up to 32K bytes. const inflate_state = struct { z_stream * strm; /* pointer back to this zlib stream */ inflate_mode mode; /* current inflate mode */ int last; /* true if processing last block */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip, bit 2 true to validate check value */ int havedict; /* true if dictionary provided */ int flags; /* gzip header method and flags (0 if zlib) */ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ unsigned long check; /* protected copy of check value */ unsigned long total; /* protected copy of output count */ gz_headerp head; /* where to save gzip header information */ /* sliding window */ unsigned wbits; /* log base 2 of requested window size */ unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned wnext; /* window write index */ u8 FAR *window; /* allocated sliding window, if needed */ /* bit accumulator */ unsigned long hold; /* input bit accumulator */ unsigned bits; /* number of bits in "in" */ /* for string and stored block copying */ unsigned length; /* literal or length of data to copy */ unsigned offset; /* distance back to copy string from */ /* for table and code decoding */ unsigned extra; /* extra bits needed */ /* fixed and dynamic code tables */ code const FAR *lencode; /* starting table for length/literal codes */ code const FAR *distcode; /* starting table for distance codes */ unsigned lenbits; /* index bits for lencode */ unsigned distbits; /* index bits for distcode */ /* dynamic table building */ unsigned ncode; /* number of code length code lengths */ unsigned nlen; /* number of length code lengths */ unsigned ndist; /* number of distance code lengths */ unsigned have; /* number of code lengths in lens[] */ code FAR *next; /* next available space in codes[] */ unsigned short lens[320]; /* temporary storage for code lengths */ unsigned short work[288]; /* work area for code table building */ code codes[ENOUGH]; /* space for code tables */ int sane; /* if false, allow invalid distance too far */ int back; /* bits back of last unprocessed length/lit */ unsigned was; /* initial length of match */ }; const alloc_func = fn(opaque: &c_void, items: u16, size: u16); const free_func = fn(opaque: &c_void, address: &c_void); const z_stream = struct { /// next input byte next_in: &u8, /// number of bytes available at next_in avail_in: u16, /// total number of input bytes read so far total_in: u32, /// next output byte will go here next_out: &u8, /// remaining free space at next_out avail_out: u16, /// total number of bytes output so far */ total_out: u32, /// last error message, NULL if no error msg: &const u8, /// not visible by applications state: &inflate_state, /// used to allocate the internal state zalloc: alloc_func, /// used to free the internal state zfree: free_func, /// private data object passed to zalloc and zfree opaque: &c_void, /// best guess about the data type: binary or text /// for deflate, or the decoding state for inflate data_type: i32, /// Adler-32 or CRC-32 value of the uncompressed data adler: u32, }; // Possible inflate modes between inflate() calls /// i: waiting for magic header pub const HEAD = 16180; /// i: waiting for method and flags (gzip) pub const FLAGS = 16181; /// i: waiting for modification time (gzip) pub const TIME = 16182; /// i: waiting for extra flags and operating system (gzip) pub const OS = 16183; /// i: waiting for extra length (gzip) pub const EXLEN = 16184; /// i: waiting for extra bytes (gzip) pub const EXTRA = 16185; /// i: waiting for end of file name (gzip) pub const NAME = 16186; /// i: waiting for end of comment (gzip) pub const COMMENT = 16187; /// i: waiting for header crc (gzip) pub const HCRC = 16188; /// i: waiting for dictionary check value pub const DICTID = 16189; /// waiting for inflateSetDictionary() call pub const DICT = 16190; /// i: waiting for type bits, including last-flag bit pub const TYPE = 16191; /// i: same, but skip check to exit inflate on new block pub const TYPEDO = 16192; /// i: waiting for stored size (length and complement) pub const STORED = 16193; /// i/o: same as COPY below, but only first time in pub const COPY_ = 16194; /// i/o: waiting for input or output to copy stored block pub const COPY = 16195; /// i: waiting for dynamic block table lengths pub const TABLE = 16196; /// i: waiting for code length code lengths pub const LENLENS = 16197; /// i: waiting for length/lit and distance code lengths pub const CODELENS = 16198; /// i: same as LEN below, but only first time in pub const LEN_ = 16199; /// i: waiting for length/lit/eob code pub const LEN = 16200; /// i: waiting for length extra bits pub const LENEXT = 16201; /// i: waiting for distance code pub const DIST = 16202; /// i: waiting for distance extra bits pub const DISTEXT = 16203; /// o: waiting for output space to copy string pub const MATCH = 16204; /// o: waiting for output space to write literal pub const LIT = 16205; /// i: waiting for 32-bit check value pub const CHECK = 16206; /// i: waiting for 32-bit length (gzip) pub const LENGTH = 16207; /// finished check, done -- remain here until reset pub const DONE = 16208; /// got a data error -- remain here until reset pub const BAD = 16209; /// got an inflate() memory error -- remain here until reset pub const MEM = 16210; /// looking for synchronization bytes to restart inflate() */ pub const SYNC = 16211; /// inflate() uses a state machine to process as much input data and generate as /// much output data as possible before returning. The state machine is /// structured roughly as follows: /// /// for (;;) switch (state) { /// ... /// case STATEn: /// if (not enough input data or output space to make progress) /// return; /// ... make progress ... /// state = STATEm; /// break; /// ... /// } /// /// so when inflate() is called again, the same case is attempted again, and /// if the appropriate resources are provided, the machine proceeds to the /// next state. The NEEDBITS() macro is usually the way the state evaluates /// whether it can proceed or should return. NEEDBITS() does the return if /// the requested bits are not available. The typical use of the BITS macros /// is: /// /// NEEDBITS(n); /// ... do something with BITS(n) ... /// DROPBITS(n); /// /// where NEEDBITS(n) either returns from inflate() if there isn't enough /// input left to load n bits into the accumulator, or it continues. BITS(n) /// gives the low n bits in the accumulator. When done, DROPBITS(n) drops /// the low n bits off the accumulator. INITBITS() clears the accumulator /// and sets the number of available bits to zero. BYTEBITS() discards just /// enough bits to put the accumulator on a byte boundary. After BYTEBITS() /// and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. /// /// NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return /// if there is no input available. The decoding of variable length codes uses /// PULLBYTE() directly in order to pull just enough bytes to decode the next /// code, and no more. /// /// Some states loop until they get enough input, making sure that enough /// state information is maintained to continue the loop where it left off /// if NEEDBITS() returns in the loop. For example, want, need, and keep /// would all have to actually be part of the saved state in case NEEDBITS() /// returns: /// /// case STATEw: /// while (want < need) { /// NEEDBITS(n); /// keep[want++] = BITS(n); /// DROPBITS(n); /// } /// state = STATEx; /// case STATEx: /// /// As shown above, if the next state is also the next case, then the break /// is omitted. /// /// A state may also return if there is not enough output space available to /// complete that state. Those states are copying stored data, writing a /// literal byte, and copying a matching string. /// /// When returning, a "goto inf_leave" is used to update the total counters, /// update the check value, and determine whether any progress has been made /// during that inflate() call in order to return the proper return code. /// Progress is defined as a change in either strm->avail_in or strm->avail_out. /// When there is a window, goto inf_leave will update the window with the last /// output written. If a goto inf_leave occurs in the middle of decompression /// and there is no window currently, goto inf_leave will create one and copy /// output to the window for the next call of inflate(). /// /// In this implementation, the flush parameter of inflate() only affects the /// return code (per zlib.h). inflate() always writes as much as possible to /// strm->next_out, given the space available and the provided input--the effect /// documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers /// the allocation of and copying into a sliding window until necessary, which /// provides the effect documented in zlib.h for Z_FINISH when the entire input /// stream available. So the only thing the flush parameter actually does is: /// when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it /// will return Z_BUF_ERROR if it has not reached the end of the stream. pub fn inflate(strm: &z_stream, flush: Flush, gunzip: bool) -> %void { // next input var next: &const u8 = undefined; // next output var put: &u8 = undefined; // available input and output var have: u16 = undefined; var left: u16 = undefined; // bit buffer var hold: u32 = undefined; // bits in bit buffer var bits: u16 = undefined; // save starting available input and output var in: u16 = undefined; var out: u16 = undefined; // number of stored or match bytes to copy var copy: u16 = undefined; // where to copy match bytes from var from: &u8 = undefined; // current decoding table entry var here: code = undefined; // parent table entry var last: code = undefined; // length to copy for repeats, bits to drop var len: u16 = undefined; // return code var ret: error = undefined; // buffer for gzip header crc calculation var hbuf: [4]u8 = undefined; // permutation of code lengths const short_order = []u16 = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; if (inflateStateCheck(strm) or strm.next_out == Z_NULL or (strm.next_in == Z_NULL and strm.avail_in != 0)) { return error.Z_STREAM_ERROR; } var state: &inflate_state = strm.state; if (state.mode == TYPE) { state.mode = TYPEDO; // skip check } put = strm.next_out; \ left = strm.avail_out; \ next = strm.next_in; \ have = strm.avail_in; \ hold = state.hold; \ bits = state.bits; \ in = have; out = left; ret = Z_OK; for (;;) switch (state.mode) { case HEAD: if (state.wrap == 0) { state.mode = TYPEDO; break; } NEEDBITS(16); #ifdef GUNZIP if ((state.wrap & 2) && hold == 0x8b1f) { /* gzip header */ if (state.wbits == 0) state.wbits = 15; state.check = crc32(0L, Z_NULL, 0); CRC2(state.check, hold); INITBITS(); state.mode = FLAGS; break; } state.flags = 0; /* expect zlib header */ if (state.head != Z_NULL) state.head.done = -1; if (!(state.wrap & 1) || /* check if zlib header allowed */ #else if ( #endif ((BITS(8) << 8) + (hold >> 8)) % 31) { strm.msg = (char *)"incorrect header check"; state.mode = BAD; break; } if (BITS(4) != Z_DEFLATED) { strm.msg = (char *)"unknown compression method"; state.mode = BAD; break; } DROPBITS(4); len = BITS(4) + 8; if (state.wbits == 0) state.wbits = len; if (len > 15 || len > state.wbits) { strm.msg = (char *)"invalid window size"; state.mode = BAD; break; } state.dmax = 1U << len; Tracev((stderr, "inflate: zlib header ok\n")); strm.adler = state.check = adler32(0L, Z_NULL, 0); state.mode = hold & 0x200 ? DICTID : TYPE; INITBITS(); break; #ifdef GUNZIP case FLAGS: NEEDBITS(16); state.flags = (int)(hold); if ((state.flags & 0xff) != Z_DEFLATED) { strm.msg = (char *)"unknown compression method"; state.mode = BAD; break; } if (state.flags & 0xe000) { strm.msg = (char *)"unknown header flags set"; state.mode = BAD; break; } if (state.head != Z_NULL) state.head.text = (int)((hold >> 8) & 1); if ((state.flags & 0x0200) && (state.wrap & 4)) CRC2(state.check, hold); INITBITS(); state.mode = TIME; case TIME: NEEDBITS(32); if (state.head != Z_NULL) state.head.time = hold; if ((state.flags & 0x0200) && (state.wrap & 4)) CRC4(state.check, hold); INITBITS(); state.mode = OS; case OS: NEEDBITS(16); if (state.head != Z_NULL) { state.head.xflags = (int)(hold & 0xff); state.head.os = (int)(hold >> 8); } if ((state.flags & 0x0200) && (state.wrap & 4)) CRC2(state.check, hold); INITBITS(); state.mode = EXLEN; case EXLEN: if (state.flags & 0x0400) { NEEDBITS(16); state.length = (unsigned)(hold); if (state.head != Z_NULL) state.head.extra_len = (unsigned)hold; if ((state.flags & 0x0200) && (state.wrap & 4)) CRC2(state.check, hold); INITBITS(); } else if (state.head != Z_NULL) state.head.extra = Z_NULL; state.mode = EXTRA; case EXTRA: if (state.flags & 0x0400) { copy = state.length; if (copy > have) copy = have; if (copy) { if (state.head != Z_NULL && state.head.extra != Z_NULL) { len = state.head.extra_len - state.length; zmemcpy(state.head.extra + len, next, len + copy > state.head.extra_max ? state.head.extra_max - len : copy); } if ((state.flags & 0x0200) && (state.wrap & 4)) state.check = crc32(state.check, next, copy); have -= copy; next += copy; state.length -= copy; } if (state.length) goto inf_leave; } state.length = 0; state.mode = NAME; case NAME: if (state.flags & 0x0800) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); if (state.head != Z_NULL && state.head.name != Z_NULL && state.length < state.head.name_max) state.head.name[state.length++] = (Bytef)len; } while (len && copy < have); if ((state.flags & 0x0200) && (state.wrap & 4)) state.check = crc32(state.check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } else if (state.head != Z_NULL) state.head.name = Z_NULL; state.length = 0; state.mode = COMMENT; case COMMENT: if (state.flags & 0x1000) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); if (state.head != Z_NULL && state.head.comment != Z_NULL && state.length < state.head.comm_max) state.head.comment[state.length++] = (Bytef)len; } while (len && copy < have); if ((state.flags & 0x0200) && (state.wrap & 4)) state.check = crc32(state.check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } else if (state.head != Z_NULL) state.head.comment = Z_NULL; state.mode = HCRC; case HCRC: if (state.flags & 0x0200) { NEEDBITS(16); if ((state.wrap & 4) && hold != (state.check & 0xffff)) { strm.msg = (char *)"header crc mismatch"; state.mode = BAD; break; } INITBITS(); } if (state.head != Z_NULL) { state.head.hcrc = (int)((state.flags >> 9) & 1); state.head.done = 1; } strm.adler = state.check = crc32(0L, Z_NULL, 0); state.mode = TYPE; break; #endif case DICTID: NEEDBITS(32); strm.adler = state.check = ZSWAP32(hold); INITBITS(); state.mode = DICT; case DICT: if (state.havedict == 0) { strm.next_out = put; \ strm.avail_out = left; \ strm.next_in = next; \ strm.avail_in = have; \ state.hold = hold; \ state.bits = bits; \ return Z_NEED_DICT; } strm.adler = state.check = adler32(0L, Z_NULL, 0); state.mode = TYPE; case TYPE: if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; case TYPEDO: if (state.last) { BYTEBITS(); state.mode = CHECK; break; } NEEDBITS(3); state.last = BITS(1); DROPBITS(1); switch (BITS(2)) { case 0: /* stored block */ Tracev((stderr, "inflate: stored block%s\n", state.last ? " (last)" : "")); state.mode = STORED; break; case 1: /* fixed block */ fixedtables(state); Tracev((stderr, "inflate: fixed codes block%s\n", state.last ? " (last)" : "")); state.mode = LEN_; /* decode codes */ if (flush == Z_TREES) { DROPBITS(2); goto inf_leave; } break; case 2: /* dynamic block */ Tracev((stderr, "inflate: dynamic codes block%s\n", state.last ? " (last)" : "")); state.mode = TABLE; break; case 3: strm.msg = (char *)"invalid block type"; state.mode = BAD; } DROPBITS(2); break; case STORED: BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { strm.msg = (char *)"invalid stored block lengths"; state.mode = BAD; break; } state.length = (unsigned)hold & 0xffff; Tracev((stderr, "inflate: stored length %u\n", state.length)); INITBITS(); state.mode = COPY_; if (flush == Z_TREES) goto inf_leave; case COPY_: state.mode = COPY; case COPY: copy = state.length; if (copy) { if (copy > have) copy = have; if (copy > left) copy = left; if (copy == 0) goto inf_leave; zmemcpy(put, next, copy); have -= copy; next += copy; left -= copy; put += copy; state.length -= copy; break; } Tracev((stderr, "inflate: stored end\n")); state.mode = TYPE; break; case TABLE: NEEDBITS(14); state.nlen = BITS(5) + 257; DROPBITS(5); state.ndist = BITS(5) + 1; DROPBITS(5); state.ncode = BITS(4) + 4; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state.nlen > 286 || state.ndist > 30) { strm.msg = (char *)"too many length or distance symbols"; state.mode = BAD; break; } #endif Tracev((stderr, "inflate: table sizes ok\n")); state.have = 0; state.mode = LENLENS; case LENLENS: while (state.have < state.ncode) { NEEDBITS(3); state.lens[order[state.have++]] = (unsigned short)BITS(3); DROPBITS(3); } while (state.have < 19) state.lens[order[state.have++]] = 0; state.next = state.codes; state.lencode = (const code FAR *)(state.next); state.lenbits = 7; ret = inflate_table(CODES, state.lens, 19, &(state.next), &(state.lenbits), state.work); if (ret) { strm.msg = (char *)"invalid code lengths set"; state.mode = BAD; break; } Tracev((stderr, "inflate: code lengths ok\n")); state.have = 0; state.mode = CODELENS; case CODELENS: while (state.have < state.nlen + state.ndist) { for (;;) { here = state.lencode[BITS(state.lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.val < 16) { DROPBITS(here.bits); state.lens[state.have++] = here.val; } else { if (here.val == 16) { NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state.have == 0) { strm.msg = (char *)"invalid bit length repeat"; state.mode = BAD; break; } len = state.lens[state.have - 1]; copy = 3 + BITS(2); DROPBITS(2); } else if (here.val == 17) { NEEDBITS(here.bits + 3); DROPBITS(here.bits); len = 0; copy = 3 + BITS(3); DROPBITS(3); } else { NEEDBITS(here.bits + 7); DROPBITS(here.bits); len = 0; copy = 11 + BITS(7); DROPBITS(7); } if (state.have + copy > state.nlen + state.ndist) { strm.msg = (char *)"invalid bit length repeat"; state.mode = BAD; break; } while (copy--) state.lens[state.have++] = (unsigned short)len; } } /* handle error breaks in while */ if (state.mode == BAD) break; /* check for end-of-block code (better have one) */ if (state.lens[256] == 0) { strm.msg = (char *)"invalid code -- missing end-of-block"; state.mode = BAD; break; } /* build code tables -- note: do not change the lenbits or distbits values here (9 and 6) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state.next = state.codes; state.lencode = (const code FAR *)(state.next); state.lenbits = 9; ret = inflate_table(LENS, state.lens, state.nlen, &(state.next), &(state.lenbits), state.work); if (ret) { strm.msg = (char *)"invalid literal/lengths set"; state.mode = BAD; break; } state.distcode = (const code FAR *)(state.next); state.distbits = 6; ret = inflate_table(DISTS, state.lens + state.nlen, state.ndist, &(state.next), &(state.distbits), state.work); if (ret) { strm.msg = (char *)"invalid distances set"; state.mode = BAD; break; } Tracev((stderr, "inflate: codes ok\n")); state.mode = LEN_; if (flush == Z_TREES) goto inf_leave; case LEN_: state.mode = LEN; case LEN: if (have >= 6 && left >= 258) { strm.next_out = put; \ strm.avail_out = left; \ strm.next_in = next; \ strm.avail_in = have; \ state.hold = hold; \ state.bits = bits; \ inflate_fast(strm, out); put = strm.next_out; \ left = strm.avail_out; \ next = strm.next_in; \ have = strm.avail_in; \ hold = state.hold; \ bits = state.bits; \ if (state.mode == TYPE) state.back = -1; break; } state.back = 0; for (;;) { here = state.lencode[BITS(state.lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.op && (here.op & 0xf0) == 0) { last = here; for (;;) { here = state.lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); state.back += last.bits; } DROPBITS(here.bits); state.back += here.bits; state.length = (unsigned)here.val; if ((int)(here.op) == 0) { Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); state.mode = LIT; break; } if (here.op & 32) { Tracevv((stderr, "inflate: end of block\n")); state.back = -1; state.mode = TYPE; break; } if (here.op & 64) { strm.msg = (char *)"invalid literal/length code"; state.mode = BAD; break; } state.extra = (unsigned)(here.op) & 15; state.mode = LENEXT; case LENEXT: if (state.extra) { NEEDBITS(state.extra); state.length += BITS(state.extra); DROPBITS(state.extra); state.back += state.extra; } Tracevv((stderr, "inflate: length %u\n", state.length)); state.was = state.length; state.mode = DIST; case DIST: for (;;) { here = state.distcode[BITS(state.distbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if ((here.op & 0xf0) == 0) { last = here; for (;;) { here = state.distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); state.back += last.bits; } DROPBITS(here.bits); state.back += here.bits; if (here.op & 64) { strm.msg = (char *)"invalid distance code"; state.mode = BAD; break; } state.offset = (unsigned)here.val; state.extra = (unsigned)(here.op) & 15; state.mode = DISTEXT; case DISTEXT: if (state.extra) { NEEDBITS(state.extra); state.offset += BITS(state.extra); DROPBITS(state.extra); state.back += state.extra; } #ifdef INFLATE_STRICT if (state.offset > state.dmax) { strm.msg = (char *)"invalid distance too far back"; state.mode = BAD; break; } #endif Tracevv((stderr, "inflate: distance %u\n", state.offset)); state.mode = MATCH; case MATCH: if (left == 0) goto inf_leave; copy = out - left; if (state.offset > copy) { /* copy from window */ copy = state.offset - copy; if (copy > state.whave) { if (state.sane) { strm.msg = (char *)"invalid distance too far back"; state.mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR Trace((stderr, "inflate.c too far\n")); copy -= state.whave; if (copy > state.length) copy = state.length; if (copy > left) copy = left; left -= copy; state.length -= copy; do { *put++ = 0; } while (--copy); if (state.length == 0) state.mode = LEN; break; #endif } if (copy > state.wnext) { copy -= state.wnext; from = state.window + (state.wsize - copy); } else from = state.window + (state.wnext - copy); if (copy > state.length) copy = state.length; } else { /* copy from output */ from = put - state.offset; copy = state.length; } if (copy > left) copy = left; left -= copy; state.length -= copy; do { *put++ = *from++; } while (--copy); if (state.length == 0) state.mode = LEN; break; case LIT: if (left == 0) goto inf_leave; *put++ = (u8)(state.length); left--; state.mode = LEN; break; case CHECK: if (state.wrap) { NEEDBITS(32); out -= left; strm.total_out += out; state.total += out; if ((state.wrap & 4) && out) strm.adler = state.check = UPDATE(state.check, put - out, out); out = left; if ((state.wrap & 4) && ( #ifdef GUNZIP state.flags ? hold : #endif ZSWAP32(hold)) != state.check) { strm.msg = (char *)"incorrect data check"; state.mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: check matches trailer\n")); } #ifdef GUNZIP state.mode = LENGTH; case LENGTH: if (state.wrap && state.flags) { NEEDBITS(32); if (hold != (state.total & 0xffffffffUL)) { strm.msg = (char *)"incorrect length check"; state.mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: length matches trailer\n")); } #endif state.mode = DONE; case DONE: ret = Z_STREAM_END; goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; case MEM: return Z_MEM_ERROR; case SYNC: default: return Z_STREAM_ERROR; } /* Return from inflate(), updating the total counts and the check value. If there was no progress during the inflate() call, return a buffer error. Call updatewindow() to create and/or update the window state. Note: a memory error from inflate() is non-recoverable. */ inf_leave: strm.next_out = put; \ strm.avail_out = left; \ strm.next_in = next; \ strm.avail_in = have; \ state.hold = hold; \ state.bits = bits; \ if (state.wsize || (out != strm.avail_out && state.mode < BAD && (state.mode < CHECK || flush != Z_FINISH))) if (updatewindow(strm, strm.next_out, out - strm.avail_out)) { state.mode = MEM; return Z_MEM_ERROR; } in -= strm.avail_in; out -= strm.avail_out; strm.total_in += in; strm.total_out += out; state.total += out; if ((state.wrap & 4) && out) strm.adler = state.check = UPDATE(state.check, strm.next_out - out, out); strm.data_type = (int)state.bits + (state.last ? 64 : 0) + (state.mode == TYPE ? 128 : 0) + (state.mode == LEN_ || state.mode == COPY_ ? 256 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) ret = Z_BUF_ERROR; return ret; } local int inflateStateCheck(z_stream * strm) { struct inflate_state FAR *state; if (strm == Z_NULL || strm.zalloc == (alloc_func)0 || strm.zfree == (free_func)0) return 1; state = (struct inflate_state FAR *)strm.state; if (state == Z_NULL || state.strm != strm || state.mode < HEAD || state.mode > SYNC) return 1; return 0; }