/* * Return state with length and distance decoding tables and index sizes set to * fixed code decoding. Normally this returns fixed tables from inffixed.h. * If BUILDFIXED is defined, then instead this routine builds the tables the * first time it's called, and returns those tables the first time and * thereafter. This reduces the size of the code by about 2K bytes, in * exchange for a little execution time. However, BUILDFIXED should not be * used for threaded applications, since the rewriting of the tables and virgin * may not be thread-safe. */ private static void fixedtables( inflate_state state) { state.lencode_array = inffixed.lenfix; state.lencode_index = 0; state.lenbits = 9; state.distcode_array = inffixed.distfix; state.distcode_index = 0; state.distbits = 5; }
public static int inflateCopy( z_stream dest, z_stream source) { inflate_state state; inflate_state copy; byte[] window; uint wsize; /* check input */ if (inflateStateCheck(source) != 0 || dest == null) { return(zlib.Z_STREAM_ERROR); } state = source.state; /* allocate space */ copy = new inflate_state(); if (copy == null) { return(zlib.Z_MEM_ERROR); } window = null; if (state.window != null) { window = new byte[1U << (int)state.wbits]; if (window == null) { copy = null; return(zlib.Z_MEM_ERROR); } } /* copy state */ zutil.zmemcpy(dest, source); zutil.zmemcpy(copy, state); copy.strm = dest; if (state.lencode_array == state.codes) { copy.lencode_array = copy.codes; copy.lencode_index = state.lencode_index; copy.distcode_array = copy.codes; copy.distcode_index = state.distcode_index; } copy.next = state.next; if (window != null) { wsize = 1U << (int)state.wbits; zutil.zmemcpy(window, 0, state.window, 0, wsize); } copy.window = window; dest.state = copy; return(zlib.Z_OK); }
internal static void zmemcpy(inflate_state target, inflate_state source) { target.strm = source.strm; target.mode = source.mode; target.last = source.last; target.wrap = source.wrap; target.havedict = source.havedict; target.flags = source.flags; target.dmax = source.dmax; target.check = source.check; target.total = source.total; target.head = source.head; target.wbits = source.wbits; target.wsize = source.wsize; target.whave = source.whave; target.wnext = source.wnext; target.window = source.window; target.hold = source.hold; target.bits = source.bits; target.length = source.length; target.offset = source.offset; target.extra = source.extra; target.lencode_array = source.lencode_array; target.lencode_index = source.lencode_index; target.distcode_array = source.distcode_array; target.distcode_index = source.distcode_index; target.lenbits = source.lenbits; target.distbits = source.distbits; target.ncode = source.ncode; target.nlen = source.nlen; target.ndist = source.ndist; target.have = source.have; target.next = source.next; target.lens = new ushort[320]; for (int i = 0; i < 320; ++i) { target.lens[i] = source.lens[i]; } target.work = new ushort[288]; for (int i = 0; i < 288; ++i) { target.work[i] = source.work[i]; } target.codes = new code[inftrees.ENOUGH]; for (int i = 0; i < inftrees.ENOUGH; ++i) { target.codes[i] = source.codes[i]; } target.sane = source.sane; target.back = source.back; target.was = source.was; }
public static int inflateInit2_( z_stream strm, int windowBits, string version, int stream_size) { int ret; inflate_state state; if (version == null || version.Length == 0 || version[0] != zlib.ZLIB_VERSION[0] || stream_size != (int)z_stream._sizeof) { return(zlib.Z_VERSION_ERROR); } if (strm == null) { return(zlib.Z_STREAM_ERROR); } strm.msg = null; /* in case we return an error */ state = new inflate_state(); if (state == null) { return(zlib.Z_MEM_ERROR); } //Tracev((stderr, "inflate: allocated\n")); strm.state = state; state.strm = strm; state.window = null; state.mode = inflate_mode.HEAD; /* to pass state test in inflateReset2() */ ret = inflateReset2(strm, windowBits); if (ret != zlib.Z_OK) { state = null; strm.state = null; } return(ret); }
// Decode literal, length, and distance codes and write out the resulting // literal and match bytes until either not enough input or output is // available, an end-of-block is encountered, or a data error is encountered. // When large enough input and output buffers are supplied to inflate(), for // example, a 16K input buffer and a 64K output buffer, more than 95% of the // inflate execution time is spent in this routine. // // Entry assumptions: // // state.mode == LEN // strm.avail_in >= 6 // strm.avail_out >= 258 // start >= strm.avail_out // state.bits < 8 // // On return, state.mode is one of: // // LEN -- ran out of enough output space or enough available input // TYPE -- reached end of block code, inflate() to interpret next block // BAD -- error in block data // // Notes: // // - The maximum input bits used by a length/distance pair is 15 bits for the // length code, 5 bits for the length extra, 15 bits for the distance code, // and 13 bits for the distance extra. This totals 48 bits, or six bytes. // Therefore if strm.avail_in >= 6, then there is enough input to avoid // checking for available input while decoding. // // - The maximum bytes that a single length/distance pair can output is 258 // bytes, which is the maximum length that can be coded. inflate_fast() // requires strm.avail_out >= 258 for each loop to avoid checking for // output space. private static void inflate_fast(z_stream strm, uint start) // inflate()'s starting value for strm.avail_out { inflate_state state = null; byte[] _in; // local strm.next_in uint in_ind; // ind in _in int last; // while in < last, enough input available byte[] @out; // local strm.next_out int out_ind; // ind in @out int beg; // inflate()'s initial strm.next_out int end; // while out < end, enough space available uint dmax; // maximum distance from zlib header uint wsize; // window size or zero if not using window uint whave; // valid bytes in the window uint wnext; // window write index byte[] window; // allocated sliding window, if wsize != 0 uint hold; // local strm.hold uint bits; // local strm.bits code[] lcode; // local strm.lencode code[] dcode; // local strm.distcode int dcode_ind; // index in strm.distcode uint lmask; // mask for first level of length codes uint dmask; // mask for first level of distance codes code here; // retrieved table entry uint op; // code bits, operation, extra bits, or window position, window bytes to copy uint len; // match length, unused bytes uint dist; // match distance byte[] from; // where to copy match from int from_ind; // where to copy match from // copy state to local variables state = (inflate_state)strm.state; _in = strm.in_buf; in_ind = strm.next_in; last = (int)(in_ind + (strm.avail_in - 5)); @out = strm.out_buf; out_ind = strm.next_out; beg = (int)(out_ind - (start - strm.avail_out)); end = (int)(out_ind + (strm.avail_out - 257)); dmax = state.dmax; wsize = state.wsize; whave = state.whave; wnext = state.wnext; window = state.window; hold = state.hold; bits = state.bits; lcode = state.lencode; dcode = state.distcode; dcode_ind = state.distcode_ind; lmask = (1U << (int)state.lenbits) - 1; dmask = (1U << (int)state.distbits) - 1; // decode literals and length/distances until end-of-block or not enough input data or output space do { if (bits < 15) { hold += (uint)_in[in_ind++] << (int)bits; bits += 8; hold += (uint)_in[in_ind++] << (int)bits; bits += 8; } here = lcode[hold & lmask]; dolen: op = here.bits; hold >>= (int)op; bits -= op; op = here.op; if (op == 0) { // literal //Tracevv((stderr, @this.val >= 0x20 && @this.val < 0x7f ? // "inflate: literal '%c'\n" : // "inflate: literal 0x%02x\n", @this.val)); @out[out_ind++] = (byte)here.val; } else if ((op & 16) != 0) { // length base len = here.val; op &= 15; // number of extra bits if (op != 0) { if (bits < op) { hold += (uint)_in[in_ind++] << (int)bits; bits += 8; } len += (uint)hold & ((1U << (int)op) - 1); hold >>= (int)op; bits -= op; } //Tracevv((stderr, "inflate: length %u\n", len)); if (bits < 15) { hold += (uint)_in[in_ind++] << (int)bits; bits += 8; hold += (uint)_in[in_ind++] << (int)bits; bits += 8; } here = dcode[dcode_ind + (hold & dmask)]; dodist: op = here.bits; hold >>= (int)op; bits -= op; op = here.op; if ((op & 16) != 0) { // distance base dist = here.val; op &= 15; // number of extra bits if (bits < op) { hold += (uint)_in[in_ind++] << (int)bits; bits += 8; if (bits < op) { hold += (uint)_in[in_ind++] << (int)bits; bits += 8; } } dist += (uint)hold & ((1U << (int)op) - 1); if (dist > dmax) { strm.msg = "invalid distance too far back (STRICT)"; state.mode = inflate_mode.BAD; break; } hold >>= (int)op; bits -= op; //Tracevv((stderr, "inflate: distance %u\n", dist)); op = (uint)(out_ind - beg); // max distance in output if (dist > op) { // see if copy from window op = dist - op; // distance back in window if (op > whave) { if (state.sane) { strm.msg = "invalid distance too far back"; state.mode = inflate_mode.BAD; break; } #if INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (len <= op - whave) { do { @out[out_ind++] = 0; } while(--len != 0); continue; } len -= op - whave; do { @out[out_ind++] = 0; } while(--op > whave); if (op == 0) { from = @out; from_ind = (int)(out_ind - dist); do { @out[out_ind++] = from[from_ind++]; } while(--len != 0); continue; } #endif } from = window; from_ind = 0; if (wnext == 0) { // very common case from_ind += (int)(wsize - op); if (op < len) { // some from window len -= op; do { @out[out_ind++] = from[from_ind++]; } while ((--op) != 0); from = @out; from_ind = (int)(out_ind - dist); // rest from output } } else if (wnext < op) { // wrap around window from_ind += (int)(wsize + wnext - op); op -= wnext; if (op < len) { // some from end of window len -= op; do { @out[out_ind++] = from[from_ind++]; } while ((--op) != 0); from = window; from_ind = 0; if (wnext < len) { // some from start of window op = wnext; len -= op; do { @out[out_ind++] = from[from_ind++]; } while ((--op) != 0); from = @out; from_ind = (int)(out_ind - dist); // rest from output } } } else { // contiguous in window from_ind += (int)(wnext - op); if (op < len) { // some from window len -= op; do { @out[out_ind++] = from[from_ind++]; } while ((--op) != 0); from = @out; from_ind = (int)(out_ind - dist); // rest from output } } while (len > 2) { @out[out_ind++] = from[from_ind++]; @out[out_ind++] = from[from_ind++]; @out[out_ind++] = from[from_ind++]; len -= 3; } if (len != 0) { @out[out_ind++] = from[from_ind++]; if (len > 1) { @out[out_ind++] = from[from_ind++]; } } } else { from = @out; from_ind = (int)(out_ind - dist); // copy direct from output do { // minimum length is three @out[out_ind++] = from[from_ind++]; @out[out_ind++] = from[from_ind++]; @out[out_ind++] = from[from_ind++]; len -= 3; } while (len > 2); if (len != 0) { @out[out_ind++] = from[from_ind++]; if (len > 1) { @out[out_ind++] = from[from_ind++]; } } } } else if ((op & 64) == 0) { // 2nd level distance code here = dcode[dcode_ind + here.val + (hold & ((1U << (int)op) - 1))]; goto dodist; } else { strm.msg = "invalid distance code"; state.mode = inflate_mode.BAD; break; } } else if ((op & 64) == 0) { // 2nd level length code here = lcode[here.val + (hold & ((1U << (int)op) - 1))]; goto dolen; } else if ((op & 32) != 0) { // end-of-block //Tracevv((stderr, "inflate: end of block\n")); state.mode = inflate_mode.TYPE; break; } else { strm.msg = "invalid literal/length code"; state.mode = inflate_mode.BAD; break; } } while (in_ind < last && out_ind < end); // return unused bytes (on entry, bits < 8, so in won't go too far back) len = bits >> 3; in_ind -= len; bits -= len << 3; hold &= (1U << (int)bits) - 1; // update state and return strm.next_in = in_ind; strm.next_out = out_ind; strm.avail_in = (uint)(in_ind < last ? 5 + (last - in_ind) : 5 - (in_ind - last)); strm.avail_out = (uint)(out_ind < end ? 257 + (end - out_ind) : 257 - (out_ind - end)); state.hold = hold; state.bits = bits; }
public int run(z_stream _strm, int _flush) { this.strm = _strm; this.flush = _flush; if (inflateStateCheck(strm) != 0 || strm.output_buffer == null || (strm.input_buffer == null && strm.avail_in != 0)) { return(zlib.Z_STREAM_ERROR); } state = strm.state; if (state.mode == inflate_mode.TYPE) { state.mode = inflate_mode.TYPEDO; /* skip check */ } LOAD(); @in = have; @out = left; ret = zlib.Z_OK; for (;;) { switch (state.mode) { case inflate_mode.HEAD: if (state.wrap == 0) { state.mode = inflate_mode.TYPEDO; break; } if (NEEDBITS_(16)) { goto inf_leave; } //#ifdef GUNZIP if ((state.wrap & 2) != 0 && hold == 0x8b1f) /* gzip header */ { if (state.wbits == 0) { state.wbits = 15; } state.check = crc32.crc32_(0L, null, 0, 0); CRC2(state.check, hold); INITBITS(); state.mode = inflate_mode.FLAGS; break; } state.flags = 0; /* expect zlib header */ if (state.head != null) { state.head.done = -1; } if (!((state.wrap & 1) != 0) || /* check if zlib header allowed */ //#else // if ( //#endif (((BITS(8) << 8) + (hold >> 8)) % 31) != 0) { strm.msg = "incorrect header check"; state.mode = inflate_mode.BAD; break; } if (BITS(4) != zlib.Z_DEFLATED) { strm.msg = "unknown compression method"; state.mode = inflate_mode.BAD; break; } DROPBITS(4); len = BITS(4) + 8; if (state.wbits == 0) { state.wbits = len; } if (len > 15 || len > state.wbits) { strm.msg = "invalid window size"; state.mode = inflate_mode.BAD; break; } state.dmax = 1U << (int)len; //Tracev((stderr, "inflate: zlib header ok\n")); strm.adler = state.check = adler32.adler32_(0L, null, 0, 0); state.mode = (hold & 0x200) != 0 ? inflate_mode.DICTID : inflate_mode.TYPE; INITBITS(); break; //#ifdef GUNZIP case inflate_mode.FLAGS: if (NEEDBITS_(16)) { goto inf_leave; } state.flags = (int)(hold); if ((state.flags & 0xff) != zlib.Z_DEFLATED) { strm.msg = "unknown compression method"; state.mode = inflate_mode.BAD; break; } if ((state.flags & 0xe000) != 0) { strm.msg = "unknown header flags set"; state.mode = inflate_mode.BAD; break; } if (state.head != null) { state.head.text = (int)((hold >> 8) & 1); } if ((state.flags & 0x0200) != 0 && (state.wrap & 4) != 0) { CRC2(state.check, hold); } INITBITS(); state.mode = inflate_mode.TIME; goto case inflate_mode.TIME; case inflate_mode.TIME: if (NEEDBITS_(32)) { goto inf_leave; } if (state.head != null) { state.head.time = hold; } if ((state.flags & 0x0200) != 0 && (state.wrap & 4) != 0) { CRC4(state.check, hold); } INITBITS(); state.mode = inflate_mode.OS; goto case inflate_mode.OS; case inflate_mode.OS: if (NEEDBITS_(16)) { goto inf_leave; } if (state.head != null) { state.head.xflags = (int)(hold & 0xff); state.head.os = (int)(hold >> 8); } if ((state.flags & 0x0200) != 0 && (state.wrap & 4) != 0) { CRC2(state.check, hold); } INITBITS(); state.mode = inflate_mode.EXLEN; goto case inflate_mode.EXLEN; case inflate_mode.EXLEN: if ((state.flags & 0x0400) != 0) { if (NEEDBITS_(16)) { goto inf_leave; } state.length = (uint)(hold); if (state.head != null) { state.head.extra_len = (uint)hold; } if ((state.flags & 0x0200) != 0 && (state.wrap & 4) != 0) { CRC2(state.check, hold); } INITBITS(); } else if (state.head != null) { state.head.extra = null; } state.mode = inflate_mode.EXTRA; goto case inflate_mode.EXTRA; case inflate_mode.EXTRA: if ((state.flags & 0x0400) != 0) { copy = state.length; if (copy > have) { copy = have; } if (copy != 0) { if (state.head != null && state.head.extra != null) { len = state.head.extra_len - state.length; zutil.zmemcpy(state.head.extra, len, next_buffer, next_index, len + copy > state.head.extra_max ? state.head.extra_max - len : copy); } if ((state.flags & 0x0200) != 0 && (state.wrap & 4) != 0) { state.check = crc32.crc32_(state.check, next_buffer, next_index, copy); } have -= copy; next_index += copy; state.length -= copy; } if (state.length != 0) { goto inf_leave; } } state.length = 0; state.mode = inflate_mode.NAME; goto case inflate_mode.NAME; case inflate_mode.NAME: if ((state.flags & 0x0800) != 0) { if (have == 0) { goto inf_leave; } copy = 0; do { len = (uint)(next_buffer[next_index + copy++]); if (state.head != null && state.head.name != null && state.length < state.head.name_max) { state.head.name[state.length++] = (byte)len; } } while (len != 0 && copy < have); if ((state.flags & 0x0200) != 0 && (state.wrap & 4) != 0) { state.check = crc32.crc32_(state.check, next_buffer, next_index, copy); } have -= copy; next_index += copy; if (len != 0) { goto inf_leave; } } else if (state.head != null) { state.head.name = null; } state.length = 0; state.mode = inflate_mode.COMMENT; goto case inflate_mode.COMMENT; case inflate_mode.COMMENT: if ((state.flags & 0x1000) != 0) { if (have == 0) { goto inf_leave; } copy = 0; do { len = (uint)(next_buffer[next_index + copy++]); if (state.head != null && state.head.comment != null && state.length < state.head.comm_max) { state.head.comment[state.length++] = (byte)len; } } while (len != 0 && copy < have); if ((state.flags & 0x0200) != 0 && (state.wrap & 4) != 0) { state.check = crc32.crc32_(state.check, next_buffer, next_index, copy); } have -= copy; next_index += copy; if (len != 0) { goto inf_leave; } } else if (state.head != null) { state.head.comment = null; } state.mode = inflate_mode.HCRC; goto case inflate_mode.HCRC; case inflate_mode.HCRC: if ((state.flags & 0x0200) != 0) { if (NEEDBITS_(16)) { goto inf_leave; } if ((state.wrap & 4) != 0 && hold != (state.check & 0xffff)) { strm.msg = "header crc mismatch"; state.mode = inflate_mode.BAD; break; } INITBITS(); } if (state.head != null) { state.head.hcrc = (int)((state.flags >> 9) & 1); state.head.done = 1; } strm.adler = state.check = crc32.crc32_(0L, null, 0, 0); state.mode = inflate_mode.TYPE; break; //#endif case inflate_mode.DICTID: if (NEEDBITS_(32)) { goto inf_leave; } strm.adler = state.check = zutil.ZSWAP32((uint)hold); INITBITS(); state.mode = inflate_mode.DICT; goto case inflate_mode.DICT; case inflate_mode.DICT: if (state.havedict == 0) { RESTORE(); return(zlib.Z_NEED_DICT); } strm.adler = state.check = adler32.adler32_(0L, null, 0, 0); state.mode = inflate_mode.TYPE; goto case inflate_mode.TYPE; case inflate_mode.TYPE: if (flush == zlib.Z_BLOCK || flush == zlib.Z_TREES) { goto inf_leave; } goto case inflate_mode.TYPEDO; case inflate_mode.TYPEDO: if (state.last != 0) { BYTEBITS(); state.mode = inflate_mode.CHECK; break; } if (NEEDBITS_(3)) { goto inf_leave; } state.last = (int)BITS(1); DROPBITS(1); switch (BITS(2)) { case 0: /* stored block */ //Tracev((stderr, "inflate: stored block%s\n", // state.last ? " (last)" : "")); state.mode = inflate_mode.STORED; break; case 1: /* fixed block */ fixedtables(state); //Tracev((stderr, "inflate: fixed codes block%s\n", // state.last ? " (last)" : "")); state.mode = inflate_mode.LEN_; /* decode codes */ if (flush == zlib.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 = inflate_mode.TABLE; break; case 3: strm.msg = "invalid block type"; state.mode = inflate_mode.BAD; break; } DROPBITS(2); break; case inflate_mode.STORED: BYTEBITS(); /* go to byte boundary */ if (NEEDBITS_(32)) { goto inf_leave; } if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { strm.msg = "invalid stored block lengths"; state.mode = inflate_mode.BAD; break; } state.length = (uint)hold & 0xffff; //Tracev((stderr, "inflate: stored length %u\n", // state.length)); INITBITS(); state.mode = inflate_mode.COPY_; if (flush == zlib.Z_TREES) { goto inf_leave; } goto case inflate_mode.COPY_; case inflate_mode.COPY_: state.mode = inflate_mode.COPY; goto case inflate_mode.COPY; case inflate_mode.COPY: copy = state.length; if (copy != 0) { if (copy > have) { copy = have; } if (copy > left) { copy = left; } if (copy == 0) { goto inf_leave; } zutil.zmemcpy(put_buffer, put_index, next_buffer, next_index, copy); have -= copy; next_index += copy; left -= copy; put_index += copy; state.length -= copy; break; } //Tracev((stderr, "inflate: stored end\n")); state.mode = inflate_mode.TYPE; break; case inflate_mode.TABLE: if (NEEDBITS_(14)) { goto inf_leave; } 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 = "too many length or distance symbols"; state.mode = inflate_mode.BAD; break; } //#endif //Tracev((stderr, "inflate: table sizes ok\n")); state.have = 0; state.mode = inflate_mode.LENLENS; goto case inflate_mode.LENLENS; case inflate_mode.LENLENS: while (state.have < state.ncode) { if (NEEDBITS_(3)) { goto inf_leave; } state.lens[order[state.have++]] = (ushort)BITS(3); DROPBITS(3); } while (state.have < 19) { state.lens[order[state.have++]] = 0; } state.next = 0; state.lencode_array = state.codes; state.lencode_index = state.next; state.lenbits = 7; ret = inftrees.inflate_table(codetype.CODES, state.lens, 0, 19, state.codes, ref state.next, ref state.lenbits, state.work); if (ret != 0) { strm.msg = "invalid code lengths set"; state.mode = inflate_mode.BAD; break; } //Tracev((stderr, "inflate: code lengths ok\n")); state.have = 0; state.mode = inflate_mode.CODELENS; goto case inflate_mode.CODELENS; case inflate_mode.CODELENS: while (state.have < state.nlen + state.ndist) { for (;;) { here = state.lencode_array[state.lencode_index + BITS(state.lenbits)]; if ((uint)(here.bits) <= bits) { break; } if (PULLBYTE_()) { goto inf_leave; } } if (here.val < 16) { DROPBITS(here.bits); state.lens[state.have++] = here.val; } else { if (here.val == 16) { if (NEEDBITS_(here.bits + 2)) { goto inf_leave; } DROPBITS(here.bits); if (state.have == 0) { strm.msg = "invalid bit length repeat"; state.mode = inflate_mode.BAD; break; } len = state.lens[state.have - 1]; copy = 3 + BITS(2); DROPBITS(2); } else if (here.val == 17) { if (NEEDBITS_(here.bits + 3)) { goto inf_leave; } DROPBITS(here.bits); len = 0; copy = 3 + BITS(3); DROPBITS(3); } else { if (NEEDBITS_(here.bits + 7)) { goto inf_leave; } DROPBITS(here.bits); len = 0; copy = 11 + BITS(7); DROPBITS(7); } if (state.have + copy > state.nlen + state.ndist) { strm.msg = "invalid bit length repeat"; state.mode = inflate_mode.BAD; break; } while (copy-- != 0) { state.lens[state.have++] = (ushort)len; } } } /* handle error breaks in while */ if (state.mode == inflate_mode.BAD) { break; } /* check for end-of-block code (better have one) */ if (state.lens[256] == 0) { strm.msg = "invalid code -- missing end-of-block"; state.mode = inflate_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 = 0; state.lencode_array = state.codes; state.lencode_index = state.next; state.lenbits = 9; ret = inftrees.inflate_table(codetype.LENS, state.lens, 0, state.nlen, state.codes, ref state.next, ref state.lenbits, state.work); if (ret != 0) { strm.msg = "invalid literal/lengths set"; state.mode = inflate_mode.BAD; break; } state.distcode_array = state.codes; state.distcode_index = state.next; state.distbits = 6; ret = inftrees.inflate_table(codetype.DISTS, state.lens, state.nlen, state.ndist, state.codes, ref state.next, ref state.distbits, state.work); if (ret != 0) { strm.msg = "invalid distances set"; state.mode = inflate_mode.BAD; break; } //Tracev((stderr, "inflate: codes ok\n")); state.mode = inflate_mode.LEN_; if (flush == zlib.Z_TREES) { goto inf_leave; } goto case inflate_mode.LEN_; case inflate_mode.LEN_: state.mode = inflate_mode.LEN; goto case inflate_mode.LEN; case inflate_mode.LEN: if (have >= 6 && left >= 258) { RESTORE(); inffast.inflate_fast(strm, @out); LOAD(); if (state.mode == inflate_mode.TYPE) { state.back = -1; } break; } state.back = 0; for (;;) { here = state.lencode_array[state.lencode_index + BITS(state.lenbits)]; if ((uint)(here.bits) <= bits) { break; } if (PULLBYTE_()) { goto inf_leave; } } if (here.op != 0 && (here.op & 0xf0) == 0) { last = here; for (;;) { here = state.lencode_array[state.lencode_index + last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((uint)(last.bits + here.bits) <= bits) { break; } if (PULLBYTE_()) { goto inf_leave; } } DROPBITS(last.bits); state.back += last.bits; } DROPBITS(here.bits); state.back += here.bits; state.length = (uint)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 = inflate_mode.LIT; break; } if ((here.op & 32) != 0) { //Tracevv((stderr, "inflate: end of block\n")); state.back = -1; state.mode = inflate_mode.TYPE; break; } if ((here.op & 64) != 0) { strm.msg = "invalid literal/length code"; state.mode = inflate_mode.BAD; break; } state.extra = (uint)(here.op) & 15; state.mode = inflate_mode.LENEXT; goto case inflate_mode.LENEXT; case inflate_mode.LENEXT: if (state.extra != 0) { if (NEEDBITS_(state.extra)) { goto inf_leave; } state.length += BITS(state.extra); DROPBITS(state.extra); state.back += (int)state.extra; } //Tracevv((stderr, "inflate: length %u\n", state.length)); state.was = state.length; state.mode = inflate_mode.DIST; goto case inflate_mode.DIST; case inflate_mode.DIST: for (;;) { here = state.distcode_array[state.distcode_index + BITS(state.distbits)]; if ((uint)(here.bits) <= bits) { break; } if (PULLBYTE_()) { goto inf_leave; } } if ((here.op & 0xf0) == 0) { last = here; for (;;) { here = state.distcode_array[state.distcode_index + last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((uint)(last.bits + here.bits) <= bits) { break; } if (PULLBYTE_()) { goto inf_leave; } } DROPBITS(last.bits); state.back += last.bits; } DROPBITS(here.bits); state.back += here.bits; if ((here.op & 64) != 0) { strm.msg = "invalid distance code"; state.mode = inflate_mode.BAD; break; } state.offset = (uint)here.val; state.extra = (uint)(here.op) & 15; state.mode = inflate_mode.DISTEXT; goto case inflate_mode.DISTEXT; case inflate_mode.DISTEXT: if (state.extra != 0) { if (NEEDBITS_(state.extra)) { goto inf_leave; } state.offset += BITS(state.extra); DROPBITS(state.extra); state.back += (int)state.extra; } //#ifdef INFLATE_STRICT // if (state.offset > state.dmax) { // strm.msg = "invalid distance too far back"; // state.mode = inflate_mode.BAD; // break; // } //#endif //Tracevv((stderr, "inflate: distance %u\n", state.offset)); state.mode = inflate_mode.MATCH; goto case inflate_mode.MATCH; case inflate_mode.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 != 0) { strm.msg = "invalid distance too far back"; state.mode = inflate_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 = inflate_mode.LEN; // break; //#endif } if (copy > state.wnext) { copy -= state.wnext; from_buffer = state.window; from_index = (state.wsize - copy); } else { from_buffer = state.window; from_index = (state.wnext - copy); } if (copy > state.length) { copy = state.length; } } else /* copy from output */ { from_buffer = put_buffer; from_index = put_index - state.offset; copy = state.length; } if (copy > left) { copy = left; } left -= copy; state.length -= copy; do { put_buffer[put_index++] = from_buffer[from_index++]; } while (--copy != 0); if (state.length == 0) { state.mode = inflate_mode.LEN; } break; case inflate_mode.LIT: if (left == 0) { goto inf_leave; } put_buffer[put_index++] = (byte)(state.length); left--; state.mode = inflate_mode.LEN; break; case inflate_mode.CHECK: if (state.wrap != 0) { if (NEEDBITS_(32)) { goto inf_leave; } @out -= left; strm.total_out += @out; state.total += @out; if ((state.wrap & 4) != 0 && @out != 0) { strm.adler = state.check = UPDATE(state.check, put_buffer, put_index - @out, @out); } @out = left; if ((state.wrap & 4) != 0 && ( //#ifdef GUNZIP state.flags != 0 ? hold : //#endif zutil.ZSWAP32((uint)hold)) != state.check) { strm.msg = "incorrect data check"; state.mode = inflate_mode.BAD; break; } INITBITS(); //Tracev((stderr, "inflate: check matches trailer\n")); } //#ifdef GUNZIP state.mode = inflate_mode.LENGTH; goto case inflate_mode.LENGTH; case inflate_mode.LENGTH: if (state.wrap != 0 && state.flags != 0) { if (NEEDBITS_(32)) { goto inf_leave; } if (hold != (state.total & 0xffffffffUL)) { strm.msg = "incorrect length check"; state.mode = inflate_mode.BAD; break; } INITBITS(); //Tracev((stderr, "inflate: length matches trailer\n")); } //#endif state.mode = inflate_mode.DONE; goto case inflate_mode.DONE; case inflate_mode.DONE: ret = zlib.Z_STREAM_END; goto inf_leave; case inflate_mode.BAD: ret = zlib.Z_DATA_ERROR; goto inf_leave; case inflate_mode.MEM: return(zlib.Z_MEM_ERROR); case inflate_mode.SYNC: default: return(zlib.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: RESTORE(); if (state.wsize != 0 || (@out != strm.avail_out && state.mode < inflate_mode.BAD && (state.mode < inflate_mode.CHECK || flush != zlib.Z_FINISH))) { if (updatewindow(strm, strm.output_buffer, strm.next_out, @out - strm.avail_out) != 0) { state.mode = inflate_mode.MEM; return(zlib.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) != 0 && @out != 0) { strm.adler = state.check = UPDATE(state.check, strm.output_buffer, strm.next_out - @out, @out); } strm.data_type = (int)state.bits + (state.last != 0 ? 64 : 0) + (state.mode == inflate_mode.TYPE ? 128 : 0) + (state.mode == inflate_mode.LEN_ || state.mode == inflate_mode.COPY_ ? 256 : 0); if (((@in == 0 && @out == 0) || flush == zlib.Z_FINISH) && ret == zlib.Z_OK) { ret = zlib.Z_BUF_ERROR; } return(ret); }
// Return state with length and distance decoding tables and index sizes set to // fixed code decoding. static void fixedtables(inflate_state state) { state.lencode=lenfix; state.lenbits=9; state.distcode=distfix; state.distcode_ind=0; state.distbits=5; }
// This is another version of inflateInit with an extra parameter. The // fields next_in, avail_in, zalloc, zfree and opaque must be initialized // before by the caller. // The windowBits parameter is the base two logarithm of the maximum window // size (the size of the history buffer). It should be in the range 8..15 for // this version of the library. The default value is 15 if inflateInit is used // instead. windowBits must be greater than or equal to the windowBits value // provided to deflateInit2() while compressing, or it must be equal to 15 if // deflateInit2() was not used. If a compressed stream with a larger window // size is given as input, inflate() will return with the error code // Z_DATA_ERROR instead of trying to allocate a larger window. // windowBits can also be -8..-15 for raw inflate. In this case, -windowBits // determines the window size. inflate() will then process raw deflate data, // not looking for a zlib or gzip header, not generating a check value, and not // looking for any check values for comparison at the end of the stream. This // is for use with other formats that use the deflate compressed data format // such as zip. Those formats provide their own check values. If a custom // format is developed using the raw deflate format for compressed data, it is // recommended that a check value such as an adler32 or a crc32 be applied to // the uncompressed data as is done in the zlib, gzip, and zip formats. For // most applications, the zlib format should be used as is. Note that comments // above on the use in deflateInit2() applies to the magnitude of windowBits. // windowBits can also be greater than 15 for optional gzip decoding. Add // 32 to windowBits to enable zlib and gzip decoding with automatic header // detection, or add 16 to decode only the gzip format (the zlib format will // return a Z_DATA_ERROR). If a gzip stream is being decoded, strm.adler is // a crc32 instead of an adler32. // inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough // memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg // is set to null if there is no error message. inflateInit2 does not perform // any decompression apart from reading the zlib header if present: this will // be done by inflate(). (So next_in and avail_in may be modified, but next_out // and avail_out are unchanged.) public static int inflateInit2(z_stream strm, int windowBits) { if(strm==null) return Z_STREAM_ERROR; strm.msg=null; // in case we return an error inflate_state state; try { state=new inflate_state(); } catch(Exception) { return Z_MEM_ERROR; } //Tracev((stderr, "inflate: allocated\n")); strm.state=state; state.window=null; int ret=inflateReset2(strm, windowBits); if(ret!=Z_OK) strm.state=null; return ret; }