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 return (size_out / size_in > MAX_UNCOMPRESSION_FACTOR);
80 (void)compression_level;
81 if (method == NO_METHOD) {
84 return (in_len < SIZE_MAX) ? in_len + 1 : in_len;
94 return MAX(in_len, 1024);
102 char **out,
size_t *out_len,
103 const char *in,
size_t in_len,
107 int protocol_warn_level)
114 if (stream == NULL) {
115 log_warn(
LD_GENERAL,
"NULL stream while %scompressing",
117 log_debug(
LD_GENERAL,
"method: %d level: %d at len: %lu",
118 method, compression_level, (
unsigned long)in_len);
122 size_t in_len_orig = in_len;
123 size_t out_remaining, out_alloc;
126 out_remaining = out_alloc =
128 *out = outptr = tor_malloc(out_remaining);
130 const int finish = complete_only || compress;
134 &outptr, &out_remaining,
135 &in, &in_len, finish)) {
136 case TOR_COMPRESS_DONE:
137 if (in_len == 0 || compress) {
143 tor_compress_free(stream);
145 if (stream == NULL) {
146 log_warn(
LD_GENERAL,
"NULL stream while %scompressing",
152 case TOR_COMPRESS_OK:
153 if (compress || complete_only) {
155 "Unexpected %s while %scompressing",
156 complete_only?
"end of input":
"result",
158 log_debug(
LD_GENERAL,
"method: %d level: %d at len: %lu",
159 method, compression_level, (
unsigned long)in_len);
167 case TOR_COMPRESS_BUFFER_FULL: {
168 if (!compress && outptr < *out+out_alloc) {
172 "Possible truncated or corrupt compressed data");
176 log_warn(
LD_GENERAL,
"While %scompressing data: ran out of space.",
188 const size_t offset = outptr - *out;
190 *out = tor_realloc(*out, out_alloc);
191 outptr = *out + offset;
192 out_remaining = out_alloc - offset;
195 case TOR_COMPRESS_ERROR:
197 "Error while %scompressing data: bad input?",
209 *out_len = outptr - *out;
211 log_warn(
LD_BUG,
"We compressed something and got an insanely high "
212 "compression factor; other Tors would think this was a "
213 "compression bomb.");
218 if (out_alloc == *out_len)
219 *out = tor_realloc(*out, out_alloc + 1);
220 (*out)[*out_len] =
'\0';
232 tor_compress_free(stream);
243 const char *in,
size_t in_len,
269 const char *in,
size_t in_len,
272 int protocol_warn_level)
276 complete_only, protocol_warn_level);
286 if (in_len > 2 &&
fast_memeq(in,
"\x1f\x8b", 2)) {
288 }
else if (in_len > 2 && (in[0] & 0x0f) == 8 &&
291 }
else if (in_len > 2 &&
294 }
else if (in_len > 3 &&
298 return UNKNOWN_METHOD;
330 static unsigned supported = 0;
331 if (supported == 0) {
333 for (m = NO_METHOD; m <= UNKNOWN_METHOD; ++m) {
335 supported |= (1u << m);
344 static const struct {
348 {
"gzip", GZIP_METHOD },
349 {
"deflate", ZLIB_METHOD },
352 {
"x-tor-lzma", LZMA_METHOD },
353 {
"x-zstd" , ZSTD_METHOD },
354 {
"identity", NO_METHOD },
358 {
"x-gzip", GZIP_METHOD },
375 static const struct {
379 { NO_METHOD,
"uncompressed" },
380 { GZIP_METHOD,
"gzipped" },
381 { ZLIB_METHOD,
"deflated" },
382 { LZMA_METHOD,
"LZMA compressed" },
383 { ZSTD_METHOD,
"Zstandard compressed" },
384 { UNKNOWN_METHOD,
"unknown encoding" },
410 return UNKNOWN_METHOD;
495 if (zlib_state == NULL)
498 state->
u.zlib_state = zlib_state;
505 if (lzma_state == NULL)
508 state->
u.lzma_state = lzma_state;
515 if (zstd_state == NULL)
518 state->
u.zstd_state = zstd_state;
550 char **out,
size_t *out_len,
551 const char **in,
size_t *in_len,
555 const size_t in_len_orig = *in_len;
556 const size_t out_len_orig = *out_len;
559 if (*out_len == 0 && (*in_len > 0 || finish)) {
563 return TOR_COMPRESS_BUFFER_FULL;
570 out, out_len, in, in_len,
575 out, out_len, in, in_len,
580 out, out_len, in, in_len,
591 if (BUG((rv == TOR_COMPRESS_OK) &&
592 *in_len == in_len_orig &&
593 *out_len == out_len_orig)) {
595 "More info on the bug: method == %s, finish == %d, "
596 " *in_len == in_len_orig == %lu, "
597 "*out_len == out_len_orig == %lu",
599 (
unsigned long)in_len_orig, (
unsigned long)out_len_orig);
600 return TOR_COMPRESS_ERROR;
605 return TOR_COMPRESS_ERROR;
618 tor_zlib_compress_free(state->
u.zlib_state);
621 tor_lzma_compress_free(state->
u.lzma_state);
624 tor_zstd_compress_free(state->
u.zstd_state);
690 subsys_compress_initialize(
void)
700 .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)
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)
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)
static atomic_counter_t total_compress_allocation
const char * compression_method_get_name(compress_method_t method)
void tor_compress_free_(tor_compress_state_t *state)
const char * tor_compress_header_version_str(compress_method_t method)
const char * compression_method_get_human_name(compress_method_t method)
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)
tor_compress_state_t * tor_compress_new(int compress, compress_method_t method, compression_level_t compression_level)
int tor_compress(char **out, size_t *out_len, const char *in, size_t in_len, compress_method_t method)
const char * tor_compress_version_str(compress_method_t method)
static const struct @21 compression_method_names[]
compress_method_t detect_compression_method(const char *in, size_t in_len)
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)
size_t tor_compress_get_total_allocation(void)
static const struct @22 compression_method_human_names[]
int tor_lzma_method_supported(void)
const char * tor_lzma_get_version_str(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)
tor_lzma_compress_state_t * tor_lzma_compress_new(int compress, compress_method_t method, compression_level_t level)
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)
int tor_zlib_method_supported(void)
size_t tor_zlib_get_total_allocation(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_compress_state_size(const tor_zlib_compress_state_t *state)
const char * tor_zlib_get_version_str(void)
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.
int tor_zstd_method_supported(void)
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)
const char * tor_zstd_get_version_str(void)
size_t tor_zstd_get_total_allocation(void)
const char * tor_zstd_get_header_version_str(void)
size_t tor_zstd_compress_state_size(const tor_zstd_compress_state_t *state)
tor_zstd_compress_state_t * tor_zstd_compress_new(int compress, compress_method_t method, compression_level_t level)
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::@23 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()