diff options
author | Nick Mathewson <nickm@torproject.org> | 2017-04-25 10:51:13 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2017-04-25 10:51:13 -0400 |
commit | 49868340f7346a7c30603b21d580a3bb54701b0a (patch) | |
tree | bca2aa3284e21557338b86db4bb550b2104f0292 /src/common/compress_lzma.c | |
parent | 232c9e14a8319040c59fd9da1b5d242a57d10a04 (diff) | |
parent | 49a5b50b31b8305e63dea5db0cc0de1cb093ff4f (diff) | |
download | tor-49868340f7346a7c30603b21d580a3bb54701b0a.tar.gz tor-49868340f7346a7c30603b21d580a3bb54701b0a.zip |
Merge branch 'unified_compress_squashed'
Diffstat (limited to 'src/common/compress_lzma.c')
-rw-r--r-- | src/common/compress_lzma.c | 291 |
1 files changed, 1 insertions, 290 deletions
diff --git a/src/common/compress_lzma.c b/src/common/compress_lzma.c index b0ba4b6ba8..906a4067bd 100644 --- a/src/common/compress_lzma.c +++ b/src/common/compress_lzma.c @@ -32,6 +32,7 @@ memory_level(compression_level_t level) { switch (level) { default: + case BEST_COMPRESSION: case HIGH_COMPRESSION: return 9; case MEDIUM_COMPRESSION: return 6; case LOW_COMPRESSION: return 3; @@ -108,296 +109,6 @@ tor_lzma_get_header_version_str(void) #endif } -/** Given <b>in_len</b> bytes at <b>in</b>, compress them into a newly - * allocated buffer, using the LZMA method. Store the compressed string in - * *<b>out</b>, and its length in *<b>out_len</b>. Return 0 on success, -1 on - * failure. - */ -int -tor_lzma_compress(char **out, size_t *out_len, - const char *in, size_t in_len, - compress_method_t method) -{ -#ifdef HAVE_LZMA - lzma_stream stream = LZMA_STREAM_INIT; - lzma_options_lzma stream_options; - lzma_ret retval; - lzma_action action; - size_t out_size, old_size; - off_t offset; - - tor_assert(out); - tor_assert(out_len); - tor_assert(in); - tor_assert(in_len < UINT_MAX); - tor_assert(method == LZMA_METHOD); - - stream.next_in = (unsigned char *)in; - stream.avail_in = in_len; - - lzma_lzma_preset(&stream_options, - memory_level(HIGH_COMPRESSION)); - - retval = lzma_alone_encoder(&stream, &stream_options); - - if (retval != LZMA_OK) { - log_warn(LD_GENERAL, "Error from LZMA encoder: %s (%u).", - lzma_error_str(retval), retval); - goto err; - } - - out_size = in_len / 2; - if (out_size < 1024) - out_size = 1024; - - *out = tor_malloc(out_size); - - stream.next_out = (unsigned char *)*out; - stream.avail_out = out_size; - - action = LZMA_RUN; - - while (1) { - retval = lzma_code(&stream, action); - switch (retval) { - case LZMA_OK: - action = LZMA_FINISH; - break; - case LZMA_STREAM_END: - goto done; - case LZMA_BUF_ERROR: - offset = stream.next_out - ((unsigned char *)*out); - old_size = out_size; - out_size *= 2; - - if (out_size < old_size) { - log_warn(LD_GENERAL, "Size overflow in LZMA compression."); - goto err; - } - - *out = tor_realloc(*out, out_size); - stream.next_out = (unsigned char *)(*out + offset); - if (out_size - offset > UINT_MAX) { - log_warn(LD_BUG, "Ran over unsigned int limit of LZMA while " - "compressing."); - goto err; - } - stream.avail_out = (unsigned int)(out_size - offset); - break; - - // We list all the possible values of `lzma_ret` here to silence the - // `switch-enum` warning and to detect if a new member was added. - case LZMA_NO_CHECK: - case LZMA_UNSUPPORTED_CHECK: - case LZMA_GET_CHECK: - case LZMA_MEM_ERROR: - case LZMA_MEMLIMIT_ERROR: - case LZMA_FORMAT_ERROR: - case LZMA_OPTIONS_ERROR: - case LZMA_DATA_ERROR: - case LZMA_PROG_ERROR: - default: - log_warn(LD_GENERAL, "LZMA compression didn't finish: %s.", - lzma_error_str(retval)); - goto err; - } - } - - done: - *out_len = stream.total_out; - lzma_end(&stream); - - if (tor_compress_is_compression_bomb(*out_len, in_len)) { - log_warn(LD_BUG, "We compressed something and got an insanely high " - "compression factor; other Tor instances would think " - "this is a compression bomb."); - goto err; - } - - return 0; - - err: - lzma_end(&stream); - tor_free(*out); - return -1; -#else // HAVE_LZMA. - (void)out; - (void)out_len; - (void)in; - (void)in_len; - (void)method; - - return -1; -#endif // HAVE_LZMA. -} - -/** Given an LZMA compressed string of total length <b>in_len</b> bytes at - * <b>in</b>, uncompress them into a newly allocated buffer. Store the - * uncompressed string in *<b>out</b>, and its length in *<b>out_len</b>. - * Return 0 on success, -1 on failure. - * - * If <b>complete_only</b> is true, we consider a truncated input as a failure; - * otherwise we decompress as much as we can. Warn about truncated or corrupt - * inputs at <b>protocol_warn_level</b>. - */ -int -tor_lzma_uncompress(char **out, size_t *out_len, - const char *in, size_t in_len, - compress_method_t method, - int complete_only, - int protocol_warn_level) -{ -#ifdef HAVE_LZMA - lzma_stream stream = LZMA_STREAM_INIT; - lzma_ret retval; - lzma_action action; - size_t out_size, old_size; - off_t offset; - - tor_assert(out); - tor_assert(out_len); - tor_assert(in); - tor_assert(in_len < UINT_MAX); - tor_assert(method == LZMA_METHOD); - - stream.next_in = (unsigned char *)in; - stream.avail_in = in_len; - - // FIXME(ahf): This should be something more sensible than - // UINT64_MAX: See #21665. - retval = lzma_alone_decoder(&stream, UINT64_MAX); - - if (retval != LZMA_OK) { - log_warn(LD_GENERAL, "Error from LZMA decoder: %s (%u).", - lzma_error_str(retval), retval); - goto err; - } - - out_size = in_len * 2; - if (out_size < 1024) - out_size = 1024; - - if (out_size >= SIZE_T_CEILING || out_size > UINT_MAX) - goto err; - - *out = tor_malloc(out_size); - stream.next_out = (unsigned char *)*out; - stream.avail_out = out_size; - - // FIXME(ahf): We should figure out how to use LZMA_FULL_FLUSH to - // make the partial string read tests. - // action = complete_only ? LZMA_FINISH : LZMA_SYNC_FLUSH. // To do this, - // it seems like we have to use LZMA using their "xz" encoder instead of just - // regular LZMA. - (void)complete_only; - action = LZMA_FINISH; - - while (1) { - retval = lzma_code(&stream, action); - switch (retval) { - case LZMA_STREAM_END: - if (stream.avail_in == 0) - goto done; - - // We might have more data here. Reset our stream. - lzma_end(&stream); - - retval = lzma_alone_decoder(&stream, UINT64_MAX); - - if (retval != LZMA_OK) { - log_warn(LD_GENERAL, "Error from LZMA decoder: %s (%u).", - lzma_error_str(retval), retval); - goto err; - } - break; - case LZMA_OK: - break; - case LZMA_BUF_ERROR: - if (stream.avail_out > 0) { - log_fn(protocol_warn_level, LD_PROTOCOL, - "possible truncated or corrupt LZMA data."); - goto err; - } - - offset = stream.next_out - (unsigned char *)*out; - old_size = out_size; - out_size *= 2; - - if (out_size < old_size) { - log_warn(LD_GENERAL, "Size overflow in LZMA uncompression."); - goto err; - } - - if (tor_compress_is_compression_bomb(in_len, out_size)) { - log_warn(LD_GENERAL, "Input looks like a possible LZMA compression " - "bomb. Not proceeding."); - goto err; - } - - if (out_size >= SIZE_T_CEILING) { - log_warn(LD_BUG, "Hit SIZE_T_CEILING limit while uncompressing " - "LZMA data."); - goto err; - } - - *out = tor_realloc(*out, out_size); - stream.next_out = (unsigned char *)(*out + offset); - - if (out_size - offset > UINT_MAX) { - log_warn(LD_BUG, "Ran over unsigned int limit of LZMA while " - "uncompressing."); - goto err; - } - - stream.avail_out = (unsigned int)(out_size - offset); - break; - - // We list all the possible values of `lzma_ret` here to silence the - // `switch-enum` warning and to detect if a new member was added. - case LZMA_NO_CHECK: - case LZMA_UNSUPPORTED_CHECK: - case LZMA_GET_CHECK: - case LZMA_MEM_ERROR: - case LZMA_MEMLIMIT_ERROR: - case LZMA_FORMAT_ERROR: - case LZMA_OPTIONS_ERROR: - case LZMA_DATA_ERROR: - case LZMA_PROG_ERROR: - default: - log_warn(LD_GENERAL, "LZMA decompression didn't finish: %s.", - lzma_error_str(retval)); - goto err; - } - } - - done: - *out_len = stream.next_out - (unsigned char*)*out; - lzma_end(&stream); - - // NUL-terminate our output. - if (out_size == *out_len) - *out = tor_realloc(*out, out_size + 1); - (*out)[*out_len] = '\0'; - - return 0; - - err: - lzma_end(&stream); - tor_free(*out); - return -1; -#else // HAVE_LZMA. - (void)out; - (void)out_len; - (void)in; - (void)in_len; - (void)method; - (void)complete_only; - (void)protocol_warn_level; - - return -1; -#endif // HAVE_LZMA. -} - /** Internal LZMA state for incremental compression/decompression. * The body of this struct is not exposed. */ struct tor_lzma_compress_state_t { |