Tor 0.4.9.9
Loading...
Searching...
No Matches
compress.c
Go to the documentation of this file.
1/* Copyright (c) 2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
4/* See LICENSE for licensing information */
5
6/**
7 * \file compress.c
8 * \brief Common compression API implementation.
9 *
10 * This file provides a unified interface to all the compression libraries Tor
11 * knows how to use.
12 **/
13
14#include "orconfig.h"
15
16#include <stdlib.h>
17#include <stdio.h>
18#include <string.h>
19#include "lib/cc/torint.h"
20
21#ifdef HAVE_NETINET_IN_H
22#include <netinet/in.h>
23#endif
24
25#include "lib/log/log.h"
26#include "lib/log/util_bug.h"
27#include "lib/arch/bytes.h"
28#include "lib/ctime/di_ops.h"
35#include "lib/intmath/cmp.h"
36#include "lib/malloc/malloc.h"
37#include "lib/subsys/subsys.h"
38#include "lib/thread/threads.h"
39
40/** Total number of bytes allocated for compression state overhead. */
42
43/** @{ */
44/* These macros define the maximum allowable compression factor. Anything of
45 * size greater than CHECK_FOR_COMPRESSION_BOMB_AFTER is not allowed to
46 * have an uncompression factor (uncompressed size:compressed size ratio) of
47 * any greater than MAX_UNCOMPRESSION_FACTOR.
48 *
49 * Picking a value for MAX_UNCOMPRESSION_FACTOR is a trade-off: we want it to
50 * be small to limit the attack multiplier, but we also want it to be large
51 * enough so that no legitimate document --even ones we might invent in the
52 * future -- ever compresses by a factor of greater than
53 * MAX_UNCOMPRESSION_FACTOR. Within those parameters, there's a reasonably
54 * large range of possible values. IMO, anything over 8 is probably safe; IMO
55 * anything under 50 is probably sufficient.
56 *
57 * 2025-10-01: (ahf) Bumped to 5 MB to avoid the situation described in
58 * tor#40739.
59 */
60#define MAX_UNCOMPRESSION_FACTOR 25
61#define CHECK_FOR_COMPRESSION_BOMB_AFTER (5 * 1024 * 1024)
62/** @} */
63
64/** Return true if uncompressing an input of size <b>in_size</b> to an input of
65 * size at least <b>size_out</b> looks like a compression bomb. */
66MOCK_IMPL(int,
67tor_compress_is_compression_bomb,(size_t size_in, size_t size_out))
68{
69 if (size_in == 0 || size_out < CHECK_FOR_COMPRESSION_BOMB_AFTER)
70 return 0;
71
72 double compression_factor = (double)size_out / size_in;
73 if (compression_factor > MAX_UNCOMPRESSION_FACTOR) {
74 log_warn(LD_GENERAL,
75 "Detected possible compression bomb with "
76 "input size = %"TOR_PRIuSZ" and output size = %"TOR_PRIuSZ" "
77 "(compression factor = %.2f)",
78 size_in, size_out, compression_factor);
79 return 1;
80 }
81
82 return 0;
83}
84
85/** Guess the size that <b>in_len</b> will be after compression or
86 * decompression. */
87static size_t
89 compression_level_t compression_level,
90 size_t in_len)
91{
92 // ignore these for now.
93 (void)compression_level;
94 if (method == NO_METHOD) {
95 /* Guess that we'll need an extra byte, to avoid a needless realloc
96 * for nul-termination */
97 return (in_len < SIZE_MAX) ? in_len + 1 : in_len;
98 }
99
100 /* Always guess a factor of 2. */
101 if (compress) {
102 in_len /= 2;
103 } else {
104 if (in_len < SIZE_T_CEILING/2)
105 in_len *= 2;
106 }
107 return MAX(in_len, 1024);
108}
109
110/** Internal function to implement tor_compress/tor_uncompress, depending on
111 * whether <b>compress</b> is set. All arguments are as for tor_compress or
112 * tor_uncompress. */
113static int
114tor_compress_impl(int compress,
115 char **out, size_t *out_len,
116 const char *in, size_t in_len,
117 compress_method_t method,
118 compression_level_t compression_level,
119 int complete_only,
120 int protocol_warn_level)
121{
122 tor_compress_state_t *stream;
123 int rv;
124
125 stream = tor_compress_new(compress, method, compression_level);
126
127 if (stream == NULL) {
128 log_warn(LD_GENERAL, "NULL stream while %scompressing",
129 compress?"":"de");
130 log_debug(LD_GENERAL, "method: %d level: %d at len: %lu",
131 method, compression_level, (unsigned long)in_len);
132 return -1;
133 }
134
135 size_t in_len_orig = in_len;
136 size_t out_remaining, out_alloc;
137 char *outptr;
138
139 out_remaining = out_alloc =
140 guess_compress_size(compress, method, compression_level, in_len);
141 *out = outptr = tor_malloc(out_remaining);
142
143 const int finish = complete_only || compress;
144
145 while (1) {
146 switch (tor_compress_process(stream,
147 &outptr, &out_remaining,
148 &in, &in_len, finish)) {
149 case TOR_COMPRESS_DONE:
150 if (in_len == 0 || compress) {
151 goto done;
152 } else {
153 // More data is present, and we're decompressing. So we may need to
154 // reinitialize the stream if we are handling multiple concatenated
155 // inputs.
156
157 /* Check the cumulative ratio across all sub-streams before
158 * reinitializing: the inner per-sub-stream bomb check resets to zero
159 * with each new backend state, so without this check an attacker can
160 * concatenate many sub-streams each just under
161 * CHECK_FOR_COMPRESSION_BOMB_AFTER bytes of output and escape
162 * detection entirely. Both subtractions are safe: outptr >= *out
163 * always (it only advances forward, and out_alloc is bounded by
164 * SIZE_T_CEILING/2), and in_len <= in_len_orig always (input is only
165 * consumed). */
166 const size_t out_so_far = (size_t)(outptr - *out);
167 const size_t in_so_far = in_len_orig - in_len;
168 if (tor_compress_is_compression_bomb(in_so_far, out_so_far)) {
169 log_warn(LD_DIR, "Possible compression bomb across concatenated "
170 "streams; abandoning.");
171 goto err;
172 }
173 tor_compress_free(stream);
174 stream = tor_compress_new(compress, method, compression_level);
175 if (stream == NULL) {
176 log_warn(LD_GENERAL, "NULL stream while %scompressing",
177 compress?"":"de");
178 goto err;
179 }
180 }
181 break;
182 case TOR_COMPRESS_OK:
183 if (compress || complete_only) {
184 log_fn(protocol_warn_level, LD_PROTOCOL,
185 "Unexpected %s while %scompressing",
186 complete_only?"end of input":"result",
187 compress?"":"de");
188 log_debug(LD_GENERAL, "method: %d level: %d at len: %lu",
189 method, compression_level, (unsigned long)in_len);
190 goto err;
191 } else {
192 if (in_len == 0) {
193 goto done;
194 }
195 }
196 break;
197 case TOR_COMPRESS_BUFFER_FULL: {
198 if (!compress && outptr < *out+out_alloc) {
199 // A buffer error in this case means that we have a problem
200 // with our input.
201 log_fn(protocol_warn_level, LD_PROTOCOL,
202 "Possible truncated or corrupt compressed data");
203 goto err;
204 }
205 if (out_alloc >= SIZE_T_CEILING / 2) {
206 log_warn(LD_GENERAL, "While %scompressing data: ran out of space.",
207 compress?"":"un");
208 goto err;
209 }
210 if (!compress &&
211 tor_compress_is_compression_bomb(in_len_orig, out_alloc)) {
212 // This should already have been caught down in the backend logic.
213 // LCOV_EXCL_START
215 goto err;
216 // LCOV_EXCL_STOP
217 }
218 const size_t offset = outptr - *out;
219 out_alloc *= 2;
220 *out = tor_realloc(*out, out_alloc);
221 outptr = *out + offset;
222 out_remaining = out_alloc - offset;
223 break;
224 }
225 case TOR_COMPRESS_ERROR:
226 log_fn(protocol_warn_level, LD_GENERAL,
227 "Error while %scompressing data: bad input?",
228 compress?"":"un");
229 goto err; // bad data.
230
231 // LCOV_EXCL_START
232 default:
234 goto err;
235 // LCOV_EXCL_STOP
236 }
237 }
238 done:
239 *out_len = outptr - *out;
240 if (compress && tor_compress_is_compression_bomb(*out_len, in_len_orig)) {
241 log_warn(LD_BUG, "We compressed something and got an insanely high "
242 "compression factor; other Tors would think this was a "
243 "compression bomb.");
244 goto err;
245 }
246 if (!compress) {
247 // NUL-terminate our output.
248 if (out_alloc == *out_len)
249 *out = tor_realloc(*out, out_alloc + 1);
250 (*out)[*out_len] = '\0';
251 }
252 rv = 0;
253 goto out;
254
255 err:
256 tor_free(*out);
257 *out_len = 0;
258 rv = -1;
259 goto out;
260
261 out:
262 tor_compress_free(stream);
263 return rv;
264}
265
266/** Given <b>in_len</b> bytes at <b>in</b>, compress them into a newly
267 * allocated buffer, using the method described in <b>method</b>. Store the
268 * compressed string in *<b>out</b>, and its length in *<b>out_len</b>.
269 * Return 0 on success, -1 on failure.
270 */
271int
272tor_compress(char **out, size_t *out_len,
273 const char *in, size_t in_len,
274 compress_method_t method)
275{
276 return tor_compress_impl(1, out, out_len, in, in_len, method,
277 BEST_COMPRESSION,
278 1, LOG_WARN);
279}
280
281/** Given zero or more compressed strings of total length <b>in_len</b> bytes
282 * at <b>in</b>, uncompress them into a newly allocated buffer, using the
283 * method described in <b>method</b>. Store the uncompressed string in
284 * *<b>out</b>, and its length in *<b>out_len</b>. Return 0 on success, -1 on
285 * failure.
286 *
287 * If any bytes are written to <b>out</b>, an extra byte NUL is always
288 * written at the end, but not counted in <b>out_len</b>. This is a
289 * safety feature to ensure that the output can be treated as a
290 * NUL-terminated string -- though of course, callers should check
291 * out_len anyway.
292 *
293 * If <b>complete_only</b> is true, we consider a truncated input as a
294 * failure; otherwise we decompress as much as we can. Warn about truncated
295 * or corrupt inputs at <b>protocol_warn_level</b>.
296 */
297int
298tor_uncompress(char **out, size_t *out_len,
299 const char *in, size_t in_len,
300 compress_method_t method,
301 int complete_only,
302 int protocol_warn_level)
303{
304 return tor_compress_impl(0, out, out_len, in, in_len, method,
305 BEST_COMPRESSION,
306 complete_only, protocol_warn_level);
307}
308
309/** Try to tell whether the <b>in_len</b>-byte string in <b>in</b> is likely
310 * to be compressed or not. If it is, return the likeliest compression method.
311 * Otherwise, return UNKNOWN_METHOD.
312 */
314detect_compression_method(const char *in, size_t in_len)
315{
316 if (in_len > 2 && fast_memeq(in, "\x1f\x8b", 2)) {
317 return GZIP_METHOD;
318 } else if (in_len > 2 && (in[0] & 0x0f) == 8 &&
319 (tor_ntohs(get_uint16(in)) % 31) == 0) {
320 return ZLIB_METHOD;
321 } else if (in_len > 2 &&
322 fast_memeq(in, "\x5d\x00\x00", 3)) {
323 return LZMA_METHOD;
324 } else if (in_len > 3 &&
325 fast_memeq(in, "\x28\xb5\x2f\xfd", 4)) {
326 return ZSTD_METHOD;
327 } else {
328 return UNKNOWN_METHOD;
329 }
330}
331
332/** Return 1 if a given <b>method</b> is supported; otherwise 0. */
333int
335{
336 switch (method) {
337 case GZIP_METHOD:
338 case ZLIB_METHOD:
340 case LZMA_METHOD:
342 case ZSTD_METHOD:
344 case NO_METHOD:
345 return 1;
346 case UNKNOWN_METHOD:
347 default:
348 return 0;
349 }
350}
351
352/**
353 * Return a bitmask of the supported compression types, where 1&lt;&lt;m is
354 * set in the bitmask if and only if compression with method <b>m</b> is
355 * supported.
356 */
357unsigned
359{
360 static unsigned supported = 0;
361 if (supported == 0) {
363 for (m = NO_METHOD; m <= UNKNOWN_METHOD; ++m) {
365 supported |= (1u << m);
366 }
367 }
368 }
369 return supported;
370}
371
372/** Table of compression method names. These should have an "x-" prefix,
373 * if they are not listed in the IANA content coding registry. */
374static const struct {
375 const char *name;
376 compress_method_t method;
378 { "gzip", GZIP_METHOD },
379 { "deflate", ZLIB_METHOD },
380 // We call this "x-tor-lzma" rather than "x-lzma", because we impose a
381 // lower maximum memory usage on the decoding side.
382 { "x-tor-lzma", LZMA_METHOD },
383 { "x-zstd" , ZSTD_METHOD },
384 { "identity", NO_METHOD },
385
386 /* Later entries in this table are not canonical; these are recognized but
387 * not emitted. */
388 { "x-gzip", GZIP_METHOD },
390
391/** Return the canonical string representation of the compression method
392 * <b>method</b>, or NULL if the method isn't recognized. */
393const char *
395{
396 unsigned i;
397 for (i = 0; i < ARRAY_LENGTH(compression_method_names); ++i) {
398 if (method == compression_method_names[i].method)
399 return compression_method_names[i].name;
400 }
401 return NULL;
402}
403
404/** Table of compression human readable method names. */
405static const struct {
406 compress_method_t method;
407 const char *name;
409 { NO_METHOD, "uncompressed" },
410 { GZIP_METHOD, "gzipped" },
411 { ZLIB_METHOD, "deflated" },
412 { LZMA_METHOD, "LZMA compressed" },
413 { ZSTD_METHOD, "Zstandard compressed" },
414 { UNKNOWN_METHOD, "unknown encoding" },
416
417/** Return a human readable string representation of the compression method
418 * <b>method</b>, or NULL if the method isn't recognized. */
419const char *
421{
422 unsigned i;
423 for (i = 0; i < ARRAY_LENGTH(compression_method_human_names); ++i) {
424 if (method == compression_method_human_names[i].method)
425 return compression_method_human_names[i].name;
426 }
427 return NULL;
428}
429
430/** Return the compression method represented by the string <b>name</b>, or
431 * UNKNOWN_METHOD if the string isn't recognized. */
434{
435 unsigned i;
436 for (i = 0; i < ARRAY_LENGTH(compression_method_names); ++i) {
437 if (!strcmp(compression_method_names[i].name, name))
438 return compression_method_names[i].method;
439 }
440 return UNKNOWN_METHOD;
441}
442
443/** Return a string representation of the version of the library providing the
444 * compression method given in <b>method</b>. Returns NULL if <b>method</b> is
445 * unknown or unsupported. */
446const char *
448{
449 switch (method) {
450 case GZIP_METHOD:
451 case ZLIB_METHOD:
453 case LZMA_METHOD:
455 case ZSTD_METHOD:
457 case NO_METHOD:
458 case UNKNOWN_METHOD:
459 default:
460 return NULL;
461 }
462}
463
464/** Return a string representation of the version of the library, found at
465 * compile time, providing the compression method given in <b>method</b>.
466 * Returns NULL if <b>method</b> is unknown or unsupported. */
467const char *
469{
470 switch (method) {
471 case GZIP_METHOD:
472 case ZLIB_METHOD:
474 case LZMA_METHOD:
476 case ZSTD_METHOD:
478 case NO_METHOD:
479 case UNKNOWN_METHOD:
480 default:
481 return NULL;
482 }
483}
484
485/** Return the approximate number of bytes allocated for all
486 * supported compression schemas. */
487size_t
495
496/** Internal state for an incremental compression/decompression. The body of
497 * this struct is not exposed. */
499 compress_method_t method; /**< The compression method. */
500
501 union {
502 tor_zlib_compress_state_t *zlib_state;
503 tor_lzma_compress_state_t *lzma_state;
504 tor_zstd_compress_state_t *zstd_state;
505 } u; /**< Compression backend state. */
506};
507
508/** Construct and return a tor_compress_state_t object using <b>method</b>. If
509 * <b>compress</b>, it's for compression; otherwise it's for decompression. */
512 compression_level_t compression_level)
513{
515
516 state = tor_malloc_zero(sizeof(tor_compress_state_t));
517 state->method = method;
518
519 switch (method) {
520 case GZIP_METHOD:
521 case ZLIB_METHOD: {
522 tor_zlib_compress_state_t *zlib_state =
523 tor_zlib_compress_new(compress, method, compression_level);
524
525 if (zlib_state == NULL)
526 goto err;
527
528 state->u.zlib_state = zlib_state;
529 break;
530 }
531 case LZMA_METHOD: {
532 tor_lzma_compress_state_t *lzma_state =
533 tor_lzma_compress_new(compress, method, compression_level);
534
535 if (lzma_state == NULL)
536 goto err;
537
538 state->u.lzma_state = lzma_state;
539 break;
540 }
541 case ZSTD_METHOD: {
542 tor_zstd_compress_state_t *zstd_state =
543 tor_zstd_compress_new(compress, method, compression_level);
544
545 if (zstd_state == NULL)
546 goto err;
547
548 state->u.zstd_state = zstd_state;
549 break;
550 }
551 case NO_METHOD: {
552 break;
553 }
554 case UNKNOWN_METHOD:
555 goto err;
556 }
557
559 sizeof(tor_compress_state_t));
560 return state;
561
562 err:
563 tor_free(state);
564 return NULL;
565}
566
567/** Compress/decompress some bytes using <b>state</b>. Read up to
568 * *<b>in_len</b> bytes from *<b>in</b>, and write up to *<b>out_len</b> bytes
569 * to *<b>out</b>, adjusting the values as we go. If <b>finish</b> is true,
570 * we've reached the end of the input.
571 *
572 * Return TOR_COMPRESS_DONE if we've finished the entire
573 * compression/decompression.
574 * Return TOR_COMPRESS_OK if we're processed everything from the input.
575 * Return TOR_COMPRESS_BUFFER_FULL if we're out of space on <b>out</b>.
576 * Return TOR_COMPRESS_ERROR if the stream is corrupt.
577 */
580 char **out, size_t *out_len,
581 const char **in, size_t *in_len,
582 int finish)
583{
584 tor_assert(state != NULL);
585 const size_t in_len_orig = *in_len;
586 const size_t out_len_orig = *out_len;
588
589 if (*out_len == 0 && (*in_len > 0 || finish)) {
590 // If we still have input data, but no space for output data, we might as
591 // well return early and let the caller do the reallocation of the out
592 // variable.
593 return TOR_COMPRESS_BUFFER_FULL;
594 }
595
596 switch (state->method) {
597 case GZIP_METHOD:
598 case ZLIB_METHOD:
599 rv = tor_zlib_compress_process(state->u.zlib_state,
600 out, out_len, in, in_len,
601 finish);
602 break;
603 case LZMA_METHOD:
604 rv = tor_lzma_compress_process(state->u.lzma_state,
605 out, out_len, in, in_len,
606 finish);
607 break;
608 case ZSTD_METHOD:
609 rv = tor_zstd_compress_process(state->u.zstd_state,
610 out, out_len, in, in_len,
611 finish);
612 break;
613 case NO_METHOD:
614 rv = tor_cnone_compress_process(out, out_len, in, in_len,
615 finish);
616 break;
617 default:
618 case UNKNOWN_METHOD:
619 goto err;
620 }
621 if (BUG((rv == TOR_COMPRESS_OK) &&
622 *in_len == in_len_orig &&
623 *out_len == out_len_orig)) {
624 log_warn(LD_GENERAL,
625 "More info on the bug: method == %s, finish == %d, "
626 " *in_len == in_len_orig == %lu, "
627 "*out_len == out_len_orig == %lu",
629 (unsigned long)in_len_orig, (unsigned long)out_len_orig);
630 return TOR_COMPRESS_ERROR;
631 }
632
633 return rv;
634 err:
635 return TOR_COMPRESS_ERROR;
636}
637
638/** Deallocate <b>state</b>. */
639void
641{
642 if (state == NULL)
643 return;
644
645 switch (state->method) {
646 case GZIP_METHOD:
647 case ZLIB_METHOD:
648 tor_zlib_compress_free(state->u.zlib_state);
649 break;
650 case LZMA_METHOD:
651 tor_lzma_compress_free(state->u.lzma_state);
652 break;
653 case ZSTD_METHOD:
654 tor_zstd_compress_free(state->u.zstd_state);
655 break;
656 case NO_METHOD:
657 break;
658 case UNKNOWN_METHOD:
659 break;
660 }
661
663 sizeof(tor_compress_state_t));
664 tor_free(state);
665}
666
667/** Return the approximate number of bytes allocated for <b>state</b>. */
668size_t
670{
671 tor_assert(state != NULL);
672
673 size_t size = sizeof(tor_compress_state_t);
674
675 switch (state->method) {
676 case GZIP_METHOD:
677 case ZLIB_METHOD:
678 size += tor_zlib_compress_state_size(state->u.zlib_state);
679 break;
680 case LZMA_METHOD:
681 size += tor_lzma_compress_state_size(state->u.lzma_state);
682 break;
683 case ZSTD_METHOD:
684 size += tor_zstd_compress_state_size(state->u.zstd_state);
685 break;
686 case NO_METHOD:
687 case UNKNOWN_METHOD:
688 break;
689 }
690
691 return size;
692}
693
694/** Initialize all compression modules. */
695int
697{
699
703
704 return 0;
705}
706
707/** Warn if we had any problems while setting up our compression libraries.
708 *
709 * (This isn't part of tor_compress_init, since the logs aren't set up yet.)
710 */
711void
713{
714 // XXXX can we move this into tor_compress_init() after all? log.c queues
715 // XXXX log messages at startup.
717}
718
719static int
720subsys_compress_initialize(void)
721{
722 return tor_compress_init();
723}
724
725const subsys_fns_t sys_compress = {
726 .name = "compress",
728 .supported = true,
729 .level = -55,
730 .initialize = subsys_compress_initialize,
731};
Inline functions for reading and writing multibyte values from the middle of strings,...
static uint16_t get_uint16(const void *cp)
Definition bytes.h:42
static uint16_t tor_ntohs(uint16_t a)
Definition bytes.h:154
Macro definitions for MIN, MAX, and CLAMP.
#define ARRAY_LENGTH(x)
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)
Definition compress.c:447
int tor_compress_init(void)
Definition compress.c:696
static const struct @29 compression_method_human_names[]
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)
Definition compress.c:579
int tor_compress_supports_method(compress_method_t method)
Definition compress.c:334
static size_t guess_compress_size(int compress, compress_method_t method, compression_level_t compression_level, size_t in_len)
Definition compress.c:88
compress_method_t compression_method_get_by_name(const char *name)
Definition compress.c:433
int tor_compress_is_compression_bomb(size_t size_in, size_t size_out)
Definition compress.c:67
const char * tor_compress_header_version_str(compress_method_t method)
Definition compress.c:468
static atomic_counter_t total_compress_allocation
Definition compress.c:41
void tor_compress_free_(tor_compress_state_t *state)
Definition compress.c:640
unsigned tor_compress_get_supported_method_bitmask(void)
Definition compress.c:358
size_t tor_compress_state_size(const tor_compress_state_t *state)
Definition compress.c:669
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)
Definition compress.c:114
void tor_compress_log_init_warnings(void)
Definition compress.c:712
int tor_compress(char **out, size_t *out_len, const char *in, size_t in_len, compress_method_t method)
Definition compress.c:272
compress_method_t detect_compression_method(const char *in, size_t in_len)
Definition compress.c:314
tor_compress_state_t * tor_compress_new(int compress, compress_method_t method, compression_level_t compression_level)
Definition compress.c:511
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)
Definition compress.c:298
const char * compression_method_get_name(compress_method_t method)
Definition compress.c:394
size_t tor_compress_get_total_allocation(void)
Definition compress.c:488
static const struct @28 compression_method_names[]
const char * compression_method_get_human_name(compress_method_t method)
Definition compress.c:420
Headers for compress.c.
tor_compress_output_t
Definition compress.h:68
compress_method_t
Definition compress.h:21
compression_level_t
Definition compress.h:35
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)
void tor_lzma_init(void)
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)
void tor_zlib_init(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)
void tor_zstd_init(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)
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.
const char * name
Definition config.c:2472
Headers for di_ops.c.
#define fast_memeq(a, b, c)
Definition di_ops.h:35
Headers for log.c.
#define log_fn(severity, domain, args,...)
Definition log.h:283
#define LD_PROTOCOL
Definition log.h:72
#define LD_BUG
Definition log.h:86
#define LD_GENERAL
Definition log.h:62
#define LD_DIR
Definition log.h:88
#define LOG_WARN
Definition log.h:53
Headers for util_malloc.c.
#define tor_free(p)
Definition malloc.h:56
compress_method_t method
Definition compress.c:499
union tor_compress_state_t::@30 u
Types used to declare a subsystem.
#define SUBSYS_DECLARE_LOCATION()
Definition subsys.h:211
#define MOCK_IMPL(rv, funcname, arglist)
Header for threads.c.
Integer definitions used throughout Tor.
#define SIZE_T_CEILING
Definition torint.h:126
Macros to manage assertions, fatal and non-fatal.
#define tor_assert_nonfatal_unreached()
Definition util_bug.h:177
#define tor_assert(expr)
Definition util_bug.h:103