Merge branch 'bug22502_redux_031' into maint-0.3.1

This commit is contained in:
Nick Mathewson 2017-06-20 20:27:48 -04:00
commit e51e7bd38b
4 changed files with 91 additions and 9 deletions

4
changes/bug22669 Normal file
View file

@ -0,0 +1,4 @@
o Minor bugfixes (compression):
- When serving directory votes compressed with zlib,
do not claim to have compressed them with zstd. Fixes bug 22669;
bugfix on 0.3.1.1-alpha.

View file

@ -150,13 +150,7 @@ tor_compress_impl(int compress,
method, compression_level, (unsigned long)in_len); method, compression_level, (unsigned long)in_len);
goto err; goto err;
} else { } else {
if (in_len != 0) { 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: %lu",
method, compression_level, (unsigned long)in_len);
goto err;
} else {
goto done; goto done;
} }
} }

View file

@ -4190,13 +4190,14 @@ static int
handle_get_status_vote(dir_connection_t *conn, const get_handler_args_t *args) handle_get_status_vote(dir_connection_t *conn, const get_handler_args_t *args)
{ {
const char *url = args->url; const char *url = args->url;
const compress_method_t compress_method =
find_best_compression_method(args->compression_supported, 1);
{ {
int current; int current;
ssize_t body_len = 0; ssize_t body_len = 0;
ssize_t estimated_len = 0; ssize_t estimated_len = 0;
/* This smartlist holds strings that we can compress on the fly. */
smartlist_t *items = smartlist_new(); smartlist_t *items = smartlist_new();
/* This smartlist holds cached_dir_t objects that have a precompressed
* deflated version. */
smartlist_t *dir_items = smartlist_new(); smartlist_t *dir_items = smartlist_new();
int lifetime = 60; /* XXXX?? should actually use vote intervals. */ int lifetime = 60; /* XXXX?? should actually use vote intervals. */
url += strlen("/tor/status-vote/"); url += strlen("/tor/status-vote/");
@ -4247,6 +4248,26 @@ handle_get_status_vote(dir_connection_t *conn, const get_handler_args_t *args)
write_http_status_line(conn, 404, "Not found"); write_http_status_line(conn, 404, "Not found");
goto vote_done; goto vote_done;
} }
/* We're sending items from at most one kind of source */
tor_assert_nonfatal(smartlist_len(items) == 0 ||
smartlist_len(dir_items) == 0);
int streaming;
unsigned mask;
if (smartlist_len(items)) {
/* We're taking strings and compressing them on the fly. */
streaming = 1;
mask = ~0u;
} else {
/* We're taking cached_dir_t objects. We only have them uncompressed
* or deflated. */
streaming = 0;
mask = (1u<<NO_METHOD) | (1u<<ZLIB_METHOD);
}
const compress_method_t compress_method = find_best_compression_method(
args->compression_supported&mask, streaming);
SMARTLIST_FOREACH(dir_items, cached_dir_t *, d, SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
body_len += compress_method != NO_METHOD ? body_len += compress_method != NO_METHOD ?
d->dir_compressed_len : d->dir_len); d->dir_compressed_len : d->dir_len);

View file

@ -2398,6 +2398,59 @@ test_util_compress(void *arg)
; ;
} }
static void
test_util_decompress_concatenated_impl(compress_method_t method)
{
char input[4096];
char *c1 = NULL, *c2 = NULL, *c3 = NULL;
char *result = NULL;
size_t sz1, sz2, sz3, szr;
int r;
crypto_rand(input, sizeof(input));
/* Compress the input in two chunks. */
r = tor_compress(&c1, &sz1, input, 2048, method);
tt_int_op(r, OP_EQ, 0);
r = tor_compress(&c2, &sz2, input+2048, 2048, method);
tt_int_op(r, OP_EQ, 0);
/* concatenate the chunks. */
sz3 = sz1 + sz2;
c3 = tor_malloc(sz3);
memcpy(c3, c1, sz1);
memcpy(c3+sz1, c2, sz2);
/* decompress the concatenated result */
r = tor_uncompress(&result, &szr, c3, sz3, method, 0, LOG_WARN);
tt_int_op(r, OP_EQ, 0);
tt_int_op(szr, OP_EQ, sizeof(input));
tt_mem_op(result, OP_EQ, input, sizeof(input));
done:
tor_free(c1);
tor_free(c2);
tor_free(c3);
tor_free(result);
}
static void
test_util_decompress_concatenated(void *arg)
{
const char *methodname = arg;
tt_assert(methodname);
compress_method_t method = compression_method_get_by_name(methodname);
tt_int_op(method, OP_NE, UNKNOWN_METHOD);
if (! tor_compress_supports_method(method)) {
tt_skip();
}
test_util_decompress_concatenated_impl(method);
done:
;
}
static void static void
test_util_gzip_compression_bomb(void *arg) test_util_gzip_compression_bomb(void *arg)
{ {
@ -5819,6 +5872,11 @@ test_util_get_unquoted_path(void *arg)
{ "compress/" #name, test_util_compress, 0, &passthrough_setup, \ { "compress/" #name, test_util_compress, 0, &passthrough_setup, \
(char*)(identifier) } (char*)(identifier) }
#define COMPRESS_CONCAT(name, identifier) \
{ "compress_concat/" #name, test_util_decompress_concatenated, 0, \
&passthrough_setup, \
(char*)(identifier) }
#ifdef _WIN32 #ifdef _WIN32
#define UTIL_TEST_NO_WIN(n, f) { #n, NULL, TT_SKIP, NULL, NULL } #define UTIL_TEST_NO_WIN(n, f) { #n, NULL, TT_SKIP, NULL, NULL }
#define UTIL_TEST_WIN_ONLY(n, f) UTIL_TEST(n, (f)) #define UTIL_TEST_WIN_ONLY(n, f) UTIL_TEST(n, (f))
@ -5848,6 +5906,11 @@ struct testcase_t util_tests[] = {
COMPRESS(lzma, "x-tor-lzma"), COMPRESS(lzma, "x-tor-lzma"),
COMPRESS(zstd, "x-zstd"), COMPRESS(zstd, "x-zstd"),
COMPRESS(none, "identity"), COMPRESS(none, "identity"),
COMPRESS_CONCAT(zlib, "deflate"),
COMPRESS_CONCAT(gzip, "gzip"),
COMPRESS_CONCAT(lzma, "x-tor-lzma"),
COMPRESS_CONCAT(zstd, "x-zstd"),
COMPRESS_CONCAT(none, "identity"),
UTIL_TEST(gzip_compression_bomb, TT_FORK), UTIL_TEST(gzip_compression_bomb, TT_FORK),
UTIL_LEGACY(datadir), UTIL_LEGACY(datadir),
UTIL_LEGACY(memarea), UTIL_LEGACY(memarea),