Ejemplo n.º 1
0
        /* READ_LENGTHS(tablename, first, last) reads in code lengths for symbols
         * first to last in the given table. The code lengths are stored in their
         * own special LZX way.
         */
        private static bool READ_LENGTHS(ULONG first, ULONG last, lzx_bits lb, ref ULONG bitbuf,
                                         ref LONG bitsleft, ref UBYTE[] ip, ref long inpos, LZXstate pState, ref UBYTE[] tablelen)
        {
            lb.bb    = bitbuf;
            lb.bl    = bitsleft;
            lb.ip    = ip;
            lb.ippos = inpos;

            if (lzx_read_lens(pState, ref tablelen, first, last, lb) != 0)
            {
                return(false);
            }

            bitbuf   = lb.bb;
            bitsleft = lb.bl;
            inpos    = lb.ippos;

            return(true);
        }
Ejemplo n.º 2
0
        /* READ_LENGTHS(tablename, first, last) reads in code lengths for symbols
         * first to last in the given table. The code lengths are stored in their
         * own special LZX way.
         */
        private static bool READ_LENGTHS(ULONG first, ULONG last, lzx_bits lb, ref ULONG bitbuf, 
            ref LONG bitsleft, ref UBYTE[] ip, ref long inpos, LZXstate pState, ref UBYTE[] tablelen)
        {
            lb.bb = bitbuf;
            lb.bl = bitsleft;
            lb.ip = ip;
            lb.ippos = inpos;

            if (lzx_read_lens(pState, ref tablelen, first, last, lb) != 0)
                return false;

            bitbuf = lb.bb;
            bitsleft = lb.bl;
            inpos = lb.ippos;

            return true;
        }
Ejemplo n.º 3
0
        private static int lzx_read_lens(LZXstate pState, ref UBYTE[] lens, ULONG first, ULONG last, lzx_bits lb)
        {
            ULONG i = 0, j = 0, x = 0, y = 0;
            int z = 0;

            ULONG bitbuf = lb.bb;
            int bitsleft = lb.bl;
            long inpos = lb.ippos;
            UWORD[] hufftbl = null;
            bool hr;

            for (x = 0; x < 20; x++) {
                READ_BITS(ref y, 4, ref bitbuf, ref bitsleft, ref lb.ip, ref inpos);
                pState.PRETREE_len[x] = (byte)y;
            }
            if (!BUILD_TABLE(ref pState.PRETREE_table, ref pState.PRETREE_len,
                    LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS))
                return DECR_ILLEGALDATA;

            for (x = first; x < last; ) {
                hr = READ_HUFFSYM(ref pState.PRETREE_table, ref hufftbl, ref bitsleft,
                    ref bitbuf, ref lb.ip, ref inpos, ref i, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS,
                    ref pState.PRETREE_len, ref j, ref z);
                if (!hr)
                    return DECR_ILLEGALDATA;

                if (z == 17) {
                    READ_BITS(ref y, 4, ref bitbuf, ref bitsleft, ref lb.ip, ref inpos); y += 4;
                    while (Convert.ToBoolean(y--)) lens[x++] = 0;
                }
                else if (z == 18) {
                    READ_BITS(ref y, 5, ref bitbuf, ref bitsleft, ref lb.ip, ref inpos); y += 20;
                    while (Convert.ToBoolean(y--)) lens[x++] = 0;
                }
                else if (z == 19) {
                    READ_BITS(ref y, 1, ref bitbuf, ref bitsleft, ref lb.ip, ref inpos); y += 4;
                    hr = READ_HUFFSYM(ref pState.PRETREE_table, ref hufftbl, ref bitsleft,
                        ref bitbuf, ref lb.ip, ref inpos, ref i, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS,
                        ref pState.PRETREE_len, ref j, ref z);
                    if (!hr)
                        return DECR_ILLEGALDATA;

                    z = lens[x] - z; if (z < 0) z += 17;
                    while (Convert.ToBoolean(y--)) lens[x++] = (byte)z;
                }
                else {
                    z = lens[x] - z; if (z < 0) z += 17;
                    lens[x++] = (byte)z;
                }
            }

            lb.bb = bitbuf;
            lb.bl = bitsleft;
            lb.ippos = inpos;
            return 0;
        }
Ejemplo n.º 4
0
        public static int LZXdecompress(LZXstate pState, ref UBYTE[] ip, long inpos, ref UBYTE[] op, 
            ulong outpos, int inlen, int outlen)
        {
            long endinp = inpos + inlen;
            UBYTE[] window = pState.window;
            long runsrc = 0;
            long rundest = 0;
            UWORD[] hufftbl = null; /* used in READ_HUFFSYM macro as chosen decoding table */

            ULONG window_posn = pState.window_posn;
            ULONG window_size = pState.window_size;
            ULONG R0 = pState.R0;
            ULONG R1 = pState.R1;
            ULONG R2 = pState.R2;

            ULONG bitbuf = 0;
            int bitsleft = 0;
            ULONG match_offset, i = 0, j = 0, k = 0; /* ijk used in READ_HUFFSYM macro */
            lzx_bits lb = new lzx_bits(); /* used in READ_LENGTHS macro */
            bool hr;

            int togo = outlen, this_run, main_element = 0, aligned_bits = 0;
            int match_length, length_footer = 0, extra;
            uint verbatim_bits = 0;

            INIT_BITSTREAM(ref bitsleft, ref bitbuf);

            /* read header if necessary */
            if (!Convert.ToBoolean(pState.header_read)) {
                i = j = 0;
                READ_BITS(ref k, 1, ref bitbuf, ref bitsleft, ref ip, ref inpos);
                if (Convert.ToBoolean(k)) {
                    READ_BITS(ref i, 16, ref bitbuf, ref bitsleft, ref ip, ref inpos);
                    READ_BITS(ref j, 16, ref bitbuf, ref bitsleft, ref ip, ref inpos);
                }
                pState.intel_filesize = (LONG)((i << 16) | j); /* or 0 if not encoded */
                pState.header_read = 1;
            }

            /* main decoding loop */
            while (togo > 0) {
                /* last block finished, new block expected */
                if (pState.block_remaining == 0) {
                    if (pState.block_type == LZX_BLOCKTYPE_UNCOMPRESSED) {
                        if (Convert.ToBoolean(pState.block_length & 1)) inpos++; /* realign bitstream to word */
                        INIT_BITSTREAM(ref bitsleft, ref bitbuf);
                    }

                    READ_BITS(ref pState.block_type, 3, ref bitbuf, ref bitsleft, ref ip, ref inpos);
                    READ_BITS(ref i, 16, ref bitbuf, ref bitsleft, ref ip, ref inpos);
                    READ_BITS(ref j, 8, ref bitbuf, ref bitsleft, ref ip, ref inpos);
                    pState.block_remaining = pState.block_length = (i << 8) | j;

                    switch (pState.block_type) {
                        case LZX_BLOCKTYPE_ALIGNED:
                            for (i = 0; i < 8; i++) {
                                READ_BITS(ref j, 3, ref bitbuf, ref bitsleft, ref ip, ref inpos);
                                pState.ALIGNED_len[i] = (byte)j;
                            }
                            if (!BUILD_TABLE(ref pState.ALIGNED_table, ref pState.ALIGNED_len,
                                    LZX_ALIGNED_TABLEBITS, LZX_ALIGNED_MAXSYMBOLS))
                                return DECR_ILLEGALDATA;
                            /* rest of aligned header is same as verbatim */
                            goto case LZX_BLOCKTYPE_VERBATIM;

                        case LZX_BLOCKTYPE_VERBATIM:
                            if (!READ_LENGTHS(0, 256, lb, ref bitbuf, ref bitsleft, ref ip, ref inpos,
                                    pState, ref pState.MAINTREE_len))
                                return DECR_ILLEGALDATA;
                            if (!READ_LENGTHS(256, pState.main_elements, lb, ref bitbuf, ref bitsleft,
                                    ref ip, ref inpos, pState, ref pState.MAINTREE_len))
                                return DECR_ILLEGALDATA;
                            if (!BUILD_TABLE(ref pState.MAINTREE_table, ref pState.MAINTREE_len,
                                    LZX_MAINTREE_TABLEBITS, LZX_MAINTREE_MAXSYMBOLS))
                                return DECR_ILLEGALDATA;
                            if (pState.MAINTREE_len[0xE8] != 0) pState.intel_started = 1;

                            if (!READ_LENGTHS(0, LZX_NUM_SECONDARY_LENGTHS, lb, ref bitbuf, ref bitsleft,
                                    ref ip, ref inpos, pState, ref pState.LENGTH_len))
                                return DECR_ILLEGALDATA;
                            if (!BUILD_TABLE(ref pState.LENGTH_table, ref pState.LENGTH_len,
                                    LZX_LENGTH_TABLEBITS, LZX_LENGTH_MAXSYMBOLS))
                                return DECR_ILLEGALDATA;
                            break;

                        case LZX_BLOCKTYPE_UNCOMPRESSED:
                            pState.intel_started = 1; /* because we can't assume otherwise */
                            ENSURE_BITS(ref bitsleft, ref bitbuf, ref ip, ref inpos, 16); /* get up to 16 pad bits into the buffer */
                            if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */
                            R0 = (ULONG)(ip[inpos + 0]|(ip[inpos + 1]<<8)|(ip[inpos + 2]<<16)|(ip[inpos + 3]<<24));inpos+=4;
                            R1 = (ULONG)(ip[inpos + 0]|(ip[inpos + 1]<<8)|(ip[inpos + 2]<<16)|(ip[inpos + 3]<<24));inpos+=4;
                            R2 = (ULONG)(ip[inpos + 0]|(ip[inpos + 1]<<8)|(ip[inpos + 2]<<16)|(ip[inpos + 3]<<24));inpos+=4;
                            break;

                        default:
                            return DECR_ILLEGALDATA;
                    }
                }

                /* buffer exhaustion check */
                if (inpos > endinp) {
                    /* it's possible to have a file where the next run is less than
                     * 16 bits in size. In this case, the READ_HUFFSYM() macro used
                     * in building the tables will exhaust the buffer, so we should
                     * allow for this, but not allow those accidentally read bits to
                     * be used (so we check that there are at least 16 bits
                     * remaining - in this boundary case they aren't really part of
                     * the compressed data)
                     */
                    if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA;
                }

                while ((this_run = (LONG)pState.block_remaining) > 0 && togo > 0) {
                    if (this_run > togo) this_run = togo;
                    togo -= this_run;
                    pState.block_remaining -= (ULONG)this_run;

                    /* apply 2^x-1 mask */
                    window_posn &= window_size - 1;
                    /* runs can't straddle the window wraparound */
                    if ((window_posn + this_run) > window_size)
                        return DECR_DATAFORMAT;

                    switch (pState.block_type) {

                        case LZX_BLOCKTYPE_VERBATIM:
                            while (this_run > 0) {
                                hr = READ_HUFFSYM(ref pState.MAINTREE_table, ref hufftbl, ref bitsleft,
                                    ref bitbuf, ref ip, ref inpos, ref i, LZX_MAINTREE_TABLEBITS,
                                    LZX_MAINTREE_MAXSYMBOLS, ref pState.MAINTREE_len, ref j, ref main_element);
                                if (!hr)
                                    return DECR_ILLEGALDATA;

                                if (main_element < LZX_NUM_CHARS) {
                                    /* literal: 0 to LZX_NUM_CHARS-1 */
                                    window[window_posn++] = (UBYTE)main_element;
                                    this_run--;
                                }
                                else {
                                    /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
                                    main_element -= LZX_NUM_CHARS;

                                    match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
                                    if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
                                        hr = READ_HUFFSYM(ref pState.LENGTH_table, ref hufftbl, ref bitsleft,
                                            ref bitbuf, ref ip, ref inpos, ref i, LZX_LENGTH_TABLEBITS,
                                            LZX_LENGTH_MAXSYMBOLS, ref pState.LENGTH_len, ref j, ref length_footer);
                                        if (!hr)
                                            return DECR_ILLEGALDATA;
                                        match_length += length_footer;
                                    }
                                    match_length += LZX_MIN_MATCH;

                                    match_offset = (ULONG)main_element >> 3;

                                    if (match_offset > 2) {
                                        /* not repeated offset */
                                        if (match_offset != 3) {
                                            extra = extra_bits[match_offset];
                                            READ_BITS(ref verbatim_bits, extra, ref bitbuf, ref bitsleft,
                                                ref ip, ref inpos);
                                            match_offset = position_base[match_offset] - 2 + verbatim_bits;
                                        }
                                        else {
                                            match_offset = 1;
                                        }

                                        /* update repeated offset LRU queue */
                                        R2 = R1; R1 = R0; R0 = match_offset;
                                    }
                                    else if (match_offset == 0) {
                                        match_offset = R0;
                                    }
                                    else if (match_offset == 1) {
                                        match_offset = R1;
                                        R1 = R0; R0 = match_offset;
                                    }
                                    else /* match_offset == 2 */ {
                                        match_offset = R2;
                                        R2 = R0; R0 = match_offset;
                                    }

                                    rundest = window_posn;
                                    runsrc  = rundest - match_offset;
                                    window_posn += (ULONG)match_length;
                                    if (window_posn > window_size) return DECR_ILLEGALDATA;
                                    this_run -= match_length;

                                    /* copy any wrapped around source data */
                                    while ((runsrc < 0) && (match_length-- > 0)) {
                                        window[rundest++] = window[runsrc + window_size]; runsrc++;
                                    }

                                    /* copy match data - no worries about destination wraps */
                                    while (match_length-- > 0) window[rundest++] = window[runsrc++];
                                }
                            }
                            break;

                        case LZX_BLOCKTYPE_ALIGNED:
                            while (this_run > 0) {
                                hr = READ_HUFFSYM(ref pState.MAINTREE_table, ref hufftbl, ref bitsleft,
                                    ref bitbuf, ref ip, ref inpos, ref i, LZX_MAINTREE_TABLEBITS,
                                    LZX_MAINTREE_MAXSYMBOLS, ref pState.MAINTREE_len, ref j, ref main_element);
                                if (!hr)
                                    return DECR_ILLEGALDATA;

                                if (main_element < LZX_NUM_CHARS) {
                                    /* literal: 0 to LZX_NUM_CHARS-1 */
                                    window[window_posn++] = (UBYTE)main_element;
                                    this_run--;
                                }
                                else {
                                    /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
                                    main_element -= LZX_NUM_CHARS;

                                    match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
                                    if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
                                        hr = READ_HUFFSYM(ref pState.LENGTH_table, ref hufftbl, ref bitsleft,
                                            ref bitbuf, ref ip, ref inpos, ref i, LZX_LENGTH_TABLEBITS,
                                            LZX_LENGTH_MAXSYMBOLS, ref pState.LENGTH_len, ref j, ref length_footer);
                                        if (!hr)
                                            return DECR_ILLEGALDATA;
                                        match_length += length_footer;
                                    }
                                    match_length += LZX_MIN_MATCH;

                                    match_offset = (ULONG)main_element >> 3;

                                    if (match_offset > 2) {
                                        /* not repeated offset */
                                        extra = extra_bits[match_offset];
                                        match_offset = position_base[match_offset] - 2;
                                        if (extra > 3) {
                                            /* verbatim and aligned bits */
                                            extra -= 3;
                                            READ_BITS(ref verbatim_bits, extra, ref bitbuf, ref bitsleft,
                                                ref ip, ref inpos);
                                            match_offset += (verbatim_bits << 3);
                                            hr = READ_HUFFSYM(ref pState.ALIGNED_table, ref hufftbl, ref bitsleft,
                                                ref bitbuf, ref ip, ref inpos, ref i, LZX_ALIGNED_TABLEBITS,
                                                LZX_ALIGNED_MAXSYMBOLS, ref pState.ALIGNED_len, ref j, ref aligned_bits);
                                            if (!hr)
                                                return DECR_ILLEGALDATA;
                                            match_offset += (ULONG)aligned_bits;
                                        }
                                        else if (extra == 3) {
                                            /* aligned bits only */
                                            hr = READ_HUFFSYM(ref pState.ALIGNED_table, ref hufftbl, ref bitsleft,
                                                ref bitbuf, ref ip, ref inpos, ref i, LZX_ALIGNED_TABLEBITS,
                                                LZX_ALIGNED_MAXSYMBOLS, ref pState.ALIGNED_len, ref j, ref aligned_bits);
                                            if (!hr)
                                                return DECR_ILLEGALDATA;
                                            match_offset += (ULONG)aligned_bits;
                                        }
                                        else if (extra > 0) { /* extra==1, extra==2 */
                                            /* verbatim bits only */
                                            READ_BITS(ref verbatim_bits, extra, ref bitbuf, ref bitsleft,
                                                ref ip, ref inpos);
                                            match_offset += verbatim_bits;
                                        }
                                        else /* extra == 0 */ {
                                            /* ??? */
                                            match_offset = 1;
                                        }

                                        /* update repeated offset LRU queue */
                                        R2 = R1; R1 = R0; R0 = match_offset;
                                    }
                                    else if (match_offset == 0) {
                                        match_offset = R0;
                                    }
                                    else if (match_offset == 1) {
                                        match_offset = R1;
                                        R1 = R0; R0 = match_offset;
                                    }
                                    else /* match_offset == 2 */ {
                                        match_offset = R2;
                                        R2 = R0; R0 = match_offset;
                                    }

                                    rundest = window_posn;
                                    runsrc  = rundest - match_offset;
                                    window_posn += (ULONG)match_length;
                                    if (window_posn > window_size) return DECR_ILLEGALDATA;
                                    this_run -= match_length;

                                    /* copy any wrapped around source data */
                                    while ((runsrc < 0) && (match_length-- > 0)) {
                                        window[rundest++] = window[runsrc + window_size]; runsrc++;
                                    }
                                    /* copy match data - no worries about destination wraps */
                                    while (match_length-- > 0) window[rundest++] = window[runsrc++];

                                }
                            }
                            break;

                        case LZX_BLOCKTYPE_UNCOMPRESSED:
                            if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA;
                            Array.Copy(ip, inpos, window, window_posn, this_run);
                            inpos += this_run; window_posn += (ULONG)this_run;
                            break;

                        default:
                            return DECR_ILLEGALDATA; /* might as well */
                    }

                }
            }

            if (togo != 0) return DECR_ILLEGALDATA;
            Array.Copy(
                window,
                (!Convert.ToBoolean(window_posn) ? window_size : window_posn) - outlen,
                op,
                (long)outpos,
                outlen);

            pState.window_posn = window_posn;
            pState.R0 = R0;
            pState.R1 = R1;
            pState.R2 = R2;

            /* intel E8 decoding */
            if ((pState.frames_read++ < 32768) && pState.intel_filesize != 0) {
                if (outlen <= 6 || !Convert.ToBoolean(pState.intel_started)) {
                    pState.intel_curpos += outlen;
                }
                else {
                    ulong data    = outpos;
                    ulong dataend = outpos + (ulong)outlen - 10;
                    LONG curpos    = pState.intel_curpos;
                    LONG filesize  = pState.intel_filesize;
                    LONG abs_off, rel_off;

                    pState.intel_curpos = curpos + outlen;

                    while (data < dataend) {
                        if (op[data++] != 0xE8) { curpos++; continue; }
                        abs_off = op[data + 0] | (op[data + 1]<<8) | (op[data + 2]<<16) | (op[data + 3]<<24);
                        if ((abs_off >= -curpos) && (abs_off < filesize)) {
                            rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
                            op[data + 0] = (UBYTE) rel_off;
                            op[data + 1] = (UBYTE)(rel_off >> 8);
                            op[data + 2] = (UBYTE)(rel_off >> 16);
                            op[data + 3] = (UBYTE)(rel_off >> 24);
                        }
                        data += 4;
                        curpos += 5;
                    }
                }
            }
            return DECR_OK;
        }
Ejemplo n.º 5
0
 static public void READ_LENGTHS(LZXstate pState, ref uint bitbuf, ref int bitsleft, ref byte *inpos, ref lzx_bits lb, Table tbl, uint first, uint last)
 {
     fixed(lzx_bits *lbp = &lb)
     {
         lb.bb = bitbuf;
         lb.bl = bitsleft;
         lb.ip = inpos;
         if (lzx_read_lens(pState, LENTABLE(tbl), (first), (last), lbp))
         {
             throw (new InvalidDataException());
         }
         bitbuf   = lb.bb;
         bitsleft = lb.bl;
         inpos    = lb.ip;
     }
 }
Ejemplo n.º 6
0
        public static int LZXdecompress(LZXstate pState, ref UBYTE[] ip, long inpos, ref UBYTE[] op,
                                        ulong outpos, int inlen, int outlen)
        {
            long endinp = inpos + inlen;

            UBYTE[] window  = pState.window;
            long    runsrc  = 0;
            long    rundest = 0;

            UWORD[] hufftbl = null; /* used in READ_HUFFSYM macro as chosen decoding table */

            ULONG window_posn = pState.window_posn;
            ULONG window_size = pState.window_size;
            ULONG R0          = pState.R0;
            ULONG R1          = pState.R1;
            ULONG R2          = pState.R2;

            ULONG    bitbuf = 0;
            int      bitsleft = 0;
            ULONG    match_offset, i = 0, j = 0, k = 0; /* ijk used in READ_HUFFSYM macro */
            lzx_bits lb = new lzx_bits();               /* used in READ_LENGTHS macro */
            bool     hr;

            int  togo = outlen, this_run, main_element = 0, aligned_bits = 0;
            int  match_length, length_footer = 0, extra;
            uint verbatim_bits = 0;

            INIT_BITSTREAM(ref bitsleft, ref bitbuf);

            /* read header if necessary */
            if (!Convert.ToBoolean(pState.header_read))
            {
                i = j = 0;
                READ_BITS(ref k, 1, ref bitbuf, ref bitsleft, ref ip, ref inpos);
                if (Convert.ToBoolean(k))
                {
                    READ_BITS(ref i, 16, ref bitbuf, ref bitsleft, ref ip, ref inpos);
                    READ_BITS(ref j, 16, ref bitbuf, ref bitsleft, ref ip, ref inpos);
                }
                pState.intel_filesize = (LONG)((i << 16) | j); /* or 0 if not encoded */
                pState.header_read    = 1;
            }

            /* main decoding loop */
            while (togo > 0)
            {
                /* last block finished, new block expected */
                if (pState.block_remaining == 0)
                {
                    if (pState.block_type == LZX_BLOCKTYPE_UNCOMPRESSED)
                    {
                        if (Convert.ToBoolean(pState.block_length & 1))
                        {
                            inpos++;                                             /* realign bitstream to word */
                        }
                        INIT_BITSTREAM(ref bitsleft, ref bitbuf);
                    }

                    READ_BITS(ref pState.block_type, 3, ref bitbuf, ref bitsleft, ref ip, ref inpos);
                    READ_BITS(ref i, 16, ref bitbuf, ref bitsleft, ref ip, ref inpos);
                    READ_BITS(ref j, 8, ref bitbuf, ref bitsleft, ref ip, ref inpos);
                    pState.block_remaining = pState.block_length = (i << 8) | j;

                    switch (pState.block_type)
                    {
                    case LZX_BLOCKTYPE_ALIGNED:
                        for (i = 0; i < 8; i++)
                        {
                            READ_BITS(ref j, 3, ref bitbuf, ref bitsleft, ref ip, ref inpos);
                            pState.ALIGNED_len[i] = (byte)j;
                        }
                        if (!BUILD_TABLE(ref pState.ALIGNED_table, ref pState.ALIGNED_len,
                                         LZX_ALIGNED_TABLEBITS, LZX_ALIGNED_MAXSYMBOLS))
                        {
                            return(DECR_ILLEGALDATA);
                        }
                        /* rest of aligned header is same as verbatim */
                        goto case LZX_BLOCKTYPE_VERBATIM;

                    case LZX_BLOCKTYPE_VERBATIM:
                        if (!READ_LENGTHS(0, 256, lb, ref bitbuf, ref bitsleft, ref ip, ref inpos,
                                          pState, ref pState.MAINTREE_len))
                        {
                            return(DECR_ILLEGALDATA);
                        }
                        if (!READ_LENGTHS(256, pState.main_elements, lb, ref bitbuf, ref bitsleft,
                                          ref ip, ref inpos, pState, ref pState.MAINTREE_len))
                        {
                            return(DECR_ILLEGALDATA);
                        }
                        if (!BUILD_TABLE(ref pState.MAINTREE_table, ref pState.MAINTREE_len,
                                         LZX_MAINTREE_TABLEBITS, LZX_MAINTREE_MAXSYMBOLS))
                        {
                            return(DECR_ILLEGALDATA);
                        }
                        if (pState.MAINTREE_len[0xE8] != 0)
                        {
                            pState.intel_started = 1;
                        }

                        if (!READ_LENGTHS(0, LZX_NUM_SECONDARY_LENGTHS, lb, ref bitbuf, ref bitsleft,
                                          ref ip, ref inpos, pState, ref pState.LENGTH_len))
                        {
                            return(DECR_ILLEGALDATA);
                        }
                        if (!BUILD_TABLE(ref pState.LENGTH_table, ref pState.LENGTH_len,
                                         LZX_LENGTH_TABLEBITS, LZX_LENGTH_MAXSYMBOLS))
                        {
                            return(DECR_ILLEGALDATA);
                        }
                        break;

                    case LZX_BLOCKTYPE_UNCOMPRESSED:
                        pState.intel_started = 1;                                     /* because we can't assume otherwise */
                        ENSURE_BITS(ref bitsleft, ref bitbuf, ref ip, ref inpos, 16); /* get up to 16 pad bits into the buffer */
                        if (bitsleft > 16)
                        {
                            inpos -= 2;                    /* and align the bitstream! */
                        }
                        R0 = (ULONG)(ip[inpos + 0] | (ip[inpos + 1] << 8) | (ip[inpos + 2] << 16) | (ip[inpos + 3] << 24)); inpos += 4;
                        R1 = (ULONG)(ip[inpos + 0] | (ip[inpos + 1] << 8) | (ip[inpos + 2] << 16) | (ip[inpos + 3] << 24)); inpos += 4;
                        R2 = (ULONG)(ip[inpos + 0] | (ip[inpos + 1] << 8) | (ip[inpos + 2] << 16) | (ip[inpos + 3] << 24)); inpos += 4;
                        break;

                    default:
                        return(DECR_ILLEGALDATA);
                    }
                }

                /* buffer exhaustion check */
                if (inpos > endinp)
                {
                    /* it's possible to have a file where the next run is less than
                     * 16 bits in size. In this case, the READ_HUFFSYM() macro used
                     * in building the tables will exhaust the buffer, so we should
                     * allow for this, but not allow those accidentally read bits to
                     * be used (so we check that there are at least 16 bits
                     * remaining - in this boundary case they aren't really part of
                     * the compressed data)
                     */
                    if (inpos > (endinp + 2) || bitsleft < 16)
                    {
                        return(DECR_ILLEGALDATA);
                    }
                }

                while ((this_run = (LONG)pState.block_remaining) > 0 && togo > 0)
                {
                    if (this_run > togo)
                    {
                        this_run = togo;
                    }
                    togo -= this_run;
                    pState.block_remaining -= (ULONG)this_run;

                    /* apply 2^x-1 mask */
                    window_posn &= window_size - 1;
                    /* runs can't straddle the window wraparound */
                    if ((window_posn + this_run) > window_size)
                    {
                        return(DECR_DATAFORMAT);
                    }

                    switch (pState.block_type)
                    {
                    case LZX_BLOCKTYPE_VERBATIM:
                        while (this_run > 0)
                        {
                            hr = READ_HUFFSYM(ref pState.MAINTREE_table, ref hufftbl, ref bitsleft,
                                              ref bitbuf, ref ip, ref inpos, ref i, LZX_MAINTREE_TABLEBITS,
                                              LZX_MAINTREE_MAXSYMBOLS, ref pState.MAINTREE_len, ref j, ref main_element);
                            if (!hr)
                            {
                                return(DECR_ILLEGALDATA);
                            }

                            if (main_element < LZX_NUM_CHARS)
                            {
                                /* literal: 0 to LZX_NUM_CHARS-1 */
                                window[window_posn++] = (UBYTE)main_element;
                                this_run--;
                            }
                            else
                            {
                                /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
                                main_element -= LZX_NUM_CHARS;

                                match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
                                if (match_length == LZX_NUM_PRIMARY_LENGTHS)
                                {
                                    hr = READ_HUFFSYM(ref pState.LENGTH_table, ref hufftbl, ref bitsleft,
                                                      ref bitbuf, ref ip, ref inpos, ref i, LZX_LENGTH_TABLEBITS,
                                                      LZX_LENGTH_MAXSYMBOLS, ref pState.LENGTH_len, ref j, ref length_footer);
                                    if (!hr)
                                    {
                                        return(DECR_ILLEGALDATA);
                                    }
                                    match_length += length_footer;
                                }
                                match_length += LZX_MIN_MATCH;

                                match_offset = (ULONG)main_element >> 3;

                                if (match_offset > 2)
                                {
                                    /* not repeated offset */
                                    if (match_offset != 3)
                                    {
                                        extra = extra_bits[match_offset];
                                        READ_BITS(ref verbatim_bits, extra, ref bitbuf, ref bitsleft,
                                                  ref ip, ref inpos);
                                        match_offset = position_base[match_offset] - 2 + verbatim_bits;
                                    }
                                    else
                                    {
                                        match_offset = 1;
                                    }

                                    /* update repeated offset LRU queue */
                                    R2 = R1; R1 = R0; R0 = match_offset;
                                }
                                else if (match_offset == 0)
                                {
                                    match_offset = R0;
                                }
                                else if (match_offset == 1)
                                {
                                    match_offset = R1;
                                    R1           = R0; R0 = match_offset;
                                }
                                else     /* match_offset == 2 */
                                {
                                    match_offset = R2;
                                    R2           = R0; R0 = match_offset;
                                }

                                rundest      = window_posn;
                                runsrc       = rundest - match_offset;
                                window_posn += (ULONG)match_length;
                                if (window_posn > window_size)
                                {
                                    return(DECR_ILLEGALDATA);
                                }
                                this_run -= match_length;

                                /* copy any wrapped around source data */
                                while ((runsrc < 0) && (match_length-- > 0))
                                {
                                    window[rundest++] = window[runsrc + window_size]; runsrc++;
                                }

                                /* copy match data - no worries about destination wraps */
                                while (match_length-- > 0)
                                {
                                    window[rundest++] = window[runsrc++];
                                }
                            }
                        }
                        break;

                    case LZX_BLOCKTYPE_ALIGNED:
                        while (this_run > 0)
                        {
                            hr = READ_HUFFSYM(ref pState.MAINTREE_table, ref hufftbl, ref bitsleft,
                                              ref bitbuf, ref ip, ref inpos, ref i, LZX_MAINTREE_TABLEBITS,
                                              LZX_MAINTREE_MAXSYMBOLS, ref pState.MAINTREE_len, ref j, ref main_element);
                            if (!hr)
                            {
                                return(DECR_ILLEGALDATA);
                            }

                            if (main_element < LZX_NUM_CHARS)
                            {
                                /* literal: 0 to LZX_NUM_CHARS-1 */
                                window[window_posn++] = (UBYTE)main_element;
                                this_run--;
                            }
                            else
                            {
                                /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
                                main_element -= LZX_NUM_CHARS;

                                match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
                                if (match_length == LZX_NUM_PRIMARY_LENGTHS)
                                {
                                    hr = READ_HUFFSYM(ref pState.LENGTH_table, ref hufftbl, ref bitsleft,
                                                      ref bitbuf, ref ip, ref inpos, ref i, LZX_LENGTH_TABLEBITS,
                                                      LZX_LENGTH_MAXSYMBOLS, ref pState.LENGTH_len, ref j, ref length_footer);
                                    if (!hr)
                                    {
                                        return(DECR_ILLEGALDATA);
                                    }
                                    match_length += length_footer;
                                }
                                match_length += LZX_MIN_MATCH;

                                match_offset = (ULONG)main_element >> 3;

                                if (match_offset > 2)
                                {
                                    /* not repeated offset */
                                    extra        = extra_bits[match_offset];
                                    match_offset = position_base[match_offset] - 2;
                                    if (extra > 3)
                                    {
                                        /* verbatim and aligned bits */
                                        extra -= 3;
                                        READ_BITS(ref verbatim_bits, extra, ref bitbuf, ref bitsleft,
                                                  ref ip, ref inpos);
                                        match_offset += (verbatim_bits << 3);
                                        hr            = READ_HUFFSYM(ref pState.ALIGNED_table, ref hufftbl, ref bitsleft,
                                                                     ref bitbuf, ref ip, ref inpos, ref i, LZX_ALIGNED_TABLEBITS,
                                                                     LZX_ALIGNED_MAXSYMBOLS, ref pState.ALIGNED_len, ref j, ref aligned_bits);
                                        if (!hr)
                                        {
                                            return(DECR_ILLEGALDATA);
                                        }
                                        match_offset += (ULONG)aligned_bits;
                                    }
                                    else if (extra == 3)
                                    {
                                        /* aligned bits only */
                                        hr = READ_HUFFSYM(ref pState.ALIGNED_table, ref hufftbl, ref bitsleft,
                                                          ref bitbuf, ref ip, ref inpos, ref i, LZX_ALIGNED_TABLEBITS,
                                                          LZX_ALIGNED_MAXSYMBOLS, ref pState.ALIGNED_len, ref j, ref aligned_bits);
                                        if (!hr)
                                        {
                                            return(DECR_ILLEGALDATA);
                                        }
                                        match_offset += (ULONG)aligned_bits;
                                    }
                                    else if (extra > 0)       /* extra==1, extra==2 */
                                    /* verbatim bits only */
                                    {
                                        READ_BITS(ref verbatim_bits, extra, ref bitbuf, ref bitsleft,
                                                  ref ip, ref inpos);
                                        match_offset += verbatim_bits;
                                    }
                                    else     /* extra == 0 */
                                    {
                                        /* ??? */
                                        match_offset = 1;
                                    }

                                    /* update repeated offset LRU queue */
                                    R2 = R1; R1 = R0; R0 = match_offset;
                                }
                                else if (match_offset == 0)
                                {
                                    match_offset = R0;
                                }
                                else if (match_offset == 1)
                                {
                                    match_offset = R1;
                                    R1           = R0; R0 = match_offset;
                                }
                                else     /* match_offset == 2 */
                                {
                                    match_offset = R2;
                                    R2           = R0; R0 = match_offset;
                                }

                                rundest      = window_posn;
                                runsrc       = rundest - match_offset;
                                window_posn += (ULONG)match_length;
                                if (window_posn > window_size)
                                {
                                    return(DECR_ILLEGALDATA);
                                }
                                this_run -= match_length;

                                /* copy any wrapped around source data */
                                while ((runsrc < 0) && (match_length-- > 0))
                                {
                                    window[rundest++] = window[runsrc + window_size]; runsrc++;
                                }
                                /* copy match data - no worries about destination wraps */
                                while (match_length-- > 0)
                                {
                                    window[rundest++] = window[runsrc++];
                                }
                            }
                        }
                        break;

                    case LZX_BLOCKTYPE_UNCOMPRESSED:
                        if ((inpos + this_run) > endinp)
                        {
                            return(DECR_ILLEGALDATA);
                        }
                        Array.Copy(ip, inpos, window, window_posn, this_run);
                        inpos += this_run; window_posn += (ULONG)this_run;
                        break;

                    default:
                        return(DECR_ILLEGALDATA);    /* might as well */
                    }
                }
            }

            if (togo != 0)
            {
                return(DECR_ILLEGALDATA);
            }
            Array.Copy(
                window,
                (!Convert.ToBoolean(window_posn) ? window_size : window_posn) - outlen,
                op,
                (long)outpos,
                outlen);

            pState.window_posn = window_posn;
            pState.R0          = R0;
            pState.R1          = R1;
            pState.R2          = R2;

            /* intel E8 decoding */
            if ((pState.frames_read++ < 32768) && pState.intel_filesize != 0)
            {
                if (outlen <= 6 || !Convert.ToBoolean(pState.intel_started))
                {
                    pState.intel_curpos += outlen;
                }
                else
                {
                    ulong data = outpos;
                    ulong dataend = outpos + (ulong)outlen - 10;
                    LONG  curpos = pState.intel_curpos;
                    LONG  filesize = pState.intel_filesize;
                    LONG  abs_off, rel_off;

                    pState.intel_curpos = curpos + outlen;

                    while (data < dataend)
                    {
                        if (op[data++] != 0xE8)
                        {
                            curpos++; continue;
                        }
                        abs_off = op[data + 0] | (op[data + 1] << 8) | (op[data + 2] << 16) | (op[data + 3] << 24);
                        if ((abs_off >= -curpos) && (abs_off < filesize))
                        {
                            rel_off      = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
                            op[data + 0] = (UBYTE)rel_off;
                            op[data + 1] = (UBYTE)(rel_off >> 8);
                            op[data + 2] = (UBYTE)(rel_off >> 16);
                            op[data + 3] = (UBYTE)(rel_off >> 24);
                        }
                        data   += 4;
                        curpos += 5;
                    }
                }
            }
            return(DECR_OK);
        }
Ejemplo n.º 7
0
        private static int lzx_read_lens(LZXstate pState, ref UBYTE[] lens, ULONG first, ULONG last, lzx_bits lb)
        {
            ULONG i = 0, j = 0, x = 0, y = 0;
            int   z = 0;

            ULONG bitbuf   = lb.bb;
            int   bitsleft = lb.bl;
            long  inpos    = lb.ippos;

            UWORD[] hufftbl = null;
            bool    hr;

            for (x = 0; x < 20; x++)
            {
                READ_BITS(ref y, 4, ref bitbuf, ref bitsleft, ref lb.ip, ref inpos);
                pState.PRETREE_len[x] = (byte)y;
            }
            if (!BUILD_TABLE(ref pState.PRETREE_table, ref pState.PRETREE_len,
                             LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS))
            {
                return(DECR_ILLEGALDATA);
            }

            for (x = first; x < last;)
            {
                hr = READ_HUFFSYM(ref pState.PRETREE_table, ref hufftbl, ref bitsleft,
                                  ref bitbuf, ref lb.ip, ref inpos, ref i, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS,
                                  ref pState.PRETREE_len, ref j, ref z);
                if (!hr)
                {
                    return(DECR_ILLEGALDATA);
                }

                if (z == 17)
                {
                    READ_BITS(ref y, 4, ref bitbuf, ref bitsleft, ref lb.ip, ref inpos); y += 4;
                    while (Convert.ToBoolean(y--))
                    {
                        lens[x++] = 0;
                    }
                }
                else if (z == 18)
                {
                    READ_BITS(ref y, 5, ref bitbuf, ref bitsleft, ref lb.ip, ref inpos); y += 20;
                    while (Convert.ToBoolean(y--))
                    {
                        lens[x++] = 0;
                    }
                }
                else if (z == 19)
                {
                    READ_BITS(ref y, 1, ref bitbuf, ref bitsleft, ref lb.ip, ref inpos); y += 4;
                    hr = READ_HUFFSYM(ref pState.PRETREE_table, ref hufftbl, ref bitsleft,
                                      ref bitbuf, ref lb.ip, ref inpos, ref i, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS,
                                      ref pState.PRETREE_len, ref j, ref z);
                    if (!hr)
                    {
                        return(DECR_ILLEGALDATA);
                    }

                    z = lens[x] - z; if (z < 0)
                    {
                        z += 17;
                    }
                    while (Convert.ToBoolean(y--))
                    {
                        lens[x++] = (byte)z;
                    }
                }
                else
                {
                    z = lens[x] - z; if (z < 0)
                    {
                        z += 17;
                    }
                    lens[x++] = (byte)z;
                }
            }

            lb.bb    = bitbuf;
            lb.bl    = bitsleft;
            lb.ippos = inpos;
            return(0);
        }