X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;ds=inline;f=src%2Fxpress-compress.c;h=005a0a22452692d47372907255838ed61d8aa81d;hb=45d7e8a4f1740974e1dacd221676f9ec38c6b272;hp=5a314b69356a949c620f4c47e05e01d5f3d64b76;hpb=4757f17833c96b8c83a7e17cbc6f374c449d60db;p=wimlib diff --git a/src/xpress-compress.c b/src/xpress-compress.c index 5a314b69..005a0a22 100644 --- a/src/xpress-compress.c +++ b/src/xpress-compress.c @@ -36,6 +36,10 @@ #include "wimlib/util.h" #include "wimlib/xpress.h" +#ifdef HAVE_ALLOCA_H +# include +#endif +#include #include /* Intermediate XPRESS match/literal representation. */ @@ -95,7 +99,7 @@ xpress_write_matches_and_literals(struct output_bitstream *ostream, } struct xpress_record_ctx { - freq_t freqs[XPRESS_NUM_SYMBOLS]; + input_idx_t freqs[XPRESS_NUM_SYMBOLS]; struct xpress_match *matches; }; @@ -132,6 +136,7 @@ xpress_record_match(unsigned len, unsigned offset, void *_ctx) static const struct lz_params xpress_lz_params = { .min_match = XPRESS_MIN_MATCH_LEN, .max_match = XPRESS_MAX_MATCH_LEN, + .max_offset = XPRESS_MAX_OFFSET, .good_match = 16, .nice_match = 32, .max_chain_len = 16, @@ -149,8 +154,11 @@ wimlib_xpress_compress(const void * restrict uncompressed_data, struct output_bitstream ostream; struct xpress_record_ctx record_ctx; - struct xpress_match matches[uncompressed_len]; - u8 udata[uncompressed_len + 8]; + + struct xpress_match *matches; + input_idx_t *prev_tab; + u8 *udata; + u16 codewords[XPRESS_NUM_SYMBOLS]; u8 lens[XPRESS_NUM_SYMBOLS]; input_idx_t num_matches; @@ -169,6 +177,21 @@ wimlib_xpress_compress(const void * restrict uncompressed_data, if (uncompressed_len < XPRESS_NUM_SYMBOLS / 2 + 1 + 4) return 0; + if (uncompressed_len <= STACK_MAX) { + matches = alloca(uncompressed_len * sizeof(matches[0])); + udata = alloca(uncompressed_len + 8); + prev_tab = alloca(uncompressed_len * sizeof(prev_tab[0])); + } else { + matches = MALLOC(uncompressed_len * sizeof(matches[0])); + udata = MALLOC(uncompressed_len + 8); + prev_tab = MALLOC(uncompressed_len * sizeof(prev_tab[0])); + if (matches == NULL || udata == NULL || prev_tab == NULL) { + WARNING("Failed to allocate memory for compression..."); + compressed_len = 0; + goto out_free; + } + } + /* Copy the data to a temporary buffer, but only to avoid * inconsequential accesses of uninitialized memory in * lz_analyze_block(). */ @@ -183,7 +206,8 @@ wimlib_xpress_compress(const void * restrict uncompressed_data, xpress_record_match, xpress_record_literal, &record_ctx, - &xpress_lz_params); + &xpress_lz_params, + prev_tab); num_matches = (record_ctx.matches - matches); @@ -206,11 +230,13 @@ wimlib_xpress_compress(const void * restrict uncompressed_data, /* Flush any pending data and get the length of the compressed data. */ compressed_len = flush_output_bitstream(&ostream); - if (compressed_len == ~(input_idx_t)0) - return 0; + if (compressed_len == ~(input_idx_t)0) { + compressed_len = 0; + goto out_free; + } compressed_len += XPRESS_NUM_SYMBOLS / 2; -#if defined(ENABLE_XPRESS_DEBUG) || defined(ENABLE_VERIFY_COMPRESSION) || 1 +#if defined(ENABLE_XPRESS_DEBUG) || defined(ENABLE_VERIFY_COMPRESSION) /* Verify that we really get the same thing back when decompressing. */ if (wimlib_xpress_decompress(compressed_data, compressed_len, udata, uncompressed_len)) @@ -218,15 +244,24 @@ wimlib_xpress_compress(const void * restrict uncompressed_data, ERROR("Failed to decompress data we " "compressed using XPRESS algorithm"); wimlib_assert(0); - return 0; + compressed_len = 0; + goto out_free; } if (memcmp(uncompressed_data, udata, uncompressed_len)) { ERROR("Data we compressed using XPRESS algorithm " "didn't decompress to original"); wimlib_assert(0); - return 0; + compressed_len = 0; + goto out_free; } #endif + +out_free: + if (uncompressed_len > STACK_MAX) { + FREE(matches); + FREE(udata); + FREE(prev_tab); + } return compressed_len; }