diff options
author | Nick Mathewson <nickm@torproject.org> | 2017-04-25 09:41:23 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2017-04-25 10:50:50 -0400 |
commit | 880fb3e3a9aba21c0b36aa4aa5659432e90eb827 (patch) | |
tree | b742f5773bf54cbf34db66aae503953772e74761 /src/common/compress_zstd.c | |
parent | 91dd4a00f7d4891e24187a849933547128aeeb9f (diff) | |
download | tor-880fb3e3a9aba21c0b36aa4aa5659432e90eb827.tar.gz tor-880fb3e3a9aba21c0b36aa4aa5659432e90eb827.zip |
Combine all *compress/*uncompress backend function into one
Since we have a streaming API for each compression backend, we don't
need a non-streaming API for each: we can build a common
non-streaming API at the front-end.
Diffstat (limited to 'src/common/compress_zstd.c')
-rw-r--r-- | src/common/compress_zstd.c | 283 |
1 files changed, 0 insertions, 283 deletions
diff --git a/src/common/compress_zstd.c b/src/common/compress_zstd.c index 664cce1700..76f2991e3d 100644 --- a/src/common/compress_zstd.c +++ b/src/common/compress_zstd.c @@ -85,289 +85,6 @@ tor_zstd_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 Zstandard 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_zstd_compress(char **out, size_t *out_len, - const char *in, size_t in_len, - compress_method_t method) -{ -#ifdef HAVE_ZSTD - ZSTD_CStream *stream = NULL; - size_t out_size, old_size; - size_t retval; - - tor_assert(out); - tor_assert(out_len); - tor_assert(in); - tor_assert(in_len < UINT_MAX); - tor_assert(method == ZSTD_METHOD); - - *out = NULL; - - stream = ZSTD_createCStream(); - - if (stream == NULL) { - // Zstandard does not give us any useful error message to why this - // happened. See https://github.com/facebook/zstd/issues/398 - log_warn(LD_GENERAL, "Error while creating Zstandard stream"); - goto err; - } - - retval = ZSTD_initCStream(stream, - memory_level(HIGH_COMPRESSION)); - - if (ZSTD_isError(retval)) { - log_warn(LD_GENERAL, "Zstandard stream initialization error: %s", - ZSTD_getErrorName(retval)); - goto err; - } - - // Assume 50% compression and update our buffer in case we need to. - out_size = in_len / 2; - if (out_size < 1024) - out_size = 1024; - - *out = tor_malloc(out_size); - *out_len = 0; - - ZSTD_inBuffer input = { in, in_len, 0 }; - ZSTD_outBuffer output = { *out, out_size, 0 }; - - while (input.pos < input.size) { - retval = ZSTD_compressStream(stream, &output, &input); - - if (ZSTD_isError(retval)) { - log_warn(LD_GENERAL, "Zstandard stream compression error: %s", - ZSTD_getErrorName(retval)); - goto err; - } - - if (input.pos < input.size && output.pos == output.size) { - old_size = out_size; - out_size *= 2; - - if (out_size < old_size) { - log_warn(LD_GENERAL, "Size overflow in Zstandard compression."); - goto err; - } - - if (out_size - output.pos > UINT_MAX) { - log_warn(LD_BUG, "Ran over unsigned int limit of Zstandard while " - "compressing."); - goto err; - } - - output.dst = *out = tor_realloc(*out, out_size); - output.size = out_size; - } - } - - while (1) { - retval = ZSTD_endStream(stream, &output); - - if (retval == 0) - break; - - if (ZSTD_isError(retval)) { - log_warn(LD_GENERAL, "Zstandard stream error: %s", - ZSTD_getErrorName(retval)); - goto err; - } - - if (output.pos == output.size) { - old_size = out_size; - out_size *= 2; - - if (out_size < old_size) { - log_warn(LD_GENERAL, "Size overflow in Zstandard compression."); - goto err; - } - - if (out_size - output.pos > UINT_MAX) { - log_warn(LD_BUG, "Ran over unsigned int limit of Zstandard while " - "compressing."); - goto err; - } - - output.dst = *out = tor_realloc(*out, out_size); - output.size = out_size; - } - } - - *out_len = output.pos; - - 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; - } - - if (stream != NULL) { - ZSTD_freeCStream(stream); - } - - return 0; - - err: - if (stream != NULL) { - ZSTD_freeCStream(stream); - } - - tor_free(*out); - return -1; -#else // HAVE_ZSTD. - (void)out; - (void)out_len; - (void)in; - (void)in_len; - (void)method; - - return -1; -#endif // HAVE_ZSTD. -} - -/** Given a Zstandard 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_zstd_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_ZSTD - ZSTD_DStream *stream = NULL; - size_t retval; - size_t out_size, old_size; - - tor_assert(out); - tor_assert(out_len); - tor_assert(in); - tor_assert(in_len < UINT_MAX); - tor_assert(method == ZSTD_METHOD); - - // FIXME(ahf): Handle this? - (void)complete_only; - (void)protocol_warn_level; - - *out = NULL; - - stream = ZSTD_createDStream(); - - if (stream == NULL) { - // Zstandard does not give us any useful error message to why this - // happened. See https://github.com/facebook/zstd/issues/398 - log_warn(LD_GENERAL, "Error while creating Zstandard stream"); - goto err; - } - - retval = ZSTD_initDStream(stream); - - if (ZSTD_isError(retval)) { - log_warn(LD_GENERAL, "Zstandard stream initialization error: %s", - ZSTD_getErrorName(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); - *out_len = 0; - - ZSTD_inBuffer input = { in, in_len, 0 }; - ZSTD_outBuffer output = { *out, out_size, 0 }; - - while (input.pos < input.size) { - retval = ZSTD_decompressStream(stream, &output, &input); - - if (ZSTD_isError(retval)) { - log_warn(LD_GENERAL, "Zstandard stream decompression error: %s", - ZSTD_getErrorName(retval)); - goto err; - } - - if (input.pos < input.size && output.pos == output.size) { - old_size = out_size; - out_size *= 2; - - if (out_size < old_size) { - log_warn(LD_GENERAL, "Size overflow in Zstandard compression."); - goto err; - } - - if (tor_compress_is_compression_bomb(in_len, out_size)) { - log_warn(LD_GENERAL, "Input looks like a possible Zstandard " - "compression bomb. Not proceeding."); - goto err; - } - - if (out_size >= SIZE_T_CEILING) { - log_warn(LD_BUG, "Hit SIZE_T_CEILING limit while uncompressing " - "Zstandard data."); - goto err; - } - - if (out_size - output.pos > UINT_MAX) { - log_warn(LD_BUG, "Ran over unsigned int limit of Zstandard while " - "decompressing."); - goto err; - } - - output.dst = *out = tor_realloc(*out, out_size); - output.size = out_size; - } - } - - *out_len = output.pos; - - if (stream != NULL) { - ZSTD_freeDStream(stream); - } - - // NUL-terminate our output. - if (out_size == *out_len) - *out = tor_realloc(*out, out_size + 1); - (*out)[*out_len] = '\0'; - - return 0; - - err: - if (stream != NULL) { - ZSTD_freeDStream(stream); - } - - tor_free(*out); - return -1; -#else // HAVE_ZSTD. - (void)out; - (void)out_len; - (void)in; - (void)in_len; - (void)method; - (void)complete_only; - (void)protocol_warn_level; - - return -1; -#endif // HAVE_ZSTD. -} - /** Internal Zstandard state for incremental compression/decompression. * The body of this struct is not exposed. */ struct tor_zstd_compress_state_t { |