Exemple #1
0
 /*
  * 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;
 }
Exemple #2
0
        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);
        }
Exemple #3
0
 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;
 }
Exemple #4
0
        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);
        }
Exemple #5
0
        // 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;
        }
Exemple #6
0
        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);
        }
Exemple #7
0
		// 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;
		}
Exemple #8
0
		//   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;
		}