commit 9328bd524e38befe240fd729a9febb4dfe8b5be4 Author: Nick Mathewson nickm@torproject.org Date: Tue Jun 20 12:26:57 2017 -0400
Enforce the rule that COMPRESS_OK means progress was made.
If COMPRESS_OK occurs but data is neither consumed nor generated, treat it as a BUG and a COMPRESS_ERROR.
This change is meant to prevent infinite loops in the case where we've made a mistake in one of our compression backends.
Closes ticket 22672. --- changes/bug22672 | 5 +++++ src/common/compress.c | 36 +++++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 11 deletions(-)
diff --git a/changes/bug22672 b/changes/bug22672 new file mode 100644 index 0000000..ec66811 --- /dev/null +++ b/changes/bug22672 @@ -0,0 +1,5 @@ + o Minor features (compression, defensive programming): + - Detect and break out of infinite loops in our compression code. + We don't think that any such loops exist now, but it's best to be + safe. Closes ticket 22672. + diff --git a/src/common/compress.c b/src/common/compress.c index c16d1b5..46aa1d5 100644 --- a/src/common/compress.c +++ b/src/common/compress.c @@ -548,28 +548,42 @@ tor_compress_process(tor_compress_state_t *state, int finish) { tor_assert(state != NULL); + const size_t in_len_orig = *in_len; + const size_t out_len_orig = *out_len; + tor_compress_output_t rv;
switch (state->method) { case GZIP_METHOD: case ZLIB_METHOD: - return tor_zlib_compress_process(state->u.zlib_state, - out, out_len, in, in_len, - finish); + rv = tor_zlib_compress_process(state->u.zlib_state, + out, out_len, in, in_len, + finish); + break; case LZMA_METHOD: - return tor_lzma_compress_process(state->u.lzma_state, - out, out_len, in, in_len, - finish); + rv =tor_lzma_compress_process(state->u.lzma_state, + out, out_len, in, in_len, + finish); + break; case ZSTD_METHOD: - return tor_zstd_compress_process(state->u.zstd_state, - out, out_len, in, in_len, - finish); + rv = tor_zstd_compress_process(state->u.zstd_state, + out, out_len, in, in_len, + finish); + break; case NO_METHOD: - return tor_cnone_compress_process(out, out_len, in, in_len, - finish); + rv = tor_cnone_compress_process(out, out_len, in, in_len, + finish); + break; + default: case UNKNOWN_METHOD: goto err; } + if (BUG((rv == TOR_COMPRESS_OK) && + *in_len == in_len_orig && + *out_len == out_len_orig)) { + return TOR_COMPRESS_ERROR; + }
+ return rv; err: return TOR_COMPRESS_ERROR; }
tor-commits@lists.torproject.org