mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-25 23:21:38 +01:00
Merge remote-tracking branch 'ahf/bugs/22085'
This commit is contained in:
commit
36e62ae7e2
6 changed files with 171 additions and 351 deletions
|
@ -18,10 +18,10 @@
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mock_connection_write_to_buf_impl_(const char *string, size_t len,
|
mock_connection_write_to_buf_impl_(const char *string, size_t len,
|
||||||
connection_t *conn, int zlib)
|
connection_t *conn, int compressed)
|
||||||
{
|
{
|
||||||
log_debug(LD_GENERAL, "%sResponse:\n%u\nConnection: %p\n%s\n",
|
log_debug(LD_GENERAL, "%sResponse:\n%u\nConnection: %p\n%s\n",
|
||||||
zlib ? "Compressed " : "", (unsigned)len, conn, string);
|
compressed ? "Compressed " : "", (unsigned)len, conn, string);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -578,7 +578,62 @@ test_buffer_time_tracking(void *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_buffers_zlib_impl(int finalize_with_nil)
|
test_buffers_compress_fin_at_chunk_end_impl(compress_method_t method,
|
||||||
|
compression_level_t level)
|
||||||
|
{
|
||||||
|
char *msg = NULL;
|
||||||
|
char *contents = NULL;
|
||||||
|
char *expanded = NULL;
|
||||||
|
buf_t *buf = NULL;
|
||||||
|
tor_compress_state_t *compress_state = NULL;
|
||||||
|
size_t out_len, in_len;
|
||||||
|
size_t sz, headerjunk;
|
||||||
|
|
||||||
|
buf = buf_new_with_capacity(128); /* will round up */
|
||||||
|
sz = buf_get_default_chunk_size(buf);
|
||||||
|
msg = tor_malloc_zero(sz);
|
||||||
|
|
||||||
|
write_to_buf(msg, 1, buf);
|
||||||
|
tt_assert(buf->head);
|
||||||
|
|
||||||
|
/* Fill up the chunk so the compression stuff won't fit in one chunk. */
|
||||||
|
tt_uint_op(buf->head->memlen, OP_LT, sz);
|
||||||
|
headerjunk = buf->head->memlen - 7;
|
||||||
|
write_to_buf(msg, headerjunk-1, buf);
|
||||||
|
tt_uint_op(buf->head->datalen, OP_EQ, headerjunk);
|
||||||
|
tt_uint_op(buf_datalen(buf), OP_EQ, headerjunk);
|
||||||
|
/* Write an empty string, with finalization on. */
|
||||||
|
compress_state = tor_compress_new(1, method, level);
|
||||||
|
tt_int_op(write_to_buf_compress(buf, compress_state, "", 0, 1), OP_EQ, 0);
|
||||||
|
|
||||||
|
in_len = buf_datalen(buf);
|
||||||
|
contents = tor_malloc(in_len);
|
||||||
|
|
||||||
|
tt_int_op(fetch_from_buf(contents, in_len, buf), OP_EQ, 0);
|
||||||
|
|
||||||
|
tt_uint_op(in_len, OP_GT, headerjunk);
|
||||||
|
|
||||||
|
tt_int_op(0, OP_EQ, tor_uncompress(&expanded, &out_len,
|
||||||
|
contents + headerjunk,
|
||||||
|
in_len - headerjunk,
|
||||||
|
method, 1,
|
||||||
|
LOG_WARN));
|
||||||
|
|
||||||
|
tt_int_op(out_len, OP_EQ, 0);
|
||||||
|
tt_assert(expanded);
|
||||||
|
|
||||||
|
done:
|
||||||
|
buf_free(buf);
|
||||||
|
tor_compress_free(compress_state);
|
||||||
|
tor_free(contents);
|
||||||
|
tor_free(expanded);
|
||||||
|
tor_free(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_buffers_compress_impl(compress_method_t method,
|
||||||
|
compression_level_t level,
|
||||||
|
int finalize_with_nil)
|
||||||
{
|
{
|
||||||
char *msg = NULL;
|
char *msg = NULL;
|
||||||
char *contents = NULL;
|
char *contents = NULL;
|
||||||
|
@ -589,7 +644,7 @@ test_buffers_zlib_impl(int finalize_with_nil)
|
||||||
int done;
|
int done;
|
||||||
|
|
||||||
buf = buf_new_with_capacity(128); /* will round up */
|
buf = buf_new_with_capacity(128); /* will round up */
|
||||||
compress_state = tor_compress_new(1, ZLIB_METHOD, HIGH_COMPRESSION);
|
compress_state = tor_compress_new(1, method, level);
|
||||||
|
|
||||||
msg = tor_malloc(512);
|
msg = tor_malloc(512);
|
||||||
crypto_rand(msg, 512);
|
crypto_rand(msg, 512);
|
||||||
|
@ -613,7 +668,7 @@ test_buffers_zlib_impl(int finalize_with_nil)
|
||||||
|
|
||||||
tt_int_op(0, OP_EQ, tor_uncompress(&expanded, &out_len,
|
tt_int_op(0, OP_EQ, tor_uncompress(&expanded, &out_len,
|
||||||
contents, in_len,
|
contents, in_len,
|
||||||
ZLIB_METHOD, 1,
|
method, 1,
|
||||||
LOG_WARN));
|
LOG_WARN));
|
||||||
|
|
||||||
tt_int_op(out_len, OP_GE, 128);
|
tt_int_op(out_len, OP_GE, 128);
|
||||||
|
@ -632,69 +687,37 @@ test_buffers_zlib_impl(int finalize_with_nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_buffers_zlib(void *arg)
|
test_buffers_compress(void *arg)
|
||||||
{
|
{
|
||||||
(void) arg;
|
(void) arg;
|
||||||
test_buffers_zlib_impl(0);
|
compress_method_t methods[] = {
|
||||||
}
|
GZIP_METHOD,
|
||||||
static void
|
ZLIB_METHOD,
|
||||||
test_buffers_zlib_fin_with_nil(void *arg)
|
LZMA_METHOD,
|
||||||
{
|
ZSTD_METHOD
|
||||||
(void) arg;
|
};
|
||||||
test_buffers_zlib_impl(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
compression_level_t levels[] = {
|
||||||
test_buffers_zlib_fin_at_chunk_end(void *arg)
|
BEST_COMPRESSION,
|
||||||
{
|
HIGH_COMPRESSION,
|
||||||
char *msg = NULL;
|
MEDIUM_COMPRESSION,
|
||||||
char *contents = NULL;
|
LOW_COMPRESSION
|
||||||
char *expanded = NULL;
|
};
|
||||||
buf_t *buf = NULL;
|
|
||||||
tor_compress_state_t *compress_state = NULL;
|
|
||||||
size_t out_len, in_len;
|
|
||||||
size_t sz, headerjunk;
|
|
||||||
(void) arg;
|
|
||||||
|
|
||||||
buf = buf_new_with_capacity(128); /* will round up */
|
for (unsigned m = 0; m < ARRAY_LENGTH(methods); ++m) {
|
||||||
sz = buf_get_default_chunk_size(buf);
|
compress_method_t method = methods[m];
|
||||||
msg = tor_malloc_zero(sz);
|
|
||||||
|
|
||||||
write_to_buf(msg, 1, buf);
|
if (! tor_compress_supports_method(method))
|
||||||
tt_assert(buf->head);
|
continue;
|
||||||
|
|
||||||
/* Fill up the chunk so the zlib stuff won't fit in one chunk. */
|
for (unsigned l = 0; l < ARRAY_LENGTH(levels); ++l) {
|
||||||
tt_uint_op(buf->head->memlen, OP_LT, sz);
|
compression_level_t level = levels[l];
|
||||||
headerjunk = buf->head->memlen - 7;
|
|
||||||
write_to_buf(msg, headerjunk-1, buf);
|
|
||||||
tt_uint_op(buf->head->datalen, OP_EQ, headerjunk);
|
|
||||||
tt_uint_op(buf_datalen(buf), OP_EQ, headerjunk);
|
|
||||||
/* Write an empty string, with finalization on. */
|
|
||||||
compress_state = tor_compress_new(1, ZLIB_METHOD, HIGH_COMPRESSION);
|
|
||||||
tt_int_op(write_to_buf_compress(buf, compress_state, "", 0, 1), OP_EQ, 0);
|
|
||||||
|
|
||||||
in_len = buf_datalen(buf);
|
test_buffers_compress_impl(method, level, 0);
|
||||||
contents = tor_malloc(in_len);
|
test_buffers_compress_impl(method, level, 1);
|
||||||
|
test_buffers_compress_fin_at_chunk_end_impl(method, level);
|
||||||
tt_int_op(fetch_from_buf(contents, in_len, buf), OP_EQ, 0);
|
}
|
||||||
|
}
|
||||||
tt_uint_op(in_len, OP_GT, headerjunk);
|
|
||||||
|
|
||||||
tt_int_op(0, OP_EQ, tor_uncompress(&expanded, &out_len,
|
|
||||||
contents + headerjunk,
|
|
||||||
in_len - headerjunk,
|
|
||||||
ZLIB_METHOD, 1,
|
|
||||||
LOG_WARN));
|
|
||||||
|
|
||||||
tt_int_op(out_len, OP_EQ, 0);
|
|
||||||
tt_assert(expanded);
|
|
||||||
|
|
||||||
done:
|
|
||||||
buf_free(buf);
|
|
||||||
tor_compress_free(compress_state);
|
|
||||||
tor_free(contents);
|
|
||||||
tor_free(expanded);
|
|
||||||
tor_free(msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t *tls_read_ptr;
|
static const uint8_t *tls_read_ptr;
|
||||||
|
@ -821,10 +844,7 @@ struct testcase_t buffer_tests[] = {
|
||||||
{ "allocation_tracking", test_buffer_allocation_tracking, TT_FORK,
|
{ "allocation_tracking", test_buffer_allocation_tracking, TT_FORK,
|
||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
{ "time_tracking", test_buffer_time_tracking, TT_FORK, NULL, NULL },
|
{ "time_tracking", test_buffer_time_tracking, TT_FORK, NULL, NULL },
|
||||||
{ "zlib", test_buffers_zlib, TT_FORK, NULL, NULL },
|
{ "compress", test_buffers_compress, TT_FORK, NULL, NULL },
|
||||||
{ "zlib_fin_with_nil", test_buffers_zlib_fin_with_nil, TT_FORK, NULL, NULL },
|
|
||||||
{ "zlib_fin_at_chunk_end", test_buffers_zlib_fin_at_chunk_end, TT_FORK,
|
|
||||||
NULL, NULL},
|
|
||||||
{ "tls_read_mocked", test_buffers_tls_read_mocked, 0,
|
{ "tls_read_mocked", test_buffers_tls_read_mocked, 0,
|
||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
{ "chunk_size", test_buffers_chunk_size, 0, NULL, NULL },
|
{ "chunk_size", test_buffers_chunk_size, 0, NULL, NULL },
|
||||||
|
|
|
@ -72,9 +72,9 @@ test_ext_or_id_map(void *arg)
|
||||||
* writes to outbuf. */
|
* writes to outbuf. */
|
||||||
static void
|
static void
|
||||||
connection_write_to_buf_impl_replacement(const char *string, size_t len,
|
connection_write_to_buf_impl_replacement(const char *string, size_t len,
|
||||||
connection_t *conn, int zlib)
|
connection_t *conn, int compressed)
|
||||||
{
|
{
|
||||||
(void) zlib;
|
(void) compressed;
|
||||||
|
|
||||||
tor_assert(string);
|
tor_assert(string);
|
||||||
tor_assert(conn);
|
tor_assert(conn);
|
||||||
|
|
|
@ -98,9 +98,9 @@ helper_setup_fake_routerlist(void)
|
||||||
|
|
||||||
void
|
void
|
||||||
connection_write_to_buf_mock(const char *string, size_t len,
|
connection_write_to_buf_mock(const char *string, size_t len,
|
||||||
connection_t *conn, int zlib)
|
connection_t *conn, int compressed)
|
||||||
{
|
{
|
||||||
(void) zlib;
|
(void) compressed;
|
||||||
|
|
||||||
tor_assert(string);
|
tor_assert(string);
|
||||||
tor_assert(conn);
|
tor_assert(conn);
|
||||||
|
|
|
@ -15,7 +15,7 @@ void helper_setup_fake_routerlist(void);
|
||||||
|
|
||||||
#define GET(path) "GET " path " HTTP/1.0\r\n\r\n"
|
#define GET(path) "GET " path " HTTP/1.0\r\n\r\n"
|
||||||
void connection_write_to_buf_mock(const char *string, size_t len,
|
void connection_write_to_buf_mock(const char *string, size_t len,
|
||||||
connection_t *conn, int zlib);
|
connection_t *conn, int compressed);
|
||||||
|
|
||||||
int mock_tor_addr_lookup__fail_on_bad_addrs(const char *name,
|
int mock_tor_addr_lookup__fail_on_bad_addrs(const char *name,
|
||||||
uint16_t family, tor_addr_t *out);
|
uint16_t family, tor_addr_t *out);
|
||||||
|
|
|
@ -2242,44 +2242,23 @@ test_util_pow2(void *arg)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Run unit tests for compression functions */
|
|
||||||
static void
|
static void
|
||||||
test_util_gzip(void *arg)
|
test_util_compress_impl(compress_method_t method)
|
||||||
{
|
{
|
||||||
char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
|
char *buf1=NULL, *buf2=NULL, *buf3=NULL;
|
||||||
const char *ccp2;
|
|
||||||
size_t len1, len2;
|
size_t len1, len2;
|
||||||
tor_compress_state_t *state = NULL;
|
|
||||||
|
|
||||||
(void)arg;
|
tt_assert(tor_compress_supports_method(method));
|
||||||
tt_assert(tor_compress_supports_method(GZIP_METHOD));
|
|
||||||
tt_assert(tor_compress_supports_method(ZLIB_METHOD));
|
|
||||||
|
|
||||||
buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
|
buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
|
||||||
tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
|
tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
|
||||||
|
|
||||||
tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1,
|
tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1, method));
|
||||||
GZIP_METHOD));
|
|
||||||
tt_assert(buf2 != NULL);
|
tt_assert(buf2 != NULL);
|
||||||
tt_int_op(len1, OP_LT, strlen(buf1));
|
tt_int_op(len1, OP_LT, strlen(buf1));
|
||||||
tt_int_op(detect_compression_method(buf2, len1), OP_EQ, GZIP_METHOD);
|
tt_int_op(detect_compression_method(buf2, len1), OP_EQ, method);
|
||||||
|
|
||||||
tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1,
|
tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1, method, 1, LOG_INFO));
|
||||||
GZIP_METHOD, 1, LOG_INFO));
|
|
||||||
tt_assert(buf3 != NULL);
|
|
||||||
tt_int_op(strlen(buf1) + 1, OP_EQ, len2);
|
|
||||||
tt_str_op(buf1, OP_EQ, buf3);
|
|
||||||
|
|
||||||
tor_free(buf2);
|
|
||||||
tor_free(buf3);
|
|
||||||
|
|
||||||
tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1,
|
|
||||||
ZLIB_METHOD));
|
|
||||||
tt_assert(buf2);
|
|
||||||
tt_int_op(detect_compression_method(buf2, len1), OP_EQ, ZLIB_METHOD);
|
|
||||||
|
|
||||||
tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1,
|
|
||||||
ZLIB_METHOD, 1, LOG_INFO));
|
|
||||||
tt_assert(buf3 != NULL);
|
tt_assert(buf3 != NULL);
|
||||||
tt_int_op(strlen(buf1) + 1, OP_EQ, len2);
|
tt_int_op(strlen(buf1) + 1, OP_EQ, len2);
|
||||||
tt_str_op(buf1, OP_EQ, buf3);
|
tt_str_op(buf1, OP_EQ, buf3);
|
||||||
|
@ -2288,42 +2267,55 @@ test_util_gzip(void *arg)
|
||||||
tor_free(buf3);
|
tor_free(buf3);
|
||||||
buf2 = tor_reallocarray(buf2, len1, 2);
|
buf2 = tor_reallocarray(buf2, len1, 2);
|
||||||
memcpy(buf2+len1, buf2, len1);
|
memcpy(buf2+len1, buf2, len1);
|
||||||
tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1*2,
|
tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1*2, method, 1, LOG_INFO));
|
||||||
ZLIB_METHOD, 1, LOG_INFO));
|
|
||||||
tt_int_op((strlen(buf1)+1)*2, OP_EQ, len2);
|
tt_int_op((strlen(buf1)+1)*2, OP_EQ, len2);
|
||||||
tt_mem_op(buf3, OP_EQ,
|
tt_mem_op(buf3, OP_EQ,
|
||||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0"
|
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0"
|
||||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0",
|
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0",
|
||||||
(strlen(buf1)+1)*2);
|
(strlen(buf1)+1)*2);
|
||||||
|
|
||||||
|
if (method != ZSTD_METHOD) {
|
||||||
|
/* Check whether we can uncompress partial strings unless we are Zstandard,
|
||||||
|
* which doesn't seem to support this. */
|
||||||
|
|
||||||
|
tor_free(buf1);
|
||||||
|
tor_free(buf2);
|
||||||
|
tor_free(buf3);
|
||||||
|
|
||||||
|
buf1 =
|
||||||
|
tor_strdup("String with low redundancy that won't be compressed much.");
|
||||||
|
tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1, method));
|
||||||
|
tt_int_op(len1, OP_GT, 16);
|
||||||
|
/* when we allow an incomplete string, we should succeed.*/
|
||||||
|
tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1-16,
|
||||||
|
method, 0, LOG_INFO));
|
||||||
|
tt_assert(len2 > 5);
|
||||||
|
buf3[len2]='\0';
|
||||||
|
tt_assert(!strcmpstart(buf1, buf3));
|
||||||
|
|
||||||
|
/* when we demand a complete string, this must fail. */
|
||||||
|
tor_free(buf3);
|
||||||
|
tt_assert(tor_uncompress(&buf3, &len2, buf2, len1-16,
|
||||||
|
method, 1, LOG_INFO));
|
||||||
|
tt_assert(buf3 == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
tor_free(buf1);
|
tor_free(buf1);
|
||||||
tor_free(buf2);
|
tor_free(buf2);
|
||||||
tor_free(buf3);
|
tor_free(buf3);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check whether we can uncompress partial strings. */
|
static void
|
||||||
buf1 =
|
test_util_compress_stream_impl(compress_method_t method,
|
||||||
tor_strdup("String with low redundancy that won't be compressed much.");
|
compression_level_t level)
|
||||||
tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1,
|
{
|
||||||
ZLIB_METHOD));
|
char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
|
||||||
tt_int_op(len1, OP_GT, 16);
|
const char *ccp2;
|
||||||
/* when we allow an incomplete string, we should succeed.*/
|
size_t len1, len2;
|
||||||
tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1-16,
|
|
||||||
ZLIB_METHOD, 0, LOG_INFO));
|
|
||||||
tt_assert(len2 > 5);
|
|
||||||
buf3[len2]='\0';
|
|
||||||
tt_assert(!strcmpstart(buf1, buf3));
|
|
||||||
|
|
||||||
/* when we demand a complete string, this must fail. */
|
tor_compress_state_t *state = NULL;
|
||||||
tor_free(buf3);
|
state = tor_compress_new(1, method, level);
|
||||||
tt_assert(tor_uncompress(&buf3, &len2, buf2, len1-16,
|
|
||||||
ZLIB_METHOD, 1, LOG_INFO));
|
|
||||||
tt_assert(buf3 == NULL);
|
|
||||||
|
|
||||||
/* Now, try streaming compression. */
|
|
||||||
tor_free(buf1);
|
|
||||||
tor_free(buf2);
|
|
||||||
tor_free(buf3);
|
|
||||||
state = tor_compress_new(1, ZLIB_METHOD, HIGH_COMPRESSION);
|
|
||||||
tt_assert(state);
|
tt_assert(state);
|
||||||
cp1 = buf1 = tor_malloc(1024);
|
cp1 = buf1 = tor_malloc(1024);
|
||||||
len1 = 1024;
|
len1 = 1024;
|
||||||
|
@ -2342,7 +2334,7 @@ test_util_gzip(void *arg)
|
||||||
tt_assert(cp1 > cp2); /* Make sure we really added something. */
|
tt_assert(cp1 > cp2); /* Make sure we really added something. */
|
||||||
|
|
||||||
tt_assert(!tor_uncompress(&buf3, &len2, buf1, 1024-len1,
|
tt_assert(!tor_uncompress(&buf3, &len2, buf1, 1024-len1,
|
||||||
ZLIB_METHOD, 1, LOG_WARN));
|
method, 1, LOG_WARN));
|
||||||
/* Make sure it compressed right. */
|
/* Make sure it compressed right. */
|
||||||
tt_str_op(buf3, OP_EQ, "ABCDEFGHIJABCDEFGHIJ");
|
tt_str_op(buf3, OP_EQ, "ABCDEFGHIJABCDEFGHIJ");
|
||||||
tt_int_op(21, OP_EQ, len2);
|
tt_int_op(21, OP_EQ, len2);
|
||||||
|
@ -2350,9 +2342,43 @@ test_util_gzip(void *arg)
|
||||||
done:
|
done:
|
||||||
if (state)
|
if (state)
|
||||||
tor_compress_free(state);
|
tor_compress_free(state);
|
||||||
|
tor_free(buf1);
|
||||||
tor_free(buf2);
|
tor_free(buf2);
|
||||||
tor_free(buf3);
|
tor_free(buf3);
|
||||||
tor_free(buf1);
|
}
|
||||||
|
|
||||||
|
/** Run unit tests for compression functions */
|
||||||
|
static void
|
||||||
|
test_util_compress(void *arg)
|
||||||
|
{
|
||||||
|
(void) arg;
|
||||||
|
compress_method_t methods[] = {
|
||||||
|
GZIP_METHOD,
|
||||||
|
ZLIB_METHOD,
|
||||||
|
LZMA_METHOD,
|
||||||
|
ZSTD_METHOD
|
||||||
|
};
|
||||||
|
|
||||||
|
compression_level_t levels[] = {
|
||||||
|
BEST_COMPRESSION,
|
||||||
|
HIGH_COMPRESSION,
|
||||||
|
MEDIUM_COMPRESSION,
|
||||||
|
LOW_COMPRESSION
|
||||||
|
};
|
||||||
|
|
||||||
|
for (unsigned m = 0; m < ARRAY_LENGTH(methods); ++m) {
|
||||||
|
compress_method_t method = methods[m];
|
||||||
|
|
||||||
|
if (! tor_compress_supports_method(method))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
test_util_compress_impl(method);
|
||||||
|
|
||||||
|
for (unsigned l = 0; l < ARRAY_LENGTH(levels); ++l) {
|
||||||
|
compression_level_t level = levels[l];
|
||||||
|
test_util_compress_stream_impl(method, level);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2407,230 +2433,6 @@ test_util_gzip_compression_bomb(void *arg)
|
||||||
tor_compress_free(state);
|
tor_compress_free(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
test_util_lzma(void *arg)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_LZMA
|
|
||||||
char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
|
|
||||||
const char *ccp2;
|
|
||||||
size_t len1, len2;
|
|
||||||
tor_compress_state_t *state = NULL;
|
|
||||||
|
|
||||||
(void)arg;
|
|
||||||
tt_assert(tor_compress_supports_method(LZMA_METHOD));
|
|
||||||
|
|
||||||
buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
|
|
||||||
tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
|
|
||||||
|
|
||||||
tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1,
|
|
||||||
LZMA_METHOD));
|
|
||||||
tt_assert(buf2 != NULL);
|
|
||||||
tt_int_op(len1, OP_LT, strlen(buf1));
|
|
||||||
tt_int_op(detect_compression_method(buf2, len1), OP_EQ, LZMA_METHOD);
|
|
||||||
|
|
||||||
tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1,
|
|
||||||
LZMA_METHOD, 1, LOG_INFO));
|
|
||||||
tt_assert(buf3 != NULL);
|
|
||||||
tt_int_op(strlen(buf1) + 1, OP_EQ, len2);
|
|
||||||
tt_str_op(buf1, OP_EQ, buf3);
|
|
||||||
|
|
||||||
tor_free(buf1);
|
|
||||||
tor_free(buf2);
|
|
||||||
tor_free(buf3);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Check whether we can uncompress concatenated, compressed strings. */
|
|
||||||
tor_free(buf3);
|
|
||||||
buf2 = tor_reallocarray(buf2, len1, 2);
|
|
||||||
memcpy(buf2+len1, buf2, len1);
|
|
||||||
tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1*2,
|
|
||||||
LZMA_METHOD, 1, LOG_INFO));
|
|
||||||
tt_int_op((strlen(buf1)+1)*2, OP_EQ, len2);
|
|
||||||
tt_mem_op(buf3, OP_EQ,
|
|
||||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0"
|
|
||||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0",
|
|
||||||
(strlen(buf1)+1)*2);
|
|
||||||
|
|
||||||
tor_free(buf1);
|
|
||||||
tor_free(buf2);
|
|
||||||
tor_free(buf3);
|
|
||||||
|
|
||||||
/* Check whether we can uncompress partial strings. */
|
|
||||||
buf1 =
|
|
||||||
tor_strdup("String with low redundancy that won't be compressed much.");
|
|
||||||
tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1,
|
|
||||||
LZMA_METHOD));
|
|
||||||
tt_int_op(len1, OP_GT, 16);
|
|
||||||
/* when we allow an incomplete string, we should succeed.*/
|
|
||||||
tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1-16,
|
|
||||||
LZMA_METHOD, 0, LOG_INFO));
|
|
||||||
tt_assert(len2 > 5);
|
|
||||||
buf3[len2]='\0';
|
|
||||||
tt_assert(!strcmpstart(buf1, buf3));
|
|
||||||
|
|
||||||
/* when we demand a complete string, this must fail. */
|
|
||||||
tor_free(buf3);
|
|
||||||
tt_assert(tor_uncompress(&buf3, &len2, buf2, len1-16,
|
|
||||||
LZMA_METHOD, 1, LOG_INFO));
|
|
||||||
tt_assert(buf3 == NULL);
|
|
||||||
|
|
||||||
tor_free(buf1);
|
|
||||||
tor_free(buf2);
|
|
||||||
tor_free(buf3);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Now, try streaming compression. */
|
|
||||||
state = tor_compress_new(1, LZMA_METHOD, HIGH_COMPRESSION);
|
|
||||||
tt_assert(state);
|
|
||||||
cp1 = buf1 = tor_malloc(1024);
|
|
||||||
len1 = 1024;
|
|
||||||
ccp2 = "ABCDEFGHIJABCDEFGHIJ";
|
|
||||||
len2 = 21;
|
|
||||||
tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 0),
|
|
||||||
OP_EQ, TOR_COMPRESS_OK);
|
|
||||||
tt_int_op(0, OP_EQ, len2); /* Make sure we compressed it all. */
|
|
||||||
tt_assert(cp1 > buf1);
|
|
||||||
|
|
||||||
len2 = 0;
|
|
||||||
cp2 = cp1;
|
|
||||||
tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 1),
|
|
||||||
OP_EQ, TOR_COMPRESS_DONE);
|
|
||||||
tt_int_op(0, OP_EQ, len2);
|
|
||||||
tt_assert(cp1 > cp2); /* Make sure we really added something. */
|
|
||||||
|
|
||||||
tt_assert(!tor_uncompress(&buf3, &len2, buf1, 1024-len1,
|
|
||||||
LZMA_METHOD, 1, LOG_WARN));
|
|
||||||
/* Make sure it compressed right. */
|
|
||||||
tt_str_op(buf3, OP_EQ, "ABCDEFGHIJABCDEFGHIJ");
|
|
||||||
tt_int_op(21, OP_EQ, len2);
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (state)
|
|
||||||
tor_compress_free(state);
|
|
||||||
tor_free(buf2);
|
|
||||||
tor_free(buf3);
|
|
||||||
tor_free(buf1);
|
|
||||||
#else
|
|
||||||
(void)arg;
|
|
||||||
tt_assert(! tor_compress_supports_method(LZMA_METHOD));
|
|
||||||
|
|
||||||
done:
|
|
||||||
;
|
|
||||||
#endif // HAVE_LZMA.
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_util_zstd(void *arg)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_ZSTD
|
|
||||||
char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
|
|
||||||
const char *ccp2;
|
|
||||||
size_t len1, len2;
|
|
||||||
tor_compress_state_t *state = NULL;
|
|
||||||
|
|
||||||
(void)arg;
|
|
||||||
tt_assert(tor_compress_supports_method(ZSTD_METHOD));
|
|
||||||
|
|
||||||
buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
|
|
||||||
tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
|
|
||||||
|
|
||||||
tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1,
|
|
||||||
ZSTD_METHOD));
|
|
||||||
tt_assert(buf2 != NULL);
|
|
||||||
tt_int_op(len1, OP_LT, strlen(buf1));
|
|
||||||
tt_int_op(detect_compression_method(buf2, len1), OP_EQ, ZSTD_METHOD);
|
|
||||||
|
|
||||||
tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1,
|
|
||||||
ZSTD_METHOD, 1, LOG_INFO));
|
|
||||||
tt_assert(buf3 != NULL);
|
|
||||||
tt_int_op(strlen(buf1) + 1, OP_EQ, len2);
|
|
||||||
tt_str_op(buf1, OP_EQ, buf3);
|
|
||||||
|
|
||||||
tor_free(buf1);
|
|
||||||
tor_free(buf2);
|
|
||||||
tor_free(buf3);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Check whether we can uncompress concatenated, compressed strings. */
|
|
||||||
tor_free(buf3);
|
|
||||||
buf2 = tor_reallocarray(buf2, len1, 2);
|
|
||||||
memcpy(buf2+len1, buf2, len1);
|
|
||||||
tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1*2,
|
|
||||||
ZSTD_METHOD, 1, LOG_INFO));
|
|
||||||
tt_int_op((strlen(buf1)+1)*2, OP_EQ, len2);
|
|
||||||
tt_mem_op(buf3, OP_EQ,
|
|
||||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0"
|
|
||||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0",
|
|
||||||
(strlen(buf1)+1)*2);
|
|
||||||
|
|
||||||
tor_free(buf1);
|
|
||||||
tor_free(buf2);
|
|
||||||
tor_free(buf3);
|
|
||||||
|
|
||||||
/* Check whether we can uncompress partial strings. */
|
|
||||||
buf1 =
|
|
||||||
tor_strdup("String with low redundancy that won't be compressed much.");
|
|
||||||
tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1,
|
|
||||||
ZSTD_METHOD));
|
|
||||||
tt_int_op(len1, OP_GT, 16);
|
|
||||||
/* when we allow an incomplete string, we should succeed.*/
|
|
||||||
tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1-16,
|
|
||||||
ZSTD_METHOD, 0, LOG_INFO));
|
|
||||||
tt_assert(len2 > 5);
|
|
||||||
buf3[len2]='\0';
|
|
||||||
tt_assert(!strcmpstart(buf1, buf3));
|
|
||||||
|
|
||||||
/* when we demand a complete string, this must fail. */
|
|
||||||
tor_free(buf3);
|
|
||||||
tt_assert(tor_uncompress(&buf3, &len2, buf2, len1-16,
|
|
||||||
ZSTD_METHOD, 1, LOG_INFO));
|
|
||||||
tt_assert(buf3 == NULL);
|
|
||||||
|
|
||||||
tor_free(buf1);
|
|
||||||
tor_free(buf2);
|
|
||||||
tor_free(buf3);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Now, try streaming compression. */
|
|
||||||
state = tor_compress_new(1, ZSTD_METHOD, HIGH_COMPRESSION);
|
|
||||||
tt_assert(state);
|
|
||||||
cp1 = buf1 = tor_malloc(1024);
|
|
||||||
len1 = 1024;
|
|
||||||
ccp2 = "ABCDEFGHIJABCDEFGHIJ";
|
|
||||||
len2 = 21;
|
|
||||||
tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 0),
|
|
||||||
OP_EQ, TOR_COMPRESS_OK);
|
|
||||||
tt_int_op(0, OP_EQ, len2); /* Make sure we compressed it all. */
|
|
||||||
// tt_assert(cp1 > buf1);
|
|
||||||
|
|
||||||
len2 = 0;
|
|
||||||
cp2 = cp1;
|
|
||||||
tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 1),
|
|
||||||
OP_EQ, TOR_COMPRESS_DONE);
|
|
||||||
tt_int_op(0, OP_EQ, len2);
|
|
||||||
tt_assert(cp1 > cp2); /* Make sure we really added something. */
|
|
||||||
|
|
||||||
tt_assert(!tor_uncompress(&buf3, &len2, buf1, 1024-len1,
|
|
||||||
ZSTD_METHOD, 1, LOG_WARN));
|
|
||||||
/* Make sure it compressed right. */
|
|
||||||
tt_str_op(buf3, OP_EQ, "ABCDEFGHIJABCDEFGHIJ");
|
|
||||||
tt_int_op(21, OP_EQ, len2);
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (state)
|
|
||||||
tor_compress_free(state);
|
|
||||||
tor_free(buf2);
|
|
||||||
tor_free(buf3);
|
|
||||||
tor_free(buf1);
|
|
||||||
#else
|
|
||||||
(void)arg;
|
|
||||||
tt_assert(! tor_compress_supports_method(ZSTD_METHOD));
|
|
||||||
|
|
||||||
done:
|
|
||||||
;
|
|
||||||
#endif // HAVE_ZSTD.
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Run unit tests for mmap() wrapper functionality. */
|
/** Run unit tests for mmap() wrapper functionality. */
|
||||||
static void
|
static void
|
||||||
test_util_mmap(void *arg)
|
test_util_mmap(void *arg)
|
||||||
|
@ -5942,10 +5744,8 @@ struct testcase_t util_tests[] = {
|
||||||
UTIL_LEGACY(strmisc),
|
UTIL_LEGACY(strmisc),
|
||||||
UTIL_TEST(parse_integer, 0),
|
UTIL_TEST(parse_integer, 0),
|
||||||
UTIL_LEGACY(pow2),
|
UTIL_LEGACY(pow2),
|
||||||
UTIL_LEGACY(gzip),
|
UTIL_LEGACY(compress),
|
||||||
UTIL_TEST(gzip_compression_bomb, TT_FORK),
|
UTIL_TEST(gzip_compression_bomb, TT_FORK),
|
||||||
UTIL_LEGACY(lzma),
|
|
||||||
UTIL_LEGACY(zstd),
|
|
||||||
UTIL_LEGACY(datadir),
|
UTIL_LEGACY(datadir),
|
||||||
UTIL_LEGACY(memarea),
|
UTIL_LEGACY(memarea),
|
||||||
UTIL_LEGACY(control_formats),
|
UTIL_LEGACY(control_formats),
|
||||||
|
|
Loading…
Add table
Reference in a new issue