X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fxpress-decompress.c;h=584fa4aa7299966430e40cf308b0a4377f0aaf27;hp=87205543022ed76c041b6a5f9f5714ddeeaf4ee0;hb=e8c3ca2d1d0cac3d64985b45a9f654d2029a7518;hpb=40beb80283a2df7af88c8359ca41adb814585e9a diff --git a/src/xpress-decompress.c b/src/xpress-decompress.c index 87205543..584fa4aa 100644 --- a/src/xpress-decompress.c +++ b/src/xpress-decompress.c @@ -6,7 +6,7 @@ /* * - * Copyright (C) 2012 Eric Biggers + * Copyright (C) 2012, 2013 Eric Biggers * * This file is part of wimlib, a library for working with WIM files. * @@ -71,12 +71,16 @@ * extra symbol is there or not. */ -#include "util.h" -#include "xpress.h" -#include "wimlib.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "wimlib.h" +#include "wimlib/assert.h" #define XPRESS_DECOMP -#include "decompress.h" +#include "wimlib/decompress.h" +#include "wimlib/util.h" +#include "wimlib/xpress.h" /* * Decodes a symbol @huffsym that begins an XPRESS match. @@ -88,10 +92,13 @@ * * Note: taking the low 8 bits of the symbol is the same as subtracting 256, the * number of symbols reserved for literals. + * + * Returns the match length, or -1 on error. */ -static int xpress_decode_match(int huffsym, unsigned window_pos, - unsigned window_len, u8 window[], - struct input_bitstream *istream) +static int +xpress_decode_match(unsigned huffsym, unsigned window_pos, + unsigned window_len, u8 window[], + struct input_bitstream *istream) { unsigned match_len; unsigned match_offset; @@ -105,27 +112,25 @@ static int xpress_decode_match(int huffsym, unsigned window_pos, ret = bitstream_read_bits(istream, offset_bsr, &match_offset); if (ret != 0) - return -1; + return ret; match_offset |= (1 << offset_bsr); if (len_hdr == 0xf) { ret = bitstream_read_byte(istream); - if (ret == -1) - return -1; + if (ret < 0) + return ret; match_len = ret; if (match_len == 0xff) { ret = bitstream_read_byte(istream); - if (ret == -1) - return -1; + if (ret < 0) + return ret; match_len = ret; ret = bitstream_read_byte(istream); - if (ret == -1) - return -1; + if (ret < 0) + return ret; match_len |= (ret << 8); - if (match_len < 0xf) - return -1; } else { match_len += 0xf; } @@ -142,15 +147,15 @@ static int xpress_decode_match(int huffsym, unsigned window_pos, match_src = match_dest - match_offset; if (window_pos + match_len > window_len) { - ERROR("XPRESS decompression error: match of length %d " + ERROR("XPRESS decompression error: match of length %u " "bytes overflows window", match_len); return -1; } if (match_src < window) { - ERROR("XPRESS decompression error: match of length %d bytes " - "references data before window (match_offset = %d, " - "window_pos = %d)", match_len, match_offset, window_pos); + ERROR("XPRESS decompression error: match of length %u bytes " + "references data before window (match_offset = %u, " + "window_pos = %u)", match_len, match_offset, window_pos); return -1; } @@ -162,23 +167,25 @@ static int xpress_decode_match(int huffsym, unsigned window_pos, /* Decodes the Huffman-encoded matches and literal bytes in a block of * XPRESS-encoded data. */ -static int xpress_decompress_literals(struct input_bitstream *istream, - u8 uncompressed_data[], - unsigned uncompressed_len, - const u8 lens[], - const u16 decode_table[]) +static int +xpress_decompress_block(struct input_bitstream *istream, + u8 uncompressed_data[], + unsigned uncompressed_len, + const u8 lens[], + const u16 decode_table[]) { - unsigned curpos = 0; + unsigned curpos; unsigned huffsym; + int ret; int match_len; - int ret = 0; + curpos = 0; while (curpos < uncompressed_len) { ret = read_huffsym(istream, decode_table, lens, XPRESS_NUM_SYMBOLS, XPRESS_TABLEBITS, &huffsym, XPRESS_MAX_CODEWORD_LEN); - if (ret != 0) - break; + if (ret) + return ret; if (huffsym < XPRESS_NUM_CHARS) { uncompressed_data[curpos++] = huffsym; @@ -188,19 +195,19 @@ static int xpress_decompress_literals(struct input_bitstream *istream, uncompressed_len, uncompressed_data, istream); - if (match_len == -1) { - ret = 1; - break; - } + if (match_len < 0) + return match_len; curpos += match_len; } } - return ret; + return 0; } -int xpress_decompress(const void *__compressed_data, unsigned compressed_len, - void *uncompressed_data, unsigned uncompressed_len) +/* Documented in wimlib.h */ +WIMLIBAPI int +wimlib_xpress_decompress(const void *__compressed_data, unsigned compressed_len, + void *uncompressed_data, unsigned uncompressed_len) { u8 lens[XPRESS_NUM_SYMBOLS]; u16 decode_table[(1 << XPRESS_TABLEBITS) + 2 * XPRESS_NUM_SYMBOLS]; @@ -220,8 +227,10 @@ int xpress_decompress(const void *__compressed_data, unsigned compressed_len, * code lengths of these symbols are given literally as 4-bit integers * in the first 256 bytes of the compressed data. */ - if (compressed_len < XPRESS_NUM_SYMBOLS / 2) - return WIMLIB_ERR_DECOMPRESSION; + if (compressed_len < XPRESS_NUM_SYMBOLS / 2) { + ERROR("xpress_decompress(): Compressed length too short!"); + return -1; + } for (i = 0; i < XPRESS_NUM_SYMBOLS / 2; i++) { *lens_p++ = compressed_data[i] & 0xf; @@ -231,13 +240,13 @@ int xpress_decompress(const void *__compressed_data, unsigned compressed_len, ret = make_huffman_decode_table(decode_table, XPRESS_NUM_SYMBOLS, XPRESS_TABLEBITS, lens, XPRESS_MAX_CODEWORD_LEN); - if (ret != 0) + if (ret) return ret; init_input_bitstream(&istream, compressed_data + XPRESS_NUM_SYMBOLS / 2, compressed_len - XPRESS_NUM_SYMBOLS / 2); - return xpress_decompress_literals(&istream, uncompressed_data, - uncompressed_len, lens, - decode_table); + return xpress_decompress_block(&istream, uncompressed_data, + uncompressed_len, lens, + decode_table); }