/* The main LZX decompressor structure.
*
* Note: we keep track of most of the decompression state outside this
- * structure. This structure only exists so that (1) we can store
- * @max_window_size and @num_main_syms for multiple calls to lzx_decompress();
- * and (2) so that we don't have to allocate the large 'struct lzx_tables' on
- * the stack. */
+ * structure. This structure only exists so that (1) we can store @window_order
+ * and @num_main_syms for multiple calls to lzx_decompress(); and (2) so that we
+ * don't have to allocate the large 'struct lzx_tables' on the stack. */
struct lzx_decompressor {
- u32 max_window_size;
+ unsigned window_order;
unsigned num_main_syms;
struct lzx_tables tables;
};
static int
lzx_read_block_header(struct input_bitstream *istream,
unsigned num_main_syms,
- u32 max_window_size,
+ unsigned window_order,
int *block_type_ret,
u32 *block_size_ret,
struct lzx_tables *tables,
block_size <<= 8;
block_size |= tmp;
- if (max_window_size >= 65536) {
+ if (window_order >= 16) {
tmp = bitstream_read_bits(istream, 8);
block_size <<= 8;
block_size |= tmp;
* *already* aligned, the correct thing to do is to throw away
* the next 16 bits. */
- if (istream->bitsleft == 0) {
- if (istream->data_bytes_left < 14)
- return -1;
- istream->data += 2;
- istream->data_bytes_left -= 2;
- } else {
- if (istream->data_bytes_left < 12)
- return -1;
- istream->bitsleft = 0;
- istream->bitbuf = 0;
- }
- queue->R[0] = le32_to_cpu(*(le32*)(istream->data + 0));
- queue->R[1] = le32_to_cpu(*(le32*)(istream->data + 4));
- queue->R[2] = le32_to_cpu(*(le32*)(istream->data + 8));
- istream->data += 12;
- istream->data_bytes_left -= 12;
+ bitstream_ensure_bits(istream, 1);
+ bitstream_align(istream);
+ queue->R[0] = bitstream_read_u32(istream);
+ queue->R[1] = bitstream_read_u32(istream);
+ queue->R[2] = bitstream_read_u32(istream);
+
+ /* Offsets of 0 are invalid. */
+ if (queue->R[0] == 0 || queue->R[1] == 0 || queue->R[2] == 0)
+ return -1;
break;
default:
bool may_have_e8_byte;
int ret;
- if (uncompressed_size > dec->max_window_size)
- return -1;
-
init_input_bitstream(&istream, compressed_data, compressed_size);
/* Initialize the recent offsets queue. */
window_pos += block_size)
{
ret = lzx_read_block_header(&istream, dec->num_main_syms,
- dec->max_window_size, &block_type,
+ dec->window_order, &block_type,
&block_size, &dec->tables, &queue);
if (ret)
return ret;
} else {
/* Uncompressed block. */
+ const u8 *p;
- if (istream.data_bytes_left < block_size)
+ p = bitstream_read_bytes(&istream, block_size);
+ if (!p)
return -1;
- memcpy(&((u8*)uncompressed_data)[window_pos], istream.data,
- block_size);
- istream.data += block_size;
- istream.data_bytes_left -= block_size;
+ memcpy(&((u8*)uncompressed_data)[window_pos], p, block_size);
/* Re-align the bitstream if an odd number of bytes was
* read. */
- if (istream.data_bytes_left && (block_size & 1)) {
- istream.data_bytes_left--;
- istream.data++;
- }
+ if (block_size & 1)
+ bitstream_read_byte(&istream);
+
may_have_e8_byte = true;
}
}
}
static int
-lzx_create_decompressor(size_t max_window_size, void **dec_ret)
+lzx_create_decompressor(size_t max_block_size, void **dec_ret)
{
struct lzx_decompressor *dec;
+ unsigned window_order;
- if (!lzx_window_size_valid(max_window_size))
+ window_order = lzx_get_window_order(max_block_size);
+ if (window_order == 0)
return WIMLIB_ERR_INVALID_PARAM;
/* The aligned allocation is needed to ensure that the lzx_tables are
if (!dec)
return WIMLIB_ERR_NOMEM;
- dec->max_window_size = max_window_size;
- dec->num_main_syms = lzx_get_num_main_syms(max_window_size);
+ dec->window_order = window_order;
+ dec->num_main_syms = lzx_get_num_main_syms(window_order);
*dec_ret = dec;
return 0;