21#ifdef HAVE_NETINET_IN_H
22#include <netinet/in.h>
57#define MAX_UNCOMPRESSION_FACTOR 25
58#define CHECK_FOR_COMPRESSION_BOMB_AFTER (1024*64)
66 if (size_in == 0 || size_out < CHECK_FOR_COMPRESSION_BOMB_AFTER)
69 if (size_out / size_in > MAX_UNCOMPRESSION_FACTOR) {
71 "Detected possible compression bomb with "
72 "input size = %"TOR_PRIuSZ
" and output size = %"TOR_PRIuSZ,
88 (void)compression_level;
89 if (method == NO_METHOD) {
92 return (in_len < SIZE_MAX) ? in_len + 1 : in_len;
102 return MAX(in_len, 1024);
110 char **out,
size_t *out_len,
111 const char *in,
size_t in_len,
115 int protocol_warn_level)
122 if (stream == NULL) {
123 log_warn(
LD_GENERAL,
"NULL stream while %scompressing",
125 log_debug(
LD_GENERAL,
"method: %d level: %d at len: %lu",
126 method, compression_level, (
unsigned long)in_len);
130 size_t in_len_orig = in_len;
131 size_t out_remaining, out_alloc;
134 out_remaining = out_alloc =
136 *out = outptr = tor_malloc(out_remaining);
138 const int finish = complete_only || compress;
142 &outptr, &out_remaining,
143 &in, &in_len, finish)) {
144 case TOR_COMPRESS_DONE:
145 if (in_len == 0 || compress) {
151 tor_compress_free(stream);
153 if (stream == NULL) {
154 log_warn(
LD_GENERAL,
"NULL stream while %scompressing",
160 case TOR_COMPRESS_OK:
161 if (compress || complete_only) {
163 "Unexpected %s while %scompressing",
164 complete_only?
"end of input":
"result",
166 log_debug(
LD_GENERAL,
"method: %d level: %d at len: %lu",
167 method, compression_level, (
unsigned long)in_len);
175 case TOR_COMPRESS_BUFFER_FULL: {
176 if (!compress && outptr < *out+out_alloc) {
180 "Possible truncated or corrupt compressed data");
184 log_warn(
LD_GENERAL,
"While %scompressing data: ran out of space.",
196 const size_t offset = outptr - *out;
198 *out = tor_realloc(*out, out_alloc);
199 outptr = *out + offset;
200 out_remaining = out_alloc - offset;
203 case TOR_COMPRESS_ERROR:
205 "Error while %scompressing data: bad input?",
217 *out_len = outptr - *out;
219 log_warn(
LD_BUG,
"We compressed something and got an insanely high "
220 "compression factor; other Tors would think this was a "
221 "compression bomb.");
226 if (out_alloc == *out_len)
227 *out = tor_realloc(*out, out_alloc + 1);
228 (*out)[*out_len] =
'\0';
240 tor_compress_free(stream);
251 const char *in,
size_t in_len,
277 const char *in,
size_t in_len,
280 int protocol_warn_level)
284 complete_only, protocol_warn_level);
294 if (in_len > 2 &&
fast_memeq(in,
"\x1f\x8b", 2)) {
296 }
else if (in_len > 2 && (in[0] & 0x0f) == 8 &&
299 }
else if (in_len > 2 &&
302 }
else if (in_len > 3 &&
306 return UNKNOWN_METHOD;
338 static unsigned supported = 0;
339 if (supported == 0) {
341 for (m = NO_METHOD; m <= UNKNOWN_METHOD; ++m) {
343 supported |= (1u << m);
356 {
"gzip", GZIP_METHOD },
357 {
"deflate", ZLIB_METHOD },
360 {
"x-tor-lzma", LZMA_METHOD },
361 {
"x-zstd" , ZSTD_METHOD },
362 {
"identity", NO_METHOD },
366 {
"x-gzip", GZIP_METHOD },
387 { NO_METHOD,
"uncompressed" },
388 { GZIP_METHOD,
"gzipped" },
389 { ZLIB_METHOD,
"deflated" },
390 { LZMA_METHOD,
"LZMA compressed" },
391 { ZSTD_METHOD,
"Zstandard compressed" },
392 { UNKNOWN_METHOD,
"unknown encoding" },
418 return UNKNOWN_METHOD;
503 if (zlib_state == NULL)
506 state->
u.zlib_state = zlib_state;
513 if (lzma_state == NULL)
516 state->
u.lzma_state = lzma_state;
523 if (zstd_state == NULL)
526 state->
u.zstd_state = zstd_state;
558 char **out,
size_t *out_len,
559 const char **in,
size_t *in_len,
563 const size_t in_len_orig = *in_len;
564 const size_t out_len_orig = *out_len;
567 if (*out_len == 0 && (*in_len > 0 || finish)) {
571 return TOR_COMPRESS_BUFFER_FULL;
578 out, out_len, in, in_len,
583 out, out_len, in, in_len,
588 out, out_len, in, in_len,
599 if (BUG((rv == TOR_COMPRESS_OK) &&
600 *in_len == in_len_orig &&
601 *out_len == out_len_orig)) {
603 "More info on the bug: method == %s, finish == %d, "
604 " *in_len == in_len_orig == %lu, "
605 "*out_len == out_len_orig == %lu",
607 (
unsigned long)in_len_orig, (
unsigned long)out_len_orig);
608 return TOR_COMPRESS_ERROR;
613 return TOR_COMPRESS_ERROR;
626 tor_zlib_compress_free(state->
u.zlib_state);
629 tor_lzma_compress_free(state->
u.lzma_state);
632 tor_zstd_compress_free(state->
u.zstd_state);
698subsys_compress_initialize(
void)
708 .initialize = subsys_compress_initialize,
Inline functions for reading and writing multibyte values from the middle of strings,...
static uint16_t get_uint16(const void *cp)
static uint16_t tor_ntohs(uint16_t a)
Macro definitions for MIN, MAX, and CLAMP.
void atomic_counter_init(atomic_counter_t *counter)
void atomic_counter_sub(atomic_counter_t *counter, size_t sub)
void atomic_counter_add(atomic_counter_t *counter, size_t add)
size_t atomic_counter_get(atomic_counter_t *counter)
const char * tor_compress_version_str(compress_method_t method)
int tor_compress_init(void)
tor_compress_output_t tor_compress_process(tor_compress_state_t *state, char **out, size_t *out_len, const char **in, size_t *in_len, int finish)
static const struct @28 compression_method_human_names[]
int tor_compress_supports_method(compress_method_t method)
static size_t guess_compress_size(int compress, compress_method_t method, compression_level_t compression_level, size_t in_len)
compress_method_t compression_method_get_by_name(const char *name)
int tor_compress_is_compression_bomb(size_t size_in, size_t size_out)
const char * tor_compress_header_version_str(compress_method_t method)
static atomic_counter_t total_compress_allocation
void tor_compress_free_(tor_compress_state_t *state)
static const struct @27 compression_method_names[]
unsigned tor_compress_get_supported_method_bitmask(void)
size_t tor_compress_state_size(const tor_compress_state_t *state)
static int tor_compress_impl(int compress, char **out, size_t *out_len, const char *in, size_t in_len, compress_method_t method, compression_level_t compression_level, int complete_only, int protocol_warn_level)
void tor_compress_log_init_warnings(void)
int tor_compress(char **out, size_t *out_len, const char *in, size_t in_len, compress_method_t method)
compress_method_t detect_compression_method(const char *in, size_t in_len)
tor_compress_state_t * tor_compress_new(int compress, compress_method_t method, compression_level_t compression_level)
int tor_uncompress(char **out, size_t *out_len, const char *in, size_t in_len, compress_method_t method, int complete_only, int protocol_warn_level)
const char * compression_method_get_name(compress_method_t method)
size_t tor_compress_get_total_allocation(void)
const char * compression_method_get_human_name(compress_method_t method)
tor_lzma_compress_state_t * tor_lzma_compress_new(int compress, compress_method_t method, compression_level_t level)
const char * tor_lzma_get_version_str(void)
int tor_lzma_method_supported(void)
const char * tor_lzma_get_header_version_str(void)
tor_compress_output_t tor_lzma_compress_process(tor_lzma_compress_state_t *state, char **out, size_t *out_len, const char **in, size_t *in_len, int finish)
size_t tor_lzma_compress_state_size(const tor_lzma_compress_state_t *state)
size_t tor_lzma_get_total_allocation(void)
Header for compress_lzma.c.
tor_compress_output_t tor_cnone_compress_process(char **out, size_t *out_len, const char **in, size_t *in_len, int finish)
Header for compress_none.c.
Declare subsystem object for the compress module.
const char * tor_zlib_get_header_version_str(void)
const char * tor_zlib_get_version_str(void)
int tor_zlib_method_supported(void)
tor_zlib_compress_state_t * tor_zlib_compress_new(int compress_, compress_method_t method, compression_level_t compression_level)
size_t tor_zlib_get_total_allocation(void)
size_t tor_zlib_compress_state_size(const tor_zlib_compress_state_t *state)
tor_compress_output_t tor_zlib_compress_process(tor_zlib_compress_state_t *state, char **out, size_t *out_len, const char **in, size_t *in_len, int finish)
Header for compress_zlib.c.
const char * tor_zstd_get_header_version_str(void)
int tor_zstd_method_supported(void)
const char * tor_zstd_get_version_str(void)
tor_zstd_compress_state_t * tor_zstd_compress_new(int compress, compress_method_t method, compression_level_t level)
tor_compress_output_t tor_zstd_compress_process(tor_zstd_compress_state_t *state, char **out, size_t *out_len, const char **in, size_t *in_len, int finish)
size_t tor_zstd_get_total_allocation(void)
size_t tor_zstd_compress_state_size(const tor_zstd_compress_state_t *state)
void tor_zstd_warn_if_version_mismatched(void)
Header for compress_zstd.c.
#define fast_memeq(a, b, c)
#define log_fn(severity, domain, args,...)
Headers for util_malloc.c.
union tor_compress_state_t::@29 u
Types used to declare a subsystem.
#define SUBSYS_DECLARE_LOCATION()
#define MOCK_IMPL(rv, funcname, arglist)
Integer definitions used throughout Tor.
Macros to manage assertions, fatal and non-fatal.
#define tor_assert_nonfatal_unreached()