28#define MEMORY_LIMIT (16 * 1024 * 1024)
40 case BEST_COMPRESSION:
41 case HIGH_COMPRESSION:
return 6;
42 case MEDIUM_COMPRESSION:
return 4;
43 case LOW_COMPRESSION:
return 2;
49lzma_error_str(lzma_ret error)
53 return "Operation completed successfully";
55 return "End of stream";
57 return "Input stream lacks integrity check";
58 case LZMA_UNSUPPORTED_CHECK:
59 return "Unable to calculate integrity check";
61 return "Integrity check available";
63 return "Unable to allocate memory";
64 case LZMA_MEMLIMIT_ERROR:
65 return "Memory limit reached";
66 case LZMA_FORMAT_ERROR:
67 return "Unknown file format";
68 case LZMA_OPTIONS_ERROR:
69 return "Unsupported options";
71 return "Corrupt input data";
73 return "Unable to progress";
75 return "Programming error";
76#if LZMA_VERSION >= 50030010
77 case LZMA_SEEK_NEEDED:
82#if LZMA_VERSION >= 50030020
83 case LZMA_RET_INTERNAL1:
84 case LZMA_RET_INTERNAL2:
85 case LZMA_RET_INTERNAL3:
86 case LZMA_RET_INTERNAL4:
87 case LZMA_RET_INTERNAL5:
88 case LZMA_RET_INTERNAL6:
89 case LZMA_RET_INTERNAL7:
90 case LZMA_RET_INTERNAL8:
94 return "Unknown LZMA error";
116 return lzma_version_string();
128 return LZMA_VERSION_STRING;
158 uint64_t memory_usage;
161 memory_usage = lzma_easy_encoder_memusage(
memory_level(level));
163 memory_usage = lzma_easy_decoder_memusage(
memory_level(level));
165 if (memory_usage == UINT64_MAX) {
167 log_warn(
LD_GENERAL,
"Unsupported compression level passed to LZMA %s",
168 compress ?
"encoder" :
"decoder");
174 memory_usage = SIZE_MAX;
178 return (
size_t)memory_usage;
200 lzma_options_lzma stream_options;
207 result->
allocation = tor_lzma_state_size_precalc(compress, level);
212 retval = lzma_alone_encoder(&result->stream, &stream_options);
214 if (retval != LZMA_OK) {
216 log_warn(
LD_GENERAL,
"Error from LZMA encoder: %s (%u).",
217 lzma_error_str(retval), retval);
222 retval = lzma_alone_decoder(&result->stream,
MEMORY_LIMIT);
224 if (retval != LZMA_OK) {
226 log_warn(
LD_GENERAL,
"Error from LZMA decoder: %s (%u).",
227 lzma_error_str(retval), retval);
263 char **out,
size_t *out_len,
264 const char **in,
size_t *in_len,
275 state->stream.next_in = (
unsigned char *)*in;
276 state->stream.avail_in = *in_len;
277 state->stream.next_out = (
unsigned char *)*out;
278 state->stream.avail_out = *out_len;
280 action = finish ? LZMA_FINISH : LZMA_RUN;
282 retval = lzma_code(&state->stream, action);
284 state->
input_so_far += state->stream.next_in - ((
unsigned char *)*in);
285 state->
output_so_far += state->stream.next_out - ((
unsigned char *)*out);
287 *out = (
char *)state->stream.next_out;
288 *out_len = state->stream.avail_out;
289 *in = (
const char *)state->stream.next_in;
290 *in_len = state->stream.avail_in;
295 log_warn(
LD_DIR,
"Possible compression bomb; abandoning stream.");
296 return TOR_COMPRESS_ERROR;
301 if (state->stream.avail_out == 0 || finish)
302 return TOR_COMPRESS_BUFFER_FULL;
304 return TOR_COMPRESS_OK;
307 if (state->stream.avail_in == 0 && !finish)
308 return TOR_COMPRESS_OK;
310 return TOR_COMPRESS_BUFFER_FULL;
312 case LZMA_STREAM_END:
313 return TOR_COMPRESS_DONE;
318 case LZMA_UNSUPPORTED_CHECK:
321 case LZMA_MEMLIMIT_ERROR:
322 case LZMA_FORMAT_ERROR:
323 case LZMA_OPTIONS_ERROR:
324 case LZMA_DATA_ERROR:
325 case LZMA_PROG_ERROR:
326#if LZMA_VERSION >= 50030010
327 case LZMA_SEEK_NEEDED:
329#if LZMA_VERSION >= 50030020
330 case LZMA_RET_INTERNAL1:
331 case LZMA_RET_INTERNAL2:
332 case LZMA_RET_INTERNAL3:
333 case LZMA_RET_INTERNAL4:
334 case LZMA_RET_INTERNAL5:
335 case LZMA_RET_INTERNAL6:
336 case LZMA_RET_INTERNAL7:
337 case LZMA_RET_INTERNAL8:
340 log_warn(
LD_GENERAL,
"LZMA %s didn't finish: %s.",
341 state->
compress ?
"compression" :
"decompression",
342 lzma_error_str(retval));
343 return TOR_COMPRESS_ERROR;
352 return TOR_COMPRESS_ERROR;
366 lzma_end(&state->stream);
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)
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)
static atomic_counter_t total_lzma_allocation
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)
void tor_lzma_compress_free_(tor_lzma_compress_state_t *state)
Header for compress_lzma.c.
static int memory_level(compression_level_t level)
Headers for util_malloc.c.
Macros to manage assertions, fatal and non-fatal.