diff options
Diffstat (limited to 'src/Common/libzip/zip_algorithm_deflate.c')
-rw-r--r-- | src/Common/libzip/zip_algorithm_deflate.c | 119 |
1 files changed, 74 insertions, 45 deletions
diff --git a/src/Common/libzip/zip_algorithm_deflate.c b/src/Common/libzip/zip_algorithm_deflate.c index ba5ad439..3c85e204 100644 --- a/src/Common/libzip/zip_algorithm_deflate.c +++ b/src/Common/libzip/zip_algorithm_deflate.c @@ -1,9 +1,9 @@ /* zip_algorithm_deflate.c -- deflate (de)compression routines - Copyright (C) 2017-2018 Dieter Baron and Thomas Klausner + Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at <libzip@nih.at> + The authors can be contacted at <info@libzip.org> Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -40,26 +40,44 @@ struct ctx { zip_error_t *error; bool compress; - int compression_flags; + int level; + int mem_level; bool end_of_input; z_stream zstr; }; +static zip_uint64_t +maximum_compressed_size(zip_uint64_t uncompressed_size) { + /* max deflate size increase: size + ceil(size/16k)*5+6 */ + + zip_uint64_t compressed_size = uncompressed_size + (uncompressed_size + 16383) / 16384 * 5 + 6; + + if (compressed_size < uncompressed_size) { + return ZIP_UINT64_MAX; + } + return compressed_size; +} + + static void * -allocate(bool compress, int compression_flags, zip_error_t *error) { +allocate(bool compress, zip_uint32_t compression_flags, zip_error_t *error) { struct ctx *ctx; if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) { - return NULL; + zip_error_set(error, ZIP_ET_SYS, errno); + return NULL; } ctx->error = error; ctx->compress = compress; - ctx->compression_flags = compression_flags; - if (ctx->compression_flags < 1 || ctx->compression_flags > 9) { - ctx->compression_flags = Z_BEST_COMPRESSION; + if (compression_flags >= 1 && compression_flags <= 9) { + ctx->level = (int)compression_flags; + } + else { + ctx->level = Z_BEST_COMPRESSION; } + ctx->mem_level = compression_flags == TORRENTZIP_COMPRESSION_FLAGS ? TORRENTZIP_MEM_LEVEL : MAX_MEM_LEVEL; ctx->end_of_input = false; ctx->zstr.zalloc = Z_NULL; @@ -71,13 +89,15 @@ allocate(bool compress, int compression_flags, zip_error_t *error) { static void * -compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) { +compress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) { + (void)method; return allocate(true, compression_flags, error); } static void * -decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) { +decompress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) { + (void)method; return allocate(false, compression_flags, error); } @@ -90,45 +110,48 @@ deallocate(void *ud) { } -static int -compression_flags(void *ud) { +static zip_uint16_t +general_purpose_bit_flags(void *ud) { struct ctx *ctx = (struct ctx *)ud; if (!ctx->compress) { - return 0; + return 0; } - if (ctx->compression_flags < 3) { - return 2; + if (ctx->level < 3) { + return 2 << 1; } - else if (ctx->compression_flags > 7) { - return 1; + else if (ctx->level > 7) { + return 1 << 1; } return 0; } static bool -start(void *ud) { +start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) { struct ctx *ctx = (struct ctx *)ud; int ret; + (void)st; + (void)attributes; + ctx->zstr.avail_in = 0; ctx->zstr.next_in = NULL; ctx->zstr.avail_out = 0; ctx->zstr.next_out = NULL; if (ctx->compress) { - /* negative value to tell zlib not to write a header */ - ret = deflateInit2(&ctx->zstr, ctx->compression_flags, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); + /* negative value to tell zlib not to write a header */ + ret = deflateInit2(&ctx->zstr, ctx->level, Z_DEFLATED, -MAX_WBITS, ctx->mem_level, Z_DEFAULT_STRATEGY); } else { - ret = inflateInit2(&ctx->zstr, -MAX_WBITS); + ret = inflateInit2(&ctx->zstr, -MAX_WBITS); } if (ret != Z_OK) { - zip_error_set(ctx->error, ZIP_ER_ZLIB, ret); - return false; + zip_error_set(ctx->error, ZIP_ER_ZLIB, ret); + return false; } @@ -142,15 +165,15 @@ end(void *ud) { int err; if (ctx->compress) { - err = deflateEnd(&ctx->zstr); + err = deflateEnd(&ctx->zstr); } else { - err = inflateEnd(&ctx->zstr); + err = inflateEnd(&ctx->zstr); } if (err != Z_OK) { - zip_error_set(ctx->error, ZIP_ER_ZLIB, err); - return false; + zip_error_set(ctx->error, ZIP_ER_ZLIB, err); + return false; } return true; @@ -162,8 +185,8 @@ input(void *ud, zip_uint8_t *data, zip_uint64_t length) { struct ctx *ctx = (struct ctx *)ud; if (length > UINT_MAX || ctx->zstr.avail_in > 0) { - zip_error_set(ctx->error, ZIP_ER_INVAL, 0); - return false; + zip_error_set(ctx->error, ZIP_ER_INVAL, 0); + return false; } ctx->zstr.avail_in = (uInt)length; @@ -184,47 +207,51 @@ end_of_input(void *ud) { static zip_compression_status_t process(void *ud, zip_uint8_t *data, zip_uint64_t *length) { struct ctx *ctx = (struct ctx *)ud; + uInt avail_out; int ret; - ctx->zstr.avail_out = (uInt)ZIP_MIN(UINT_MAX, *length); + avail_out = (uInt)ZIP_MIN(UINT_MAX, *length); + ctx->zstr.avail_out = avail_out; ctx->zstr.next_out = (Bytef *)data; if (ctx->compress) { - ret = deflate(&ctx->zstr, ctx->end_of_input ? Z_FINISH : 0); + ret = deflate(&ctx->zstr, ctx->end_of_input ? Z_FINISH : 0); } else { - ret = inflate(&ctx->zstr, Z_SYNC_FLUSH); + ret = inflate(&ctx->zstr, Z_SYNC_FLUSH); } - *length = *length - ctx->zstr.avail_out; + *length = avail_out - ctx->zstr.avail_out; switch (ret) { case Z_OK: - return ZIP_COMPRESSION_OK; + return ZIP_COMPRESSION_OK; case Z_STREAM_END: - return ZIP_COMPRESSION_END; + return ZIP_COMPRESSION_END; case Z_BUF_ERROR: - if (ctx->zstr.avail_in == 0) { - return ZIP_COMPRESSION_NEED_DATA; - } + if (ctx->zstr.avail_in == 0) { + return ZIP_COMPRESSION_NEED_DATA; + } - /* fallthrough */ + /* fallthrough */ default: - zip_error_set(ctx->error, ZIP_ER_ZLIB, ret); - return ZIP_COMPRESSION_ERROR; + zip_error_set(ctx->error, ZIP_ER_ZLIB, ret); + return ZIP_COMPRESSION_ERROR; } } -// clang-format off +/* clang-format off */ zip_compression_algorithm_t zip_algorithm_deflate_compress = { + maximum_compressed_size, compress_allocate, deallocate, - compression_flags, + general_purpose_bit_flags, + 20, start, end, input, @@ -234,9 +261,11 @@ zip_compression_algorithm_t zip_algorithm_deflate_compress = { zip_compression_algorithm_t zip_algorithm_deflate_decompress = { + maximum_compressed_size, decompress_allocate, deallocate, - compression_flags, + general_purpose_bit_flags, + 20, start, end, input, @@ -244,4 +273,4 @@ zip_compression_algorithm_t zip_algorithm_deflate_decompress = { process }; -// clang-format on +/* clang-format on */ |