23 #ifdef ENABLE_ZSTD_ADVANCED_APIS
27 #define ZSTD_STATIC_LINKING_ONLY
31 #ifdef HAVE_CFLAG_WUNUSED_CONST_VARIABLE
32 DISABLE_GCC_WARNING(
"-Wunused-const-variable")
35 #ifdef HAVE_CFLAG_WUNUSED_CONST_VARIABLE
36 ENABLE_GCC_WARNING(
"-Wunused-const-variable")
50 case BEST_COMPRESSION:
51 case HIGH_COMPRESSION:
return 9;
52 case MEDIUM_COMPRESSION:
return 3;
53 case LOW_COMPRESSION:
return 1;
72 tor_zstd_format_version(
char *buf,
size_t buflen,
unsigned version_number)
76 version_number / 10000 % 100,
77 version_number / 100 % 100,
78 version_number % 100);
82 #define VERSION_STR_MAX_LEN 16
90 static char version_str[VERSION_STR_MAX_LEN];
92 tor_zstd_format_version(version_str,
sizeof(version_str),
93 ZSTD_versionNumber());
107 return ZSTD_VERSION_STRING;
113 #ifdef TOR_UNIT_TESTS
114 static int static_apis_disable_for_testing = 0;
121 #if defined(ZSTD_STATIC_LINKING_ONLY) && defined(HAVE_ZSTD)
122 #ifdef TOR_UNIT_TESTS
123 if (static_apis_disable_for_testing) {
127 return (ZSTD_VERSION_NUMBER == ZSTD_versionNumber());
139 ZSTD_CStream *compress_stream;
141 ZSTD_DStream *decompress_stream;
164 tor_zstd_state_size_precalc_fake(
int compress,
int preset)
198 memory_usage += (preset * 1024 * 1024) - (512 * 1024);
201 memory_usage += 128 * 1024;
203 memory_usage += 2048 * 1024;
212 memory_usage += 150 * 1024;
225 tor_zstd_state_size_precalc(
int compress,
int preset)
227 #ifdef ZSTD_STATIC_LINKING_ONLY
230 #ifdef HAVE_ZSTD_ESTIMATECSTREAMSIZE
231 return ZSTD_estimateCStreamSize(preset);
234 #ifdef HAVE_ZSTD_ESTIMATEDCTXSIZE
236 return ZSTD_estimateDCtxSize();
241 return tor_zstd_state_size_precalc_fake(compress, preset);
262 result->
allocation = tor_zstd_state_size_precalc(compress, preset);
265 result->u.compress_stream = ZSTD_createCStream();
267 if (result->u.compress_stream == NULL) {
269 log_warn(
LD_GENERAL,
"Error while creating Zstandard compression "
275 retval = ZSTD_initCStream(result->u.compress_stream, preset);
277 if (ZSTD_isError(retval)) {
279 log_warn(
LD_GENERAL,
"Zstandard stream initialization error: %s",
280 ZSTD_getErrorName(retval));
285 result->u.decompress_stream = ZSTD_createDStream();
287 if (result->u.decompress_stream == NULL) {
289 log_warn(
LD_GENERAL,
"Error while creating Zstandard decompression "
295 retval = ZSTD_initDStream(result->u.decompress_stream);
297 if (ZSTD_isError(retval)) {
299 log_warn(
LD_GENERAL,
"Zstandard stream initialization error: %s",
300 ZSTD_getErrorName(retval));
312 ZSTD_freeCStream(result->u.compress_stream);
314 ZSTD_freeDStream(result->u.decompress_stream);
342 char **out,
size_t *out_len,
343 const char **in,
size_t *in_len,
353 ZSTD_inBuffer input = { *in, *in_len, 0 };
354 ZSTD_outBuffer output = { *out, *out_len, 0 };
362 retval = ZSTD_compressStream(state->u.compress_stream,
367 retval = ZSTD_decompressStream(state->u.decompress_stream,
374 *out = (
char *)output.dst + output.pos;
375 *out_len = output.size - output.pos;
376 *in = (
char *)input.src + input.pos;
377 *in_len = input.size - input.pos;
382 log_warn(
LD_DIR,
"Possible compression bomb; abandoning stream.");
383 return TOR_COMPRESS_ERROR;
386 if (ZSTD_isError(retval)) {
387 log_warn(
LD_GENERAL,
"Zstandard %s didn't finish: %s.",
388 state->
compress ?
"compression" :
"decompression",
389 ZSTD_getErrorName(retval));
390 return TOR_COMPRESS_ERROR;
394 retval = ZSTD_flushStream(state->u.compress_stream, &output);
396 *out = (
char *)output.dst + output.pos;
397 *out_len = output.size - output.pos;
399 if (ZSTD_isError(retval)) {
400 log_warn(
LD_GENERAL,
"Zstandard compression unable to flush: %s.",
401 ZSTD_getErrorName(retval));
402 return TOR_COMPRESS_ERROR;
408 return TOR_COMPRESS_BUFFER_FULL;
415 return TOR_COMPRESS_OK;
420 return TOR_COMPRESS_OK;
423 retval = ZSTD_endStream(state->u.compress_stream, &output);
425 *out = (
char *)output.dst + output.pos;
426 *out_len = output.size - output.pos;
428 if (ZSTD_isError(retval)) {
429 log_warn(
LD_GENERAL,
"Zstandard compression unable to write "
431 ZSTD_getErrorName(retval));
432 return TOR_COMPRESS_ERROR;
438 return TOR_COMPRESS_BUFFER_FULL;
440 return TOR_COMPRESS_DONE;
445 tor_assert_nonfatal(!ZSTD_isError(retval));
448 return TOR_COMPRESS_DONE;
451 else if (*in_len > 0)
452 return TOR_COMPRESS_BUFFER_FULL;
454 return TOR_COMPRESS_OK;
465 return TOR_COMPRESS_ERROR;
480 ZSTD_freeCStream(state->u.compress_stream);
482 ZSTD_freeDStream(state->u.decompress_stream);
516 #if defined(HAVE_ZSTD) && defined(ENABLE_ZSTD_ADVANCED_APIS)
518 char header_version[VERSION_STR_MAX_LEN];
519 char runtime_version[VERSION_STR_MAX_LEN];
520 tor_zstd_format_version(header_version,
sizeof(header_version),
521 ZSTD_VERSION_NUMBER);
522 tor_zstd_format_version(runtime_version,
sizeof(runtime_version),
523 ZSTD_versionNumber());
526 "Tor was compiled with zstd %s, but is running with zstd %s. "
527 "For safety, we'll avoid using advanced zstd functionality.",
528 header_version, runtime_version);
533 #ifdef TOR_UNIT_TESTS
537 tor_zstd_set_static_apis_disabled_for_testing(
int disabled)
539 static_apis_disable_for_testing = disabled;
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_is_compression_bomb(size_t size_in, size_t size_out)
static int memory_level(compression_level_t level)
void tor_zstd_compress_free_(tor_zstd_compress_state_t *state)
int tor_zstd_method_supported(void)
static atomic_counter_t total_zstd_allocation
int tor_zstd_can_use_static_apis(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.
int tor_snprintf(char *str, size_t size, const char *format,...)
Macros to manage assertions, fatal and non-fatal.