Ejemplo n.º 1
0
        static public LZXstate LZXinit(int window)
        {
            LZXstate pState = null;
            uint     wndsize = (uint)(1 << window);
            int      i, posn_slots;

            // LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb)
            // if a previously allocated window is big enough, keep it
            if (window < 15 || window > 21)
            {
                return(null);
            }

            // allocate state and associated window
            pState             = new LZXstate();
            pState.window      = new byte[wndsize];
            pState.actual_size = wndsize;
            pState.window_size = wndsize;

            // calculate required position slots
            if (window == 20)
            {
                posn_slots = 42;
            }
            else if (window == 21)
            {
                posn_slots = 50;
            }
            else
            {
                posn_slots = window << 1;
            }

            // alternatively
            // posn_slots=i=0; while (i < wndsize) i += 1 << extra_bits[posn_slots++];

            // initialize other state
            pState.R0              = pState.R1 = pState.R2 = 1;
            pState.main_elements   = (ushort)(LZX_NUM_CHARS + (posn_slots << 3));
            pState.header_read     = 0;
            pState.frames_read     = 0;
            pState.block_remaining = 0;
            pState.block_type      = LZX_BLOCKTYPE_INVALID;
            pState.intel_curpos    = 0;
            pState.intel_started   = false;
            pState.window_posn     = 0;

            // initialise tables to 0 (because deltas will be applied to them)
            for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++)
            {
                pState.MAINTREE.len[i] = 0;
            }
            for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
            {
                pState.LENGTH.len[i] = 0;
            }

            return(pState);
        }
Ejemplo n.º 2
0
 static public void LZXteardown(LZXstate pState)
 {
     /*
      * if (pState)
      * {
      *      free(pState.window);
      *      free(pState);
      * }
      */
 }
Ejemplo n.º 3
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.º 4
0
        static public int LZXreset(LZXstate pState)
        {
            int i;

            pState.R0              = pState.R1 = pState.R2 = 1;
            pState.header_read     = 0;
            pState.frames_read     = 0;
            pState.block_remaining = 0;
            pState.block_type      = LZX_BLOCKTYPE_INVALID;
            pState.intel_curpos    = 0;
            pState.intel_started   = false;
            pState.window_posn     = 0;

            for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS + LZX_LENTABLE_SAFETY; i++)
            {
                pState.MAINTREE.len[i] = 0;
            }
            for (i = 0; i < LZX_LENGTH_MAXSYMBOLS + LZX_LENTABLE_SAFETY; i++)
            {
                pState.LENGTH.len[i] = 0;
            }

            return(DECR_OK);
        }
Ejemplo n.º 5
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.º 6
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.º 7
0
 public static void LZXteardown(LZXstate pState)
 {
 }
Ejemplo n.º 8
0
        public static int LZXreset(LZXstate pState)
        {
            int i;

            pState.R0  =  pState.R1  = pState.R2 = 1;
            pState.header_read     = 0;
            pState.frames_read     = 0;
            pState.block_remaining = 0;
            pState.block_type      = LZX_BLOCKTYPE_INVALID;
            pState.intel_curpos    = 0;
            pState.intel_started   = 0;
            pState.window_posn     = 0;

            for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS + LZX_LENTABLE_SAFETY; i++) pState.MAINTREE_len[i] = 0;
            for (i = 0; i < LZX_LENGTH_MAXSYMBOLS + LZX_LENTABLE_SAFETY; i++)   pState.LENGTH_len[i]   = 0;

            return DECR_OK;
        }
Ejemplo n.º 9
0
        public static LZXstate LZXinit(int window)
        {
            LZXstate pState = null;
            ULONG wndsize = (ULONG)(1 << window);
            int i, posn_slots;

            /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
            /* if a previously allocated window is big enough, keep it     */
            if (window < 15 || window > 21) return null;

            /* allocate state and associated window */
            pState = new LZXstate();
            pState.window = new UBYTE[wndsize];
            pState.actual_size = wndsize;
            pState.window_size = wndsize;

            /* calculate required position slots */
            if (window == 20) posn_slots = 42;
            else if (window == 21) posn_slots = 50;
            else posn_slots = window << 1;

            /** alternatively **/
            /* posn_slots=i=0; while (i < wndsize) i += 1 << extra_bits[posn_slots++]; */

            /* initialize other state */
            pState.R0  =  pState.R1  = pState.R2 = 1;
            pState.main_elements   = (UWORD)(LZX_NUM_CHARS + (posn_slots << 3));
            pState.header_read     = 0;
            pState.frames_read     = 0;
            pState.block_remaining = 0;
            pState.block_type      = LZX_BLOCKTYPE_INVALID;
            pState.intel_curpos    = 0;
            pState.intel_started   = 0;
            pState.window_posn     = 0;

            /* initialise tables to 0 (because deltas will be applied to them) */
            for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++) pState.MAINTREE_len[i] = 0;
            for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)   pState.LENGTH_len[i]   = 0;

            return pState;
        }
Ejemplo n.º 10
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.º 11
0
        static public int LZXdecompress(LZXstate pState, byte *inpos, byte *outpos, int inlen, int outlen)
        {
            fixed(byte *window = pState.window)
            {
                byte *endinp = inpos + inlen;
                byte *runsrc;
                byte *rundest;

                ushort[] hufftbl;                 // used in READ_HUFFSYM macro as chosen decoding table

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

                uint bitbuf;
                int  bitsleft;
                uint match_offset, i = 0, j = 0, k = 0;     /* ijk used in READ_HUFFSYM macro */
                var  lb = default(lzx_bits);                /* used in READ_LENGTHS macro */

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

                //INIT_BITSTREAM();
                bitsleft = 0;
                bitbuf   = 0;

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

                // main decoding loop
                while (togo > 0)
                {
#if DEBUG_LZX_COMPRESSION
                    Console.WriteLine("------------------------------------------------------------");
                    Console.WriteLine("MainLoop togo: {0}, pState.block_remaining: {1}", togo, pState.block_remaining);
#endif
                    // last block finished, new block expected
                    if (pState.block_remaining == 0)
                    {
                        READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref pState.block_type, 3);
                        READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref i, 16);
                        READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref j, 8);
                        pState.block_remaining = pState.block_length = (i << 8) | j;

#if DEBUG_LZX_COMPRESSION
                        Console.WriteLine("BlockSize: {0}", pState.block_length);
#endif

                        switch (pState.block_type)
                        {
                        case LZX_BLOCKTYPE_ALIGNED:
#if DEBUG_LZX_COMPRESSION
                            Console.WriteLine("[L]LZX_BLOCKTYPE_ALIGNED");
#endif
                            for (i = 0; i < 8; i++)
                            {
                                READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref j, 3);
                                LENTABLE(pState.ALIGNED)[i] = (byte)j;
                            }
                            BUILD_TABLE(pState.ALIGNED);
                            /* rest of aligned header is same as verbatim */
                            goto case LZX_BLOCKTYPE_VERBATIM;

                        case LZX_BLOCKTYPE_VERBATIM:
#if DEBUG_LZX_COMPRESSION
                            Console.WriteLine("[L]LZX_BLOCKTYPE_VERBATIM");
#endif
                            READ_LENGTHS(pState, ref bitbuf, ref bitsleft, ref inpos, ref lb, pState.MAINTREE, 0, 256);
                            READ_LENGTHS(pState, ref bitbuf, ref bitsleft, ref inpos, ref lb, pState.MAINTREE, 256, pState.main_elements);
                            BUILD_TABLE(pState.MAINTREE);
                            if (LENTABLE(pState.MAINTREE)[0xE8] != 0)
                            {
                                pState.intel_started = true;
                            }

                            READ_LENGTHS(pState, ref bitbuf, ref bitsleft, ref inpos, ref lb, pState.LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS);
                            BUILD_TABLE(pState.LENGTH);
                            break;

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

                        default:
                            Console.Error.WriteLine("Invalid Block Type: {0}", pState.block_type);
                            return(DECR_ILLEGALDATA);
                        }
                    }

                    if (inpos > endinp)
                    {
                        if (inpos > (endinp + 2) || bitsleft < 16)
                        {
                            Console.Error.WriteLine("Error (inpos > endinp) && (inpos > (endinp + 2) || bitsleft < 16)");
                            return(DECR_ILLEGALDATA);
                        }
                    }

                    while ((this_run = (int)pState.block_remaining) > 0 && togo > 0)
                    {
                        if (this_run > togo)
                        {
                            this_run = togo;
                        }
                        togo -= this_run;
                        pState.block_remaining -= (uint)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:
#if DEBUG_LZX_COMPRESSION
                            Console.WriteLine("[B]LZX_BLOCKTYPE_VERBATIM");
#endif
                            while (this_run > 0)
                            {
                                READ_HUFFSYM(out hufftbl, ref bitsleft, ref inpos, ref bitbuf, ref i, ref j, pState.MAINTREE, out main_element);

                                if (main_element < LZX_NUM_CHARS)
                                {
                                    /* literal: 0 to LZX_NUM_CHARS-1 */
                                    window[window_posn++] = (byte)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)
                                    {
                                        READ_HUFFSYM(out hufftbl, ref bitsleft, ref inpos, ref bitbuf, ref i, ref j, pState.LENGTH, out length_footer);
                                        match_length += length_footer;
                                    }
                                    match_length += LZX_MIN_MATCH;

                                    match_offset = (uint)(main_element >> 3);

                                    if (match_offset > 2)
                                    {
                                        /* not repeated offset */
                                        if (match_offset != 3)
                                        {
                                            extra = extra_bits[match_offset];
                                            READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref verbatim_bits, extra);
                                            match_offset = (uint)(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 + window_posn;
                                    this_run -= match_length;

                                    /* copy any wrapped around source data */
                                    if (window_posn >= match_offset)
                                    {
                                        /* no wrap */
                                        runsrc = rundest - match_offset;
                                    }
                                    else
                                    {
                                        runsrc      = rundest + (window_size - match_offset);
                                        copy_length = (int)(match_offset - window_posn);
                                        if (copy_length < match_length)
                                        {
                                            match_length -= copy_length;
                                            window_posn  += (uint)copy_length;
                                            while (copy_length-- > 0)
                                            {
                                                *rundest++ = *runsrc++;
                                            }
                                            runsrc = window;
                                        }
                                    }
                                    window_posn += (uint)match_length;

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

                        case LZX_BLOCKTYPE_ALIGNED:
#if DEBUG_LZX_COMPRESSION
                            Console.WriteLine("[B]LZX_BLOCKTYPE_ALIGNED");
#endif
                            while (this_run > 0)
                            {
                                READ_HUFFSYM(out hufftbl, ref bitsleft, ref inpos, ref bitbuf, ref i, ref j, pState.MAINTREE, out main_element);

                                if (main_element < LZX_NUM_CHARS)
                                {
                                    /* literal: 0 to LZX_NUM_CHARS-1 */
                                    window[window_posn++] = (byte)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)
                                    {
                                        READ_HUFFSYM(out hufftbl, ref bitsleft, ref inpos, ref bitbuf, ref i, ref j, pState.LENGTH, out length_footer);
                                        match_length += length_footer;
                                    }
                                    match_length += LZX_MIN_MATCH;

                                    match_offset = (uint)(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 bitsleft, ref inpos, ref bitbuf, ref verbatim_bits, extra);
                                            match_offset += (uint)(verbatim_bits << 3);

                                            READ_HUFFSYM(out hufftbl, ref bitsleft, ref inpos, ref bitbuf, ref i, ref j, pState.ALIGNED, out aligned_bits);
                                            match_offset += (uint)aligned_bits;
                                        }
                                        else if (extra == 3)
                                        {
                                            /* aligned bits only */
                                            READ_HUFFSYM(out hufftbl, ref bitsleft, ref inpos, ref bitbuf, ref i, ref j, pState.ALIGNED, out aligned_bits);
                                            match_offset += (uint)aligned_bits;
                                        }
                                        else if (extra > 0)
                                        {                                         /* extra==1, extra==2 */
                                            /* verbatim bits only */
                                            READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref verbatim_bits, extra);
                                            match_offset += (uint)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 + window_posn;
                                    this_run -= match_length;

                                    /* copy any wrapped around source data */
                                    if (window_posn >= match_offset)
                                    {
                                        /* no wrap */
                                        runsrc = rundest - match_offset;
                                    }
                                    else
                                    {
                                        runsrc      = rundest + (window_size - match_offset);
                                        copy_length = (int)(match_offset - window_posn);
                                        if (copy_length < match_length)
                                        {
                                            match_length -= copy_length;
                                            window_posn  += (uint)copy_length;
                                            while (copy_length-- > 0)
                                            {
                                                *rundest++ = *runsrc++;
                                            }
                                            runsrc = window;
                                        }
                                    }
                                    window_posn += (uint)match_length;

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

                        case LZX_BLOCKTYPE_UNCOMPRESSED:
#if DEBUG_LZX_COMPRESSION
                            Console.WriteLine("[B]LZX_BLOCKTYPE_UNCOMPRESSED");
#endif
                            if ((inpos + this_run) > endinp)
                            {
                                Console.Error.WriteLine("Error: ((inpos + this_run) > endinp)");
                                return(DECR_ILLEGALDATA);
                            }
                            PointerUtils.Memcpy(window + window_posn, inpos, (int)this_run);
                            inpos += this_run; window_posn += (uint)this_run;
                            break;

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

                if (togo != 0)
                {
                    return(DECR_ILLEGALDATA);
                }
                PointerUtils.Memcpy(outpos, window + ((window_posn == 0) ? window_size : window_posn) - outlen, (int)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 || !pState.intel_started)
                    {
                        pState.intel_curpos += outlen;
                    }
                    else
                    {
                        byte *data = outpos;
                        byte *dataend = data + outlen - 10;
                        int   curpos = pState.intel_curpos;
                        int   filesize = pState.intel_filesize;
                        int   abs_off, rel_off;

                        pState.intel_curpos = curpos + outlen;

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

            uint  bitbuf   = lb->bb;
            int   bitsleft = lb->bl;
            byte *inpos    = lb->ip;

            ushort[] hufftbl;

            for (x = 0; x < 20; x++)
            {
                READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref y, 4);
                LENTABLE(pState.PRETREE)[x] = (byte)y;
            }
            BUILD_TABLE(pState.PRETREE);

            for (x = first; x < last;)
            {
                // static public void READ_HUFFSYM(
                READ_HUFFSYM(out hufftbl, ref bitsleft, ref inpos, ref bitbuf, ref i, ref j, pState.PRETREE, out z);
                if (z == 17)
                {
                    READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref y, 4); y += 4;
                    while (y-- > 0)
                    {
                        lens[x++] = 0;
                    }
                }
                else if (z == 18)
                {
                    READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref y, 5); y += 20;
                    while (y-- > 0)
                    {
                        lens[x++] = 0;
                    }
                }
                else if (z == 19)
                {
                    READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref y, 1); y += 4;
                    READ_HUFFSYM(out hufftbl, ref bitsleft, ref inpos, ref bitbuf, ref i, ref j, pState.PRETREE, out z);
                    z = lens[x] - z; if (z < 0)
                    {
                        z += 17;
                    }
                    while (y-- > 0)
                    {
                        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->ip = inpos;
            return(false);
        }
Ejemplo n.º 13
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.º 14
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.º 15
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.º 16
0
 public static void LZXteardown(LZXstate pState)
 {
 }