aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2017-06-20 10:04:16 -0400
committerNick Mathewson <nickm@torproject.org>2017-06-20 10:04:16 -0400
commit1c0459f19a9abf3b3c33ce28923fb567d5c5dfe1 (patch)
treeac6b6fbf0393d96a9622fe39a882da58752c9183
parenteff5e29404980a87b4618e8623c35a363af6cc04 (diff)
parent7d535ea9d3a0b2706392425c13feac760dfccdee (diff)
downloadtor-1c0459f19a9abf3b3c33ce28923fb567d5c5dfe1.tar.gz
tor-1c0459f19a9abf3b3c33ce28923fb567d5c5dfe1.zip
Merge remote-tracking branch 'teor/bug22502' into maint-0.3.1
-rw-r--r--src/common/compress.c28
-rw-r--r--src/common/compress_zstd.c20
-rw-r--r--src/or/directory.c49
3 files changed, 74 insertions, 23 deletions
diff --git a/src/common/compress.c b/src/common/compress.c
index 6513029f9c..e65894d9d2 100644
--- a/src/common/compress.c
+++ b/src/common/compress.c
@@ -102,8 +102,13 @@ tor_compress_impl(int compress,
stream = tor_compress_new(compress, method, compression_level);
- if (stream == NULL)
+ if (stream == NULL) {
+ log_warn(LD_GENERAL, "NULL stream while %scompressing",
+ compress?"":"de");
+ log_debug(LD_GENERAL, "method: %d level: %d at len: %zd",
+ method, compression_level, in_len);
return -1;
+ }
size_t in_len_orig = in_len;
size_t out_remaining, out_alloc;
@@ -128,13 +133,32 @@ tor_compress_impl(int compress,
// inputs.
tor_compress_free(stream);
stream = tor_compress_new(compress, method, compression_level);
+ if (stream == NULL) {
+ log_warn(LD_GENERAL, "NULL stream while %scompressing",
+ compress?"":"de");
+ goto err;
+ }
}
break;
case TOR_COMPRESS_OK:
if (compress || complete_only) {
+ log_fn(protocol_warn_level, LD_PROTOCOL,
+ "Unexpected %s while %scompressing",
+ complete_only?"end of input":"result",
+ compress?"":"de");
+ log_debug(LD_GENERAL, "method: %d level: %d at len: %zd",
+ method, compression_level, in_len);
goto err;
} else {
- goto done;
+ if (in_len != 0) {
+ log_fn(protocol_warn_level, LD_PROTOCOL,
+ "Unexpected extra input while decompressing");
+ log_debug(LD_GENERAL, "method: %d level: %d at len: %zd",
+ method, compression_level, in_len);
+ goto err;
+ } else {
+ goto done;
+ }
}
break;
case TOR_COMPRESS_BUFFER_FULL: {
diff --git a/src/common/compress_zstd.c b/src/common/compress_zstd.c
index 99d05c37bd..a136db48bf 100644
--- a/src/common/compress_zstd.c
+++ b/src/common/compress_zstd.c
@@ -312,6 +312,8 @@ tor_zstd_compress_process(tor_zstd_compress_state_t *state,
return TOR_COMPRESS_ERROR;
}
+ // ZSTD_flushStream returns 0 if the frame is done, or >0 if it
+ // is incomplete.
if (retval > 0)
return TOR_COMPRESS_BUFFER_FULL;
}
@@ -319,7 +321,7 @@ tor_zstd_compress_process(tor_zstd_compress_state_t *state,
if (!finish) {
// We're not done with the input, so no need to flush.
return TOR_COMPRESS_OK;
- } else if (state->compress && finish) {
+ } else if (state->compress) {
retval = ZSTD_endStream(state->u.compress_stream, &output);
*out = (char *)output.dst + output.pos;
@@ -338,10 +340,20 @@ tor_zstd_compress_process(tor_zstd_compress_state_t *state,
return TOR_COMPRESS_BUFFER_FULL;
return TOR_COMPRESS_DONE;
- } else {
- // ZSTD_flushStream returns 0 if the frame is done, or >0 if it
+ } else /* if (!state->compress) */ {
+ // ZSTD_decompressStream returns 0 if the frame is done, or >0 if it
// is incomplete.
- return (retval == 0) ? TOR_COMPRESS_DONE : TOR_COMPRESS_OK;
+ // We check this above.
+ tor_assert_nonfatal(!ZSTD_isError(retval));
+ // Start a new frame if this frame is done
+ if (retval == 0)
+ return TOR_COMPRESS_DONE;
+ // Don't check out_len, it might have some space left if the next output
+ // chunk is larger than the remaining space
+ else if (*in_len > 0)
+ return TOR_COMPRESS_BUFFER_FULL;
+ else
+ return TOR_COMPRESS_OK;
}
#else // HAVE_ZSTD.
diff --git a/src/or/directory.c b/src/or/directory.c
index acd694ffee..ecd98119fe 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -2327,30 +2327,40 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
plausible = body_is_plausible(body, body_len, conn->base_.purpose);
if (compression != NO_METHOD || !plausible) {
+ int severity = LOG_DEBUG;
char *new_body = NULL;
size_t new_len = 0;
+ const char *description1, *description2;
+ int want_to_try_both = 0;
+ int tried_both = 0;
compress_method_t guessed = detect_compression_method(body, body_len);
- if (compression == UNKNOWN_METHOD || guessed != compression) {
- /* Tell the user if we don't believe what we're told about compression.*/
- const char *description1, *description2;
- description1 = compression_method_get_human_name(compression);
+ description1 = compression_method_get_human_name(compression);
- if (BUG(description1 == NULL))
- description1 = compression_method_get_human_name(UNKNOWN_METHOD);
+ if (BUG(description1 == NULL))
+ description1 = compression_method_get_human_name(UNKNOWN_METHOD);
- if (guessed == UNKNOWN_METHOD && !plausible)
- description2 = "confusing binary junk";
- else
- description2 = compression_method_get_human_name(guessed);
+ if (guessed == UNKNOWN_METHOD && !plausible)
+ description2 = "confusing binary junk";
+ else
+ description2 = compression_method_get_human_name(guessed);
- log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled as %s, "
- "but it seems to be %s.%s",
- conn->base_.address, conn->base_.port, description1,
- description2,
- (compression>0 && guessed>0)?" Trying both.":"");
+ /* Tell the user if we don't believe what we're told about compression.*/
+ want_to_try_both = (compression == UNKNOWN_METHOD ||
+ guessed != compression);
+ if (want_to_try_both) {
+ severity = LOG_INFO;
}
+ tor_log(severity, LD_HTTP,
+ "HTTP body from server '%s:%d' was labeled as %s, "
+ "%s it seems to be %s.%s",
+ conn->base_.address, conn->base_.port, description1,
+ guessed != compression?"but":"and",
+ description2,
+ (compression>0 && guessed>0 && want_to_try_both)?
+ " Trying both.":"");
+
/* Try declared compression first if we can.
* tor_compress_supports_method() also returns true for NO_METHOD.
* Ensure that the server is not sending us data compressed using a
@@ -2376,14 +2386,19 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
}
if (!new_body && tor_compress_supports_method(guessed) &&
- compression != guessed)
+ compression != guessed) {
tor_uncompress(&new_body, &new_len, body, body_len, guessed,
!allow_partial, LOG_PROTOCOL_WARN);
+ tried_both = 1;
+ }
/* If we're pretty sure that we have a compressed directory, and
* we didn't manage to uncompress it, then warn and bail. */
if (!plausible && !new_body) {
log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
- "Unable to decompress HTTP body (server '%s:%d').",
+ "Unable to decompress HTTP body (tried %s%s%s, server '%s:%d').",
+ description1,
+ tried_both?" and ":"",
+ tried_both?description2:"",
conn->base_.address, conn->base_.port);
rv = -1;
goto done;