summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/compress.c52
-rw-r--r--src/common/compress_none.c2
-rw-r--r--src/common/sandbox.c10
-rw-r--r--src/common/storagedir.c8
-rw-r--r--src/or/buffers.c11
-rw-r--r--src/or/channelpadding.c16
-rw-r--r--src/or/connection_or.c4
-rw-r--r--src/or/consdiffmgr.c24
-rw-r--r--src/or/consdiffmgr.h3
-rw-r--r--src/or/control.c2
-rw-r--r--src/or/cpuworker.c2
-rw-r--r--src/or/directory.c56
-rw-r--r--src/or/dirserv.c6
-rw-r--r--src/or/entrynodes.c36
-rw-r--r--src/or/main.c4
-rw-r--r--src/test/fuzz/include.am2
-rw-r--r--src/test/test_channelpadding.c2
-rw-r--r--src/test/test_util.c63
18 files changed, 249 insertions, 54 deletions
diff --git a/src/common/compress.c b/src/common/compress.c
index e65894d9d2..7926faaa60 100644
--- a/src/common/compress.c
+++ b/src/common/compress.c
@@ -105,8 +105,8 @@ tor_compress_impl(int compress,
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);
+ log_debug(LD_GENERAL, "method: %d level: %d at len: %lu",
+ method, compression_level, (unsigned long)in_len);
return -1;
}
@@ -146,17 +146,11 @@ tor_compress_impl(int compress,
"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);
+ log_debug(LD_GENERAL, "method: %d level: %d at len: %lu",
+ method, compression_level, (unsigned long)in_len);
goto err;
} else {
- 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 {
+ if (in_len == 0) {
goto done;
}
}
@@ -548,28 +542,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;
}
diff --git a/src/common/compress_none.c b/src/common/compress_none.c
index b76e6010ec..34314e4af7 100644
--- a/src/common/compress_none.c
+++ b/src/common/compress_none.c
@@ -4,7 +4,7 @@
/* See LICENSE for licensing information */
/**
- * \file compress_lzma.c
+ * \file compress_none.c
* \brief Compression backend for identity compression.
*
* We actually define this backend so that we can treat the identity transform
diff --git a/src/common/sandbox.c b/src/common/sandbox.c
index aae0705af4..52caa4fcc6 100644
--- a/src/common/sandbox.c
+++ b/src/common/sandbox.c
@@ -19,8 +19,14 @@
#define _LARGEFILE64_SOURCE
#endif
-/** Malloc mprotect limit in bytes. */
-#define MALLOC_MP_LIM (16*1024*1024)
+/** Malloc mprotect limit in bytes.
+ *
+ * 28/06/2017: This value was increased from 16 MB to 20 MB after we introduced
+ * LZMA support in Tor (0.3.1.1-alpha). We limit our LZMA coder to 16 MB, but
+ * liblzma have a small overhead that we need to compensate for to avoid being
+ * killed by the sandbox.
+ */
+#define MALLOC_MP_LIM (20*1024*1024)
#include <stdio.h>
#include <string.h>
diff --git a/src/common/storagedir.c b/src/common/storagedir.c
index befcfe693f..31933f64c2 100644
--- a/src/common/storagedir.c
+++ b/src/common/storagedir.c
@@ -119,7 +119,8 @@ storage_dir_clean_tmpfiles(storage_dir_t *d)
char *path = NULL;
tor_asprintf(&path, "%s/%s", d->directory, fname);
if (unlink(sandbox_intern_string(path))) {
- log_warn(LD_FS, "Unable to unlink %s", escaped(path));
+ log_warn(LD_FS, "Unable to unlink %s while cleaning "
+ "temporary files: %s", escaped(path), strerror(errno));
tor_free(path);
continue;
}
@@ -210,7 +211,9 @@ storage_dir_read(storage_dir_t *d, const char *fname, int bin, size_t *sz_out)
char *contents = read_file_to_str(path, flags, &st);
if (contents && sz_out) {
// it fits in RAM, so we know its size is less than SIZE_MAX
+#if UINT64_MAX > SIZE_MAX
tor_assert((uint64_t)st.st_size <= SIZE_MAX);
+#endif
*sz_out = (size_t) st.st_size;
}
@@ -453,7 +456,8 @@ storage_dir_remove_file(storage_dir_t *d,
if (unlink(ipath) == 0) {
storage_dir_reduce_usage(d, size);
} else {
- log_warn(LD_FS, "Unable to unlink %s", escaped(path));
+ log_warn(LD_FS, "Unable to unlink %s while removing file: %s",
+ escaped(path), strerror(errno));
tor_free(path);
return;
}
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 3692ed4d08..12a6c0239b 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -2092,7 +2092,7 @@ fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len)
int
write_to_buf_compress(buf_t *buf, tor_compress_state_t *state,
const char *data, size_t data_len,
- int done)
+ const int done)
{
char *next;
size_t old_avail, avail;
@@ -2114,8 +2114,10 @@ write_to_buf_compress(buf_t *buf, tor_compress_state_t *state,
case TOR_COMPRESS_ERROR:
return -1;
case TOR_COMPRESS_OK:
- if (data_len == 0)
+ if (data_len == 0) {
+ tor_assert_nonfatal(!done);
over = 1;
+ }
break;
case TOR_COMPRESS_BUFFER_FULL:
if (avail) {
@@ -2124,6 +2126,11 @@ write_to_buf_compress(buf_t *buf, tor_compress_state_t *state,
* whether were going to or not. */
need_new_chunk = 1;
}
+ if (data_len == 0 && !done) {
+ /* We've consumed all the input data, though, so there's no
+ * point in forging ahead right now. */
+ over = 1;
+ }
break;
}
buf->datalen += old_avail - avail;
diff --git a/src/or/channelpadding.c b/src/or/channelpadding.c
index f5248e8960..bed2489837 100644
--- a/src/or/channelpadding.c
+++ b/src/or/channelpadding.c
@@ -530,10 +530,20 @@ channelpadding_compute_time_until_pad_for_netflow(channel_t *chan)
>= chan->next_padding_time_ms) {
int64_t ms_until_pad_for_netflow = chan->next_padding_time_ms -
long_now;
+ /* If the padding time is in the past, that means that libevent delayed
+ * calling the once-per-second callback due to other work taking too long.
+ * See https://bugs.torproject.org/22212 and
+ * https://bugs.torproject.org/16585. This is a systemic problem
+ * with being single-threaded, but let's emit a notice if this
+ * is long enough in the past that we might have missed a netflow window,
+ * and allowed a router to emit a netflow frame, just so we don't forget
+ * about it entirely.. */
+#define NETFLOW_MISSED_WINDOW (150000 - DFLT_NETFLOW_INACTIVE_KEEPALIVE_HIGH)
if (ms_until_pad_for_netflow < 0) {
- log_warn(LD_BUG,
- "Channel padding timeout scheduled "I64_FORMAT"ms in the past. "
- "Did the monotonic clock just jump?",
+ int severity = (ms_until_pad_for_netflow < -NETFLOW_MISSED_WINDOW)
+ ? LOG_NOTICE : LOG_INFO;
+ log_fn(severity, LD_OR,
+ "Channel padding timeout scheduled "I64_FORMAT"ms in the past. ",
I64_PRINTF_ARG(-ms_until_pad_for_netflow));
return 0; /* Clock jumped: Send padding now */
}
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index ab0f411cc5..753148291c 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -420,9 +420,11 @@ cell_pack(packed_cell_t *dst, const cell_t *src, int wide_circ_ids)
set_uint32(dest, htonl(src->circ_id));
dest += 4;
} else {
+ /* Clear the last two bytes of dest, in case we can accidentally
+ * send them to the network somehow. */
+ memset(dest+CELL_MAX_NETWORK_SIZE-2, 0, 2);
set_uint16(dest, htons(src->circ_id));
dest += 2;
- memset(dest+CELL_MAX_NETWORK_SIZE-2, 0, 2); /*make sure it's clear */
}
set_uint8(dest, src->command);
memcpy(dest+1, src->payload, CELL_PAYLOAD_SIZE);
diff --git a/src/or/consdiffmgr.c b/src/or/consdiffmgr.c
index 2af104733b..638fcd6794 100644
--- a/src/or/consdiffmgr.c
+++ b/src/or/consdiffmgr.c
@@ -325,7 +325,8 @@ cdm_diff_ht_purge(consensus_flavor_t flav,
if ((*diff)->cdm_diff_status == CDM_DIFF_PRESENT &&
flav == (*diff)->flavor) {
- if (consensus_cache_entry_handle_get((*diff)->entry) == NULL) {
+ if (BUG((*diff)->entry == NULL) ||
+ consensus_cache_entry_handle_get((*diff)->entry) == NULL) {
/* the underlying entry has gone away; drop this. */
next = HT_NEXT_RMV(cdm_diff_ht, &cdm_diff_ht, diff);
cdm_diff_free(this);
@@ -622,6 +623,9 @@ consdiffmgr_find_diff_from(consensus_cache_entry_t **entry_out,
return CONSDIFF_IN_PROGRESS;
}
+ if (BUG(ent->entry == NULL)) {
+ return CONSDIFF_NOT_FOUND;
+ }
*entry_out = consensus_cache_entry_handle_get(ent->entry);
return (*entry_out) ? CONSDIFF_AVAILABLE : CONSDIFF_NOT_FOUND;
@@ -1840,3 +1844,21 @@ consensus_cache_entry_get_valid_until(const consensus_cache_entry_t *ent,
return 0;
}
+/** Read the valid after timestamp from the cached object <b>ent</b> into
+ * *<b>out</b> and return 0, or return -1 if no such time was recorded. */
+int
+consensus_cache_entry_get_valid_after(const consensus_cache_entry_t *ent,
+ time_t *out)
+{
+ tor_assert(ent);
+ tor_assert(out);
+
+ const char *s;
+ s = consensus_cache_entry_get_value(ent, LABEL_VALID_AFTER);
+
+ if (s == NULL || parse_iso_time_nospace(s, out) < 0)
+ return -1;
+ else
+ return 0;
+}
+
diff --git a/src/or/consdiffmgr.h b/src/or/consdiffmgr.h
index fe4f9ee239..079f9fe2d2 100644
--- a/src/or/consdiffmgr.h
+++ b/src/or/consdiffmgr.h
@@ -44,6 +44,9 @@ int consensus_cache_entry_get_fresh_until(
int consensus_cache_entry_get_valid_until(
const struct consensus_cache_entry_t *ent,
time_t *out);
+int consensus_cache_entry_get_valid_after(
+ const struct consensus_cache_entry_t *ent,
+ time_t *out);
void consdiffmgr_rescan(void);
int consdiffmgr_cleanup(void);
diff --git a/src/or/control.c b/src/or/control.c
index 9454a7ab67..9bcf1ee364 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -6506,7 +6506,7 @@ monitor_owning_controller_process(const char *process_spec)
msg);
owning_controller_process_spec = NULL;
tor_cleanup();
- exit(0);
+ exit(1);
}
}
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index af79fafaa6..1013fa555e 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -475,7 +475,7 @@ queue_pending_tasks(void)
return;
if (assign_onionskin_to_cpuworker(circ, onionskin))
- log_warn(LD_OR,"assign_to_cpuworker failed. Ignoring.");
+ log_info(LD_OR,"assign_to_cpuworker failed. Ignoring.");
}
}
diff --git a/src/or/directory.c b/src/or/directory.c
index ac40e54ceb..45fbd1dd33 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -3920,6 +3920,30 @@ find_best_compression_method(unsigned compression_methods, int stream)
return NO_METHOD;
}
+/** Check if any of the digests in <b>digests</b> matches the latest consensus
+ * flavor (given in <b>flavor</b>) that we have available. */
+static int
+digest_list_contains_best_consensus(consensus_flavor_t flavor,
+ const smartlist_t *digests)
+{
+ const networkstatus_t *ns = NULL;
+
+ if (digests == NULL)
+ return 0;
+
+ ns = networkstatus_get_latest_consensus_by_flavor(flavor);
+
+ if (ns == NULL)
+ return 0;
+
+ SMARTLIST_FOREACH_BEGIN(digests, const uint8_t *, digest) {
+ if (tor_memeq(ns->digest_sha3_as_signed, digest, DIGEST256_LEN))
+ return 1;
+ } SMARTLIST_FOREACH_END(digest);
+
+ return 0;
+}
+
/** Check if the given compression method is allowed for a connection that is
* supposed to be anonymous. Returns 1 if the compression method is allowed,
* otherwise 0. */
@@ -4089,6 +4113,13 @@ handle_get_current_consensus(dir_connection_t *conn,
goto done;
}
+ if (digest_list_contains_best_consensus(req.flav,
+ req.diff_from_digests)) {
+ write_http_status_line(conn, 304, "Not modified");
+ geoip_note_ns_response(GEOIP_REJECT_NOT_MODIFIED);
+ goto done;
+ }
+
struct consensus_cache_entry_t *cached_consensus = NULL;
compress_method_t compression_used = NO_METHOD;
@@ -4227,13 +4258,14 @@ static int
handle_get_status_vote(dir_connection_t *conn, const get_handler_args_t *args)
{
const char *url = args->url;
- const compress_method_t compress_method =
- find_best_compression_method(args->compression_supported, 1);
{
int current;
ssize_t body_len = 0;
ssize_t estimated_len = 0;
+ /* This smartlist holds strings that we can compress on the fly. */
smartlist_t *items = smartlist_new();
+ /* This smartlist holds cached_dir_t objects that have a precompressed
+ * deflated version. */
smartlist_t *dir_items = smartlist_new();
int lifetime = 60; /* XXXX?? should actually use vote intervals. */
url += strlen("/tor/status-vote/");
@@ -4284,6 +4316,26 @@ handle_get_status_vote(dir_connection_t *conn, const get_handler_args_t *args)
write_http_status_line(conn, 404, "Not found");
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,
body_len += compress_method != NO_METHOD ?
d->dir_compressed_len : d->dir_len);
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 408f58b22b..4954471c6a 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -14,6 +14,7 @@
#include "connection.h"
#include "connection_or.h"
#include "conscache.h"
+#include "consdiffmgr.h"
#include "control.h"
#include "directory.h"
#include "dirserv.h"
@@ -3518,6 +3519,11 @@ spooled_resource_estimate_size(const spooled_resource_t *spooled,
} else {
cached_dir_t *cached;
if (spooled->consensus_cache_entry) {
+ if (published_out) {
+ consensus_cache_entry_get_valid_after(
+ spooled->consensus_cache_entry, published_out);
+ }
+
return spooled->cce_len;
}
if (spooled->cached_dir_ref) {
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index dc2cab28f7..be9f85a89f 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -1093,6 +1093,18 @@ select_and_add_guard_item_for_sample(guard_selection_t *gs,
return added_guard;
}
+/** Return true iff we need a consensus to maintain our */
+static int
+live_consensus_is_missing(const guard_selection_t *gs)
+{
+ tor_assert(gs);
+ if (gs->type == GS_TYPE_BRIDGE) {
+ /* We don't update bridges from the consensus; they aren't there. */
+ return 0;
+ }
+ return networkstatus_get_live_consensus(approx_time()) == NULL;
+}
+
/**
* Add new guards to the sampled guards in <b>gs</b> until there are
* enough usable filtered guards, but never grow the sample beyond its
@@ -1104,6 +1116,13 @@ entry_guards_expand_sample(guard_selection_t *gs)
{
tor_assert(gs);
const or_options_t *options = get_options();
+
+ if (live_consensus_is_missing(gs)) {
+ log_info(LD_GUARD, "Not expanding the sample guard set; we have "
+ "no live consensus.");
+ return NULL;
+ }
+
int n_sampled = smartlist_len(gs->sampled_entry_guards);
entry_guard_t *added_guard = NULL;
int n_usable_filtered_guards = num_reachable_filtered_guards(gs, NULL);
@@ -1212,18 +1231,13 @@ sampled_guards_update_from_consensus(guard_selection_t *gs)
// It's important to use only a live consensus here; we don't want to
// make changes based on anything expired or old.
- if (gs->type != GS_TYPE_BRIDGE) {
- networkstatus_t *ns = networkstatus_get_live_consensus(approx_time());
-
- if (! ns) {
- log_info(LD_GUARD, "No live consensus; can't update "
- "sampled entry guards.");
- return;
- } else {
- log_info(LD_GUARD, "Updating sampled guard status based on received "
- "consensus.");
- }
+ if (live_consensus_is_missing(gs)) {
+ log_info(LD_GUARD, "Not updating the sample guard set; we have "
+ "no live consensus.");
+ return;
}
+ log_info(LD_GUARD, "Updating sampled guard status based on received "
+ "consensus.");
int n_changes = 0;
diff --git a/src/or/main.c b/src/or/main.c
index 9699c8d381..cb24fd18c8 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -1556,7 +1556,7 @@ check_ed_keys_callback(time_t now, const or_options_t *options)
generate_ed_link_cert(options, now, new_signing_key > 0)) {
log_err(LD_OR, "Unable to update Ed25519 keys! Exiting.");
tor_cleanup();
- exit(0);
+ exit(1);
}
}
return 30;
@@ -3168,7 +3168,7 @@ try_locking(const or_options_t *options, int err_if_locked)
r = try_locking(options, 0);
if (r<0) {
log_err(LD_GENERAL, "No, it's still there. Exiting.");
- exit(0);
+ exit(1);
}
return r;
}
diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am
index 6008238bba..2961dab56f 100644
--- a/src/test/fuzz/include.am
+++ b/src/test/fuzz/include.am
@@ -36,7 +36,7 @@ oss-fuzz-prereqs: \
noinst_HEADERS += \
src/test/fuzz/fuzzing.h
-LIBFUZZER = /home/nickm/build/libfuzz/libFuzzer.a
+LIBFUZZER = -lFuzzer
LIBFUZZER_CPPFLAGS = $(FUZZING_CPPFLAGS) -DLLVM_FUZZ
LIBFUZZER_CFLAGS = $(FUZZING_CFLAGS)
LIBFUZZER_LDFLAG = $(FUZZING_LDFLAG)
diff --git a/src/test/test_channelpadding.c b/src/test/test_channelpadding.c
index 0a70184f86..3b889991b6 100644
--- a/src/test/test_channelpadding.c
+++ b/src/test/test_channelpadding.c
@@ -795,8 +795,6 @@ test_channelpadding_decide_to_pad_channel(void *arg)
tried_to_write_cell = 0;
chan->next_padding_time_ms = monotime_coarse_absolute_msec() - 100;
decision = channelpadding_decide_to_pad_channel(chan);
- expect_log_msg("Channel padding timeout scheduled 100ms in the past. "
- "Did the monotonic clock just jump?\n");
tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SENT);
tt_int_op(tried_to_write_cell, OP_EQ, 1);
tt_assert(!chan->pending_padding_callback);
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 0d9dd974df..7db93324d1 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -2399,6 +2399,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
test_util_gzip_compression_bomb(void *arg)
{
/* A 'compression bomb' is a very small object that uncompresses to a huge
@@ -5819,6 +5872,11 @@ test_util_get_unquoted_path(void *arg)
{ "compress/" #name, test_util_compress, 0, &passthrough_setup, \
(char*)(identifier) }
+#define COMPRESS_CONCAT(name, identifier) \
+ { "compress_concat/" #name, test_util_decompress_concatenated, 0, \
+ &passthrough_setup, \
+ (char*)(identifier) }
+
#ifdef _WIN32
#define UTIL_TEST_NO_WIN(n, f) { #n, NULL, TT_SKIP, NULL, NULL }
#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(zstd, "x-zstd"),
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_LEGACY(datadir),
UTIL_LEGACY(memarea),