/* 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); }
/* 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; }
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; }
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; }
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; } }
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); }
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); }