diff --git a/compat.h b/compat.h index a5cf728..47c28fd 100644 --- a/compat.h +++ b/compat.h @@ -3,7 +3,7 @@ /* compat.h -- compatibility defines. - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -94,7 +94,7 @@ typedef char bool; #if !defined(HAVE_FILENO) && defined(HAVE__FILENO) #define fileno _fileno #endif -#if defined(HAVE__SNPRINTF) +#if !defined(HAVE_SNPRINTF) && defined(HAVE__SNPRINTF) #define snprintf _snprintf #endif #if defined(HAVE__STRDUP) diff --git a/config_x32.h b/config_x32.h index 770c46f..e1a3ffe 100644 --- a/config_x32.h +++ b/config_x32.h @@ -29,13 +29,14 @@ /* #undef HAVE_GNUTLS */ /* #undef HAVE_LIBBZ2 */ /* #undef HAVE_LIBLZMA */ +/* #undef HAVE_LIBZSTD */ /* #undef HAVE_LOCALTIME_R */ /* #undef HAVE_MBEDTLS */ /* #undef HAVE_MKSTEMP */ /* #undef HAVE_NULLABLE */ /* #undef HAVE_OPENSSL */ #define HAVE_SETMODE -/* #undef HAVE_SNPRINTF */ +/* #define HAVE_SNPRINTF */ /* #undef HAVE_STRCASECMP */ #define HAVE_STRDUP #define HAVE_STRICMP @@ -57,6 +58,6 @@ #define HAVE_SHARED /* END DEFINES */ #define PACKAGE "libzip" -#define VERSION "1.7.3" +#define VERSION "1.8.0" #endif /* HAD_CONFIG_H */ diff --git a/config_x64.h b/config_x64.h index b034d1b..a5fe80a 100644 --- a/config_x64.h +++ b/config_x64.h @@ -10,7 +10,7 @@ #define HAVE__FDOPEN #define HAVE__FILENO #define HAVE__SETMODE -#undef HAVE__SNPRINTF +#define HAVE__SNPRINTF #define HAVE__STRDUP #define HAVE__STRICMP #define HAVE__STRTOI64 @@ -29,13 +29,14 @@ /* #undef HAVE_GNUTLS */ /* #undef HAVE_LIBBZ2 */ /* #undef HAVE_LIBLZMA */ +/* #undef HAVE_LIBZSTD */ /* #undef HAVE_LOCALTIME_R */ /* #undef HAVE_MBEDTLS */ /* #undef HAVE_MKSTEMP */ /* #undef HAVE_NULLABLE */ /* #undef HAVE_OPENSSL */ #define HAVE_SETMODE -/* #undef HAVE_SNPRINTF */ +#define HAVE_SNPRINTF /* #undef HAVE_STRCASECMP */ #define HAVE_STRDUP #define HAVE_STRICMP @@ -57,6 +58,6 @@ #define HAVE_SHARED /* END DEFINES */ #define PACKAGE "libzip" -#define VERSION "1.7.3" +#define VERSION "1.8.0" #endif /* HAD_CONFIG_H */ diff --git a/libzip.rc b/libzip.rc index 35917e6..368cb5d 100644 --- a/libzip.rc +++ b/libzip.rc @@ -56,8 +56,8 @@ VS_VERSION_INFO$(NDEB64) VERSIONINFO #else VS_VERSION_INFO VERSIONINFO #endif - FILEVERSION 1,7,3,0 - PRODUCTVERSION 1,7,3,0 + FILEVERSION 1,8,0,0 + PRODUCTVERSION 1,8,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -73,12 +73,12 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "Libzip Release Version" - VALUE "FileVersion", "1.7.3.0" + VALUE "FileVersion", "1.8.0.0" VALUE "InternalName", "zipR64.dll" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "zipR64.dll" VALUE "ProductName", "libzip" - VALUE "ProductVersion", "1.7.3.0" + VALUE "ProductVersion", "1.8.0.0" END END BLOCK "VarFileInfo" @@ -94,8 +94,8 @@ VS_VERSION_INFO$(NDEB32) VERSIONINFO #else VS_VERSION_INFO VERSIONINFO #endif - FILEVERSION 1,7,3,0 - PRODUCTVERSION 1,7,3,0 + FILEVERSION 1,8,0,0 + PRODUCTVERSION 1,8,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -111,11 +111,11 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "Libzip Release Version" - VALUE "FileVersion", "1.7.3.0" + VALUE "FileVersion", "1.8.0.0" VALUE "InternalName", "zipR32.dll" VALUE "OriginalFilename", "zipR32.dll" VALUE "ProductName", "libzip" - VALUE "ProductVersion", "1.7.3.0" + VALUE "ProductVersion", "1.8.0.0" END END BLOCK "VarFileInfo" @@ -131,8 +131,8 @@ VS_VERSION_INFO$(_DEB64) VERSIONINFO #else VS_VERSION_INFO VERSIONINFO #endif - FILEVERSION 1,7,3,0 - PRODUCTVERSION 1,7,3,0 + FILEVERSION 1,8,0,0 + PRODUCTVERSION 1,8,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -148,11 +148,11 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "Libzip Debug Version" - VALUE "FileVersion", "1.7.3.0" + VALUE "FileVersion", "1.8.0.0" VALUE "InternalName", "zipD64.dll" VALUE "OriginalFilename", "zipD64.dll" VALUE "ProductName", "libzip" - VALUE "ProductVersion", "1.7.3.0" + VALUE "ProductVersion", "1.8.0.0" END END BLOCK "VarFileInfo" @@ -168,8 +168,8 @@ VS_VERSION_INFO$(_DEB32) VERSIONINFO #else VS_VERSION_INFO VERSIONINFO #endif - FILEVERSION 1,7,3,0 - PRODUCTVERSION 1,7,3,0 + FILEVERSION 1,8,0,0 + PRODUCTVERSION 1,8,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -185,11 +185,11 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "Libzip Debug Version" - VALUE "FileVersion", "1.7.3.0" + VALUE "FileVersion", "1.8.0.0" VALUE "InternalName", "zipD32.dll" VALUE "OriginalFilename", "zipD32.dll" VALUE "ProductName", "libzip" - VALUE "ProductVersion", "1.7.3.0" + VALUE "ProductVersion", "1.8.0.0" END END BLOCK "VarFileInfo" diff --git a/zip_add.c b/zip_add.c index 1954235..dd6dcbc 100644 --- a/zip_add.c +++ b/zip_add.c @@ -1,6 +1,6 @@ /* zip_add.c -- add file via callback function - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -38,9 +38,9 @@ /* NOTE: Return type is signed so we can return -1 on error. - The index can not be larger than ZIP_INT64_MAX since the size - of the central directory cannot be larger than - ZIP_UINT64_MAX, and each entry is larger than 2 bytes. + The index can not be larger than ZIP_INT64_MAX since the size + of the central directory cannot be larger than + ZIP_UINT64_MAX, and each entry is larger than 2 bytes. */ ZIP_EXTERN zip_int64_t diff --git a/zip_add_dir.c b/zip_add_dir.c index 88fcf53..41de94b 100644 --- a/zip_add_dir.c +++ b/zip_add_dir.c @@ -1,6 +1,6 @@ /* zip_add_dir.c -- add directory - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at diff --git a/zip_add_entry.c b/zip_add_entry.c index f52e0b5..6f3c162 100644 --- a/zip_add_entry.c +++ b/zip_add_entry.c @@ -1,6 +1,6 @@ /* zip_add_entry.c -- create and init struct zip_entry - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -44,32 +44,32 @@ _zip_add_entry(zip_t *za) { zip_uint64_t idx; if (za->nentry + 1 >= za->nentry_alloc) { - zip_entry_t *rentries; - zip_uint64_t nalloc = za->nentry_alloc; - zip_uint64_t additional_entries = 2 * nalloc; - zip_uint64_t realloc_size; + zip_entry_t *rentries; + zip_uint64_t nalloc = za->nentry_alloc; + zip_uint64_t additional_entries = 2 * nalloc; + zip_uint64_t realloc_size; - if (additional_entries < 16) { - additional_entries = 16; - } - else if (additional_entries > 1024) { - additional_entries = 1024; - } - /* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */ - nalloc += additional_entries; - realloc_size = sizeof(struct zip_entry) * (size_t)nalloc; + if (additional_entries < 16) { + additional_entries = 16; + } + else if (additional_entries > 1024) { + additional_entries = 1024; + } + /* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */ + nalloc += additional_entries; + realloc_size = sizeof(struct zip_entry) * (size_t)nalloc; - if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; - } - rentries = (zip_entry_t *)realloc(za->entry, sizeof(struct zip_entry) * (size_t)nalloc); - if (!rentries) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; - } - za->entry = rentries; - za->nentry_alloc = nalloc; + if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + rentries = (zip_entry_t *)realloc(za->entry, sizeof(struct zip_entry) * (size_t)nalloc); + if (!rentries) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + za->entry = rentries; + za->nentry_alloc = nalloc; } idx = za->nentry++; diff --git a/zip_algorithm_deflate.c b/zip_algorithm_deflate.c index d28a1ac..8707eec 100644 --- a/zip_algorithm_deflate.c +++ b/zip_algorithm_deflate.c @@ -1,6 +1,6 @@ /* zip_algorithm_deflate.c -- deflate (de)compression routines - Copyright (C) 2017-2019 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 @@ -46,20 +46,33 @@ struct ctx { }; +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) { struct ctx *ctx; if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) { - zip_error_set(error, ZIP_ET_SYS, errno); - 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; + ctx->compression_flags = Z_BEST_COMPRESSION; } ctx->end_of_input = false; @@ -96,21 +109,21 @@ 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 << 1; + return 2 << 1; } else if (ctx->compression_flags > 7) { - return 1 << 1; + 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; @@ -120,16 +133,16 @@ start(void *ud) { 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->compression_flags, Z_DEFLATED, -MAX_WBITS, MAX_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; } @@ -143,15 +156,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; @@ -163,8 +176,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; @@ -192,37 +205,38 @@ process(void *ud, zip_uint8_t *data, zip_uint64_t *length) { 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; 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 */ zip_compression_algorithm_t zip_algorithm_deflate_compress = { + maximum_compressed_size, compress_allocate, deallocate, general_purpose_bit_flags, @@ -236,6 +250,7 @@ zip_compression_algorithm_t zip_algorithm_deflate_compress = { zip_compression_algorithm_t zip_algorithm_deflate_decompress = { + maximum_compressed_size, decompress_allocate, deallocate, general_purpose_bit_flags, diff --git a/zip_buffer.c b/zip_buffer.c index 8c24b27..4e5783e 100644 --- a/zip_buffer.c +++ b/zip_buffer.c @@ -1,6 +1,6 @@ /* zip_buffer.c -- bounds checked access to memory buffer - Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -45,11 +45,11 @@ _zip_buffer_data(zip_buffer_t *buffer) { void _zip_buffer_free(zip_buffer_t *buffer) { if (buffer == NULL) { - return; + return; } if (buffer->free_data) { - free(buffer->data); + free(buffer->data); } free(buffer); @@ -69,7 +69,7 @@ _zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length) { data = _zip_buffer_peek(buffer, length); if (data != NULL) { - buffer->offset += length; + buffer->offset += length; } return data; @@ -81,7 +81,7 @@ _zip_buffer_get_16(zip_buffer_t *buffer) { zip_uint8_t *data = _zip_buffer_get(buffer, 2); if (data == NULL) { - return 0; + return 0; } return (zip_uint16_t)(data[0] + (data[1] << 8)); @@ -93,7 +93,7 @@ _zip_buffer_get_32(zip_buffer_t *buffer) { zip_uint8_t *data = _zip_buffer_get(buffer, 4); if (data == NULL) { - return 0; + return 0; } return ((((((zip_uint32_t)data[3] << 8) + data[2]) << 8) + data[1]) << 8) + data[0]; @@ -105,7 +105,7 @@ _zip_buffer_get_64(zip_buffer_t *buffer) { zip_uint8_t *data = _zip_buffer_get(buffer, 8); if (data == NULL) { - return 0; + return 0; } return ((zip_uint64_t)data[7] << 56) + ((zip_uint64_t)data[6] << 48) + ((zip_uint64_t)data[5] << 40) + ((zip_uint64_t)data[4] << 32) + ((zip_uint64_t)data[3] << 24) + ((zip_uint64_t)data[2] << 16) + ((zip_uint64_t)data[1] << 8) + (zip_uint64_t)data[0]; @@ -117,7 +117,7 @@ _zip_buffer_get_8(zip_buffer_t *buffer) { zip_uint8_t *data = _zip_buffer_get(buffer, 1); if (data == NULL) { - return 0; + return 0; } return data[0]; @@ -133,7 +133,7 @@ _zip_buffer_left(zip_buffer_t *buffer) { zip_uint64_t _zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) { if (_zip_buffer_left(buffer) < length) { - length = _zip_buffer_left(buffer); + length = _zip_buffer_left(buffer); } memcpy(data, _zip_buffer_get(buffer, length), length); @@ -148,16 +148,16 @@ _zip_buffer_new(zip_uint8_t *data, zip_uint64_t size) { zip_buffer_t *buffer; if (data == NULL) { - if ((data = (zip_uint8_t *)malloc(size)) == NULL) { - return NULL; - } + if ((data = (zip_uint8_t *)malloc(size)) == NULL) { + return NULL; + } } if ((buffer = (zip_buffer_t *)malloc(sizeof(*buffer))) == NULL) { - if (free_data) { - free(data); - } - return NULL; + if (free_data) { + free(data); + } + return NULL; } buffer->ok = true; @@ -175,13 +175,13 @@ _zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *b zip_buffer_t *buffer; if ((buffer = _zip_buffer_new(buf, size)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } if (_zip_read(src, buffer->data, size, error) < 0) { - _zip_buffer_free(buffer); - return NULL; + _zip_buffer_free(buffer); + return NULL; } return buffer; @@ -205,8 +205,8 @@ _zip_buffer_peek(zip_buffer_t *buffer, zip_uint64_t length) { zip_uint8_t *data; if (!buffer->ok || buffer->offset + length < length || buffer->offset + length > buffer->size) { - buffer->ok = false; - return NULL; + buffer->ok = false; + return NULL; } data = buffer->data + buffer->offset; @@ -218,7 +218,7 @@ _zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length) { zip_uint8_t *dst = _zip_buffer_get(buffer, length); if (dst == NULL) { - return -1; + return -1; } memcpy(dst, src, length); @@ -231,7 +231,7 @@ _zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i) { zip_uint8_t *data = _zip_buffer_get(buffer, 2); if (data == NULL) { - return -1; + return -1; } data[0] = (zip_uint8_t)(i & 0xff); @@ -246,7 +246,7 @@ _zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i) { zip_uint8_t *data = _zip_buffer_get(buffer, 4); if (data == NULL) { - return -1; + return -1; } data[0] = (zip_uint8_t)(i & 0xff); @@ -263,7 +263,7 @@ _zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i) { zip_uint8_t *data = _zip_buffer_get(buffer, 8); if (data == NULL) { - return -1; + return -1; } data[0] = (zip_uint8_t)(i & 0xff); @@ -284,7 +284,7 @@ _zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i) { zip_uint8_t *data = _zip_buffer_get(buffer, 1); if (data == NULL) { - return -1; + return -1; } data[0] = i; @@ -296,8 +296,8 @@ _zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i) { int _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset) { if (offset > buffer->size) { - buffer->ok = false; - return -1; + buffer->ok = false; + return -1; } buffer->ok = true; @@ -312,8 +312,8 @@ _zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length) { zip_uint64_t offset = buffer->offset + length; if (offset < buffer->offset) { - buffer->ok = false; - return -1; + buffer->ok = false; + return -1; } return _zip_buffer_set_offset(buffer, offset); } diff --git a/zip_close.c b/zip_close.c index 816fcef..a990c2f 100644 --- a/zip_close.c +++ b/zip_close.c @@ -1,6 +1,6 @@ /* zip_close.c -- close zip archive and update changes - Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -57,225 +57,225 @@ zip_close(zip_t *za) { int changed; if (za == NULL) - return -1; + return -1; changed = _zip_changed(za, &survivors); /* don't create zip files with no entries */ if (survivors == 0) { - if ((za->open_flags & ZIP_TRUNCATE) || changed) { - if (zip_source_remove(za->src) < 0) { - if (!((zip_error_code_zip(zip_source_error(za->src)) == ZIP_ER_REMOVE) && (zip_error_code_system(zip_source_error(za->src)) == ENOENT))) { - _zip_error_set_from_source(&za->error, za->src); - return -1; - } - } - } - zip_discard(za); - return 0; + if ((za->open_flags & ZIP_TRUNCATE) || changed) { + if (zip_source_remove(za->src) < 0) { + if (!((zip_error_code_zip(zip_source_error(za->src)) == ZIP_ER_REMOVE) && (zip_error_code_system(zip_source_error(za->src)) == ENOENT))) { + _zip_error_set_from_source(&za->error, za->src); + return -1; + } + } + } + zip_discard(za); + return 0; } if (!changed) { - zip_discard(za); - return 0; + zip_discard(za); + return 0; } if (survivors > za->nentry) { - zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; } if ((filelist = (zip_filelist_t *)malloc(sizeof(filelist[0]) * (size_t)survivors)) == NULL) - return -1; + return -1; unchanged_offset = ZIP_UINT64_MAX; /* create list of files with index into original archive */ for (i = j = 0; i < za->nentry; i++) { - if (za->entry[i].orig != NULL && ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) { - unchanged_offset = ZIP_MIN(unchanged_offset, za->entry[i].orig->offset); - } - if (za->entry[i].deleted) { - continue; - } + if (za->entry[i].orig != NULL && ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) { + unchanged_offset = ZIP_MIN(unchanged_offset, za->entry[i].orig->offset); + } + if (za->entry[i].deleted) { + continue; + } - if (j >= survivors) { - free(filelist); - zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); - return -1; - } + if (j >= survivors) { + free(filelist); + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } - filelist[j].idx = i; - j++; + filelist[j].idx = i; + j++; } if (j < survivors) { - free(filelist); - zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); - return -1; + free(filelist); + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; } if ((zip_source_supports(za->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING)) == 0) { - unchanged_offset = 0; + unchanged_offset = 0; } else { - if (unchanged_offset == ZIP_UINT64_MAX) { - /* we're keeping all file data, find the end of the last one */ - zip_uint64_t last_index = ZIP_UINT64_MAX; - unchanged_offset = 0; + if (unchanged_offset == ZIP_UINT64_MAX) { + /* we're keeping all file data, find the end of the last one */ + zip_uint64_t last_index = ZIP_UINT64_MAX; + unchanged_offset = 0; - for (i = 0; i < za->nentry; i++) { - if (za->entry[i].orig != NULL) { - if (za->entry[i].orig->offset >= unchanged_offset) { - unchanged_offset = za->entry[i].orig->offset; - last_index = i; - } - } - } - if (last_index != ZIP_UINT64_MAX) { - if ((unchanged_offset = _zip_file_get_end(za, last_index, &za->error)) == 0) { - free(filelist); - return -1; - } - } - } - if (unchanged_offset > 0) { - if (zip_source_begin_write_cloning(za->src, unchanged_offset) < 0) { - /* cloning not supported, need to copy everything */ - unchanged_offset = 0; - } - } + for (i = 0; i < za->nentry; i++) { + if (za->entry[i].orig != NULL) { + if (za->entry[i].orig->offset >= unchanged_offset) { + unchanged_offset = za->entry[i].orig->offset; + last_index = i; + } + } + } + if (last_index != ZIP_UINT64_MAX) { + if ((unchanged_offset = _zip_file_get_end(za, last_index, &za->error)) == 0) { + free(filelist); + return -1; + } + } + } + if (unchanged_offset > 0) { + if (zip_source_begin_write_cloning(za->src, unchanged_offset) < 0) { + /* cloning not supported, need to copy everything */ + unchanged_offset = 0; + } + } } if (unchanged_offset == 0) { - if (zip_source_begin_write(za->src) < 0) { - _zip_error_set_from_source(&za->error, za->src); - free(filelist); - return -1; - } + if (zip_source_begin_write(za->src) < 0) { + _zip_error_set_from_source(&za->error, za->src); + free(filelist); + return -1; + } } if (_zip_progress_start(za->progress) != 0) { - zip_error_set(&za->error, ZIP_ER_CANCELLED, 0); - zip_source_rollback_write(za->src); - free(filelist); - return -1; + zip_error_set(&za->error, ZIP_ER_CANCELLED, 0); + zip_source_rollback_write(za->src); + free(filelist); + return -1; } error = 0; for (j = 0; j < survivors; j++) { - int new_data; - zip_entry_t *entry; - zip_dirent_t *de; + int new_data; + zip_entry_t *entry; + zip_dirent_t *de; - if (_zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors) != 0) { - zip_error_set(&za->error, ZIP_ER_CANCELLED, 0); - error = 1; - break; - } + if (_zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors) != 0) { + zip_error_set(&za->error, ZIP_ER_CANCELLED, 0); + error = 1; + break; + } - i = filelist[j].idx; - entry = za->entry + i; + i = filelist[j].idx; + entry = za->entry + i; - if (entry->orig != NULL && entry->orig->offset < unchanged_offset) { - /* already implicitly copied by cloning */ - continue; - } + if (entry->orig != NULL && entry->orig->offset < unchanged_offset) { + /* already implicitly copied by cloning */ + continue; + } - new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD)); + new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD)); - /* create new local directory entry */ - if (entry->changes == NULL) { - if ((entry->changes = _zip_dirent_clone(entry->orig)) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - error = 1; - break; - } - } - de = entry->changes; - - if (_zip_read_local_ef(za, i) < 0) { - error = 1; - break; - } - - if ((off = zip_source_tell_write(za->src)) < 0) { - _zip_error_set_from_source(&za->error, za->src); - error = 1; - break; - } - de->offset = (zip_uint64_t)off; - - if (new_data) { - zip_source_t *zs; - - zs = NULL; - if (!ZIP_ENTRY_DATA_CHANGED(entry)) { - if ((zs = _zip_source_zip_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) { - error = 1; - break; - } - } - - /* add_data writes dirent */ - if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) { - error = 1; - if (zs) - zip_source_free(zs); - break; - } - if (zs) - zip_source_free(zs); - } - else { - zip_uint64_t offset; - - if (de->encryption_method != ZIP_EM_TRAD_PKWARE) { - /* when copying data, all sizes are known -> no data descriptor needed */ - /* except for PKWare encryption, where removing the data descriptor breaks password validation */ - de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR; - } - if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) { - error = 1; - break; - } - if ((offset = _zip_file_get_offset(za, i, &za->error)) == 0) { - error = 1; - break; - } - if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) { - _zip_error_set_from_source(&za->error, za->src); + /* create new local directory entry */ + if (entry->changes == NULL) { + if ((entry->changes = _zip_dirent_clone(entry->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); error = 1; - break; - } - if (copy_data(za, de->comp_size) < 0) { - error = 1; - break; - } + break; + } + } + de = entry->changes; - if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) { - if (write_data_descriptor(za, de, _zip_dirent_needs_zip64(de, 0)) < 0) { - error = 1; - break; - } - } - } + if (_zip_read_local_ef(za, i) < 0) { + error = 1; + break; + } + + if ((off = zip_source_tell_write(za->src)) < 0) { + _zip_error_set_from_source(&za->error, za->src); + error = 1; + break; + } + de->offset = (zip_uint64_t)off; + + if (new_data) { + zip_source_t *zs; + + zs = NULL; + if (!ZIP_ENTRY_DATA_CHANGED(entry)) { + if ((zs = _zip_source_zip_new(za, i, ZIP_FL_UNCHANGED, 0, 0, NULL, &za->error)) == NULL) { + error = 1; + break; + } + } + + /* add_data writes dirent */ + if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) { + error = 1; + if (zs) + zip_source_free(zs); + break; + } + if (zs) + zip_source_free(zs); + } + else { + zip_uint64_t offset; + + if (de->encryption_method != ZIP_EM_TRAD_PKWARE) { + /* when copying data, all sizes are known -> no data descriptor needed */ + /* except for PKWare encryption, where removing the data descriptor breaks password validation */ + de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR; + } + if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) { + error = 1; + break; + } + if ((offset = _zip_file_get_offset(za, i, &za->error)) == 0) { + error = 1; + break; + } + if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) { + _zip_error_set_from_source(&za->error, za->src); + error = 1; + break; + } + if (copy_data(za, de->comp_size) < 0) { + error = 1; + break; + } + + if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) { + if (write_data_descriptor(za, de, _zip_dirent_needs_zip64(de, 0)) < 0) { + error = 1; + break; + } + } + } } if (!error) { - if (write_cdir(za, filelist, survivors) < 0) - error = 1; + if (write_cdir(za, filelist, survivors) < 0) + error = 1; } free(filelist); if (!error) { - if (zip_source_commit_write(za->src) != 0) { - _zip_error_set_from_source(&za->error, za->src); - error = 1; - } - _zip_progress_end(za->progress); + if (zip_source_commit_write(za->src) != 0) { + _zip_error_set_from_source(&za->error, za->src); + error = 1; + } + _zip_progress_end(za->progress); } if (error) { - zip_source_rollback_write(za->src); - return -1; + zip_source_rollback_write(za->src); + return -1; } zip_discard(za); @@ -296,86 +296,83 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt; if (zip_source_stat(src, &st) < 0) { - _zip_error_set_from_source(&za->error, src); - return -1; + _zip_error_set_from_source(&za->error, src); + return -1; } if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) { - st.valid |= ZIP_STAT_COMP_METHOD; - st.comp_method = ZIP_CM_STORE; + st.valid |= ZIP_STAT_COMP_METHOD; + st.comp_method = ZIP_CM_STORE; } if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE) - de->comp_method = st.comp_method; + de->comp_method = st.comp_method; else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) { - st.valid |= ZIP_STAT_COMP_SIZE; - st.comp_size = st.size; + st.valid |= ZIP_STAT_COMP_SIZE; + st.comp_size = st.size; } else { - /* we'll recompress */ - st.valid &= ~ZIP_STAT_COMP_SIZE; + /* we'll recompress */ + st.valid &= ~ZIP_STAT_COMP_SIZE; } if ((st.valid & ZIP_STAT_ENCRYPTION_METHOD) == 0) { - st.valid |= ZIP_STAT_ENCRYPTION_METHOD; - st.encryption_method = ZIP_EM_NONE; + st.valid |= ZIP_STAT_ENCRYPTION_METHOD; + st.encryption_method = ZIP_EM_NONE; } flags = ZIP_EF_LOCAL; if ((st.valid & ZIP_STAT_SIZE) == 0) { - flags |= ZIP_FL_FORCE_ZIP64; - data_length = -1; + flags |= ZIP_FL_FORCE_ZIP64; + data_length = -1; } else { - de->uncomp_size = st.size; - /* this is technically incorrect (copy_source counts compressed data), but it's the best we have */ - data_length = (zip_int64_t)st.size; + de->uncomp_size = st.size; + /* this is technically incorrect (copy_source counts compressed data), but it's the best we have */ + data_length = (zip_int64_t)st.size; - if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) { - zip_uint64_t max_size; + if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) { + zip_uint64_t max_compressed_size; + zip_uint16_t compression_method = ZIP_CM_ACTUAL(de->comp_method); - switch (ZIP_CM_ACTUAL(de->comp_method)) { - case ZIP_CM_BZIP2: - /* computed by looking at increase of 10 random files of size 1MB when - * compressed with bzip2, rounded up: 1.006 */ - max_size = 4269351188u; - break; + if (compression_method == ZIP_CM_STORE) { + max_compressed_size = st.size; + } + else { + zip_compression_algorithm_t *algorithm = _zip_get_compression_algorithm(compression_method, true); + if (algorithm == NULL) { + max_compressed_size = ZIP_UINT64_MAX; + } + else { + max_compressed_size = algorithm->maximum_compressed_size(st.size); + } + } - case ZIP_CM_DEFLATE: - /* max deflate size increase: size + ceil(size/16k)*5+6 */ - max_size = 4293656963u; - break; - - case ZIP_CM_STORE: - max_size = 0xffffffffu; - break; - - default: - max_size = 0; - } - - if (st.size > max_size) { - flags |= ZIP_FL_FORCE_ZIP64; - } - } - else - de->comp_size = st.comp_size; + if (max_compressed_size > 0xffffffffu) { + flags |= ZIP_FL_FORCE_ZIP64; + } + } + else { + de->comp_size = st.comp_size; + data_length = (zip_int64_t)st.comp_size; + } } if ((offstart = zip_source_tell_write(za->src)) < 0) { - _zip_error_set_from_source(&za->error, za->src); - return -1; + _zip_error_set_from_source(&za->error, za->src); + return -1; } /* as long as we don't support non-seekable output, clear data descriptor bit */ de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR; if ((is_zip64 = _zip_dirent_write(za, de, flags)) < 0) { - return -1; + return -1; } needs_recompress = st.comp_method != ZIP_CM_ACTUAL(de->comp_method); needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE); + /* in these cases we can compute the CRC ourselves, so we do */ needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress; needs_compress = needs_recompress && (de->comp_method != ZIP_CM_STORE); @@ -387,127 +384,127 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { zip_source_keep(src_final); if (needs_decrypt) { - zip_encryption_implementation impl; + zip_encryption_implementation impl; - if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) { - zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); - zip_source_free(src_final); - return -1; - } - if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) { - /* error set by impl */ - zip_source_free(src_final); - return -1; - } + if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) { + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + zip_source_free(src_final); + return -1; + } + if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) { + /* error set by impl */ + zip_source_free(src_final); + return -1; + } - zip_source_free(src_final); - src_final = src_tmp; + zip_source_free(src_final); + src_final = src_tmp; } if (needs_decompress) { - if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) { - zip_source_free(src_final); - return -1; - } + if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) { + zip_source_free(src_final); + return -1; + } - zip_source_free(src_final); - src_final = src_tmp; + zip_source_free(src_final); + src_final = src_tmp; } if (needs_crc) { - if ((src_tmp = zip_source_crc(za, src_final, 0)) == NULL) { - zip_source_free(src_final); - return -1; - } + if ((src_tmp = zip_source_crc_create(src_final, 0, &za->error)) == NULL) { + zip_source_free(src_final); + return -1; + } - zip_source_free(src_final); - src_final = src_tmp; + zip_source_free(src_final); + src_final = src_tmp; } if (needs_compress) { - if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) { - zip_source_free(src_final); - return -1; - } + if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) { + zip_source_free(src_final); + return -1; + } - zip_source_free(src_final); - src_final = src_tmp; + zip_source_free(src_final); + src_final = src_tmp; } if (needs_encrypt) { - zip_encryption_implementation impl; - const char *password = NULL; + zip_encryption_implementation impl; + const char *password = NULL; - if (de->password) { - password = de->password; - } - else if (za->default_password) { - password = za->default_password; - } + if (de->password) { + password = de->password; + } + else if (za->default_password) { + password = za->default_password; + } - if ((impl = _zip_get_encryption_implementation(de->encryption_method, ZIP_CODEC_ENCODE)) == NULL) { - zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); - zip_source_free(src_final); - return -1; - } - if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) { - /* error set by impl */ - zip_source_free(src_final); - return -1; - } - if (de->encryption_method == ZIP_EM_TRAD_PKWARE) { - de->bitflags |= ZIP_GPBF_DATA_DESCRIPTOR; - } + if ((impl = _zip_get_encryption_implementation(de->encryption_method, ZIP_CODEC_ENCODE)) == NULL) { + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + zip_source_free(src_final); + return -1; + } + if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) { + /* error set by impl */ + zip_source_free(src_final); + return -1; + } + if (de->encryption_method == ZIP_EM_TRAD_PKWARE) { + de->bitflags |= ZIP_GPBF_DATA_DESCRIPTOR; + } - zip_source_free(src_final); - src_final = src_tmp; + zip_source_free(src_final); + src_final = src_tmp; } if ((offdata = zip_source_tell_write(za->src)) < 0) { - _zip_error_set_from_source(&za->error, za->src); - return -1; + _zip_error_set_from_source(&za->error, za->src); + return -1; } ret = copy_source(za, src_final, data_length); if (zip_source_stat(src_final, &st) < 0) { - _zip_error_set_from_source(&za->error, src_final); - ret = -1; + _zip_error_set_from_source(&za->error, src_final); + ret = -1; } if (zip_source_get_file_attributes(src_final, &attributes) != 0) { - _zip_error_set_from_source(&za->error, src_final); - ret = -1; + _zip_error_set_from_source(&za->error, src_final); + ret = -1; } zip_source_free(src_final); if (ret < 0) { - return -1; + return -1; } if ((offend = zip_source_tell_write(za->src)) < 0) { - _zip_error_set_from_source(&za->error, za->src); - return -1; + _zip_error_set_from_source(&za->error, za->src); + return -1; } if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) { - _zip_error_set_from_source(&za->error, za->src); - return -1; + _zip_error_set_from_source(&za->error, za->src); + return -1; } if ((st.valid & (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) { - zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; } if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) { - if (st.valid & ZIP_STAT_MTIME) - de->last_mod = st.mtime; - else - time(&de->last_mod); + if (st.valid & ZIP_STAT_MTIME) + de->last_mod = st.mtime; + else + time(&de->last_mod); } de->comp_method = st.comp_method; de->crc = st.crc; @@ -516,23 +513,23 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { _zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed); if ((ret = _zip_dirent_write(za, de, flags)) < 0) - return -1; + return -1; if (is_zip64 != ret) { - /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */ - zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); - return -1; + /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */ + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; } if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) { - _zip_error_set_from_source(&za->error, za->src); - return -1; + _zip_error_set_from_source(&za->error, za->src); + return -1; } if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) { - if (write_data_descriptor(za, de, is_zip64) < 0) { - return -1; - } + if (write_data_descriptor(za, de, is_zip64) < 0) { + return -1; + } } return 0; @@ -546,28 +543,28 @@ copy_data(zip_t *za, zip_uint64_t len) { double total = (double)len; if (!byte_array_init(buf, BUFSIZE)) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; } while (len > 0) { - n = len > BUFSIZE ? BUFSIZE : len; - if (_zip_read(za->src, buf, n, &za->error) < 0) { - byte_array_fini(buf); - return -1; - } + n = len > BUFSIZE ? BUFSIZE : len; + if (_zip_read(za->src, buf, n, &za->error) < 0) { + byte_array_fini(buf); + return -1; + } - if (_zip_write(za, buf, n) < 0) { - byte_array_fini(buf); - return -1; - } + if (_zip_write(za, buf, n) < 0) { + byte_array_fini(buf); + return -1; + } - len -= n; + len -= n; - if (_zip_progress_update(za->progress, (total - (double)len) / total) != 0) { - zip_error_set(&za->error, ZIP_ER_CANCELLED, 0); - return -1; - } + if (_zip_progress_update(za->progress, (total - (double)len) / total) != 0) { + zip_error_set(&za->error, ZIP_ER_CANCELLED, 0); + return -1; + } } byte_array_fini(buf); @@ -582,35 +579,35 @@ copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) { int ret; if (zip_source_open(src) < 0) { - _zip_error_set_from_source(&za->error, src); - return -1; + _zip_error_set_from_source(&za->error, src); + return -1; } if (!byte_array_init(buf, BUFSIZE)) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; } ret = 0; current = 0; while ((n = zip_source_read(src, buf, BUFSIZE)) > 0) { - if (_zip_write(za, buf, (zip_uint64_t)n) < 0) { - ret = -1; - break; - } - if (n == BUFSIZE && za->progress && data_length > 0) { - current += n; - if (_zip_progress_update(za->progress, (double)current / (double)data_length) != 0) { - zip_error_set(&za->error, ZIP_ER_CANCELLED, 0); - ret = -1; - break; - } - } + if (_zip_write(za, buf, (zip_uint64_t)n) < 0) { + ret = -1; + break; + } + if (n == BUFSIZE && za->progress && data_length > 0) { + current += n; + if (_zip_progress_update(za->progress, (double)current / (double)data_length) != 0) { + zip_error_set(&za->error, ZIP_ER_CANCELLED, 0); + ret = -1; + break; + } + } } if (n < 0) { - _zip_error_set_from_source(&za->error, src); - ret = -1; + _zip_error_set_from_source(&za->error, src); + ret = -1; } byte_array_fini(buf); @@ -622,18 +619,16 @@ copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) { static int write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) { - zip_int64_t cd_start, end, size; - - if ((cd_start = zip_source_tell_write(za->src)) < 0) { - return -1; + if (zip_source_tell_write(za->src) < 0) { + return -1; } - if ((size = _zip_cdir_write(za, filelist, survivors)) < 0) { - return -1; + if (_zip_cdir_write(za, filelist, survivors) < 0) { + return -1; } - if ((end = zip_source_tell_write(za->src)) < 0) { - return -1; + if (zip_source_tell_write(za->src) < 0) { + return -1; } return 0; @@ -649,20 +644,20 @@ _zip_changed(const zip_t *za, zip_uint64_t *survivorsp) { survivors = 0; if (za->comment_changed || za->ch_flags != za->flags) { - changed = 1; + changed = 1; } for (i = 0; i < za->nentry; i++) { - if (ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) { - changed = 1; - } - if (!za->entry[i].deleted) { - survivors++; - } + if (ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) { + changed = 1; + } + if (!za->entry[i].deleted) { + survivors++; + } } if (survivorsp) { - *survivorsp = survivors; + *survivorsp = survivors; } return changed; @@ -674,27 +669,27 @@ write_data_descriptor(zip_t *za, const zip_dirent_t *de, int is_zip64) { int ret = 0; if (buffer == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; } _zip_buffer_put(buffer, DATADES_MAGIC, 4); _zip_buffer_put_32(buffer, de->crc); if (is_zip64) { - _zip_buffer_put_64(buffer, de->comp_size); - _zip_buffer_put_64(buffer, de->uncomp_size); + _zip_buffer_put_64(buffer, de->comp_size); + _zip_buffer_put_64(buffer, de->uncomp_size); } else { - _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size); - _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size); + _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size); + _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size); } if (!_zip_buffer_ok(buffer)) { - zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); - ret = -1; + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + ret = -1; } else { - ret = _zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer)); + ret = _zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer)); } _zip_buffer_free(buffer); diff --git a/zip_crypto.h b/zip_crypto.h index f46c7d8..ac6e109 100644 --- a/zip_crypto.h +++ b/zip_crypto.h @@ -1,6 +1,6 @@ /* zip_crypto.h -- crypto definitions - Copyright (C) 2017-2019 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 diff --git a/zip_crypto_gnutls.h b/zip_crypto_gnutls.h index 30645ef..6743186 100644 --- a/zip_crypto_gnutls.h +++ b/zip_crypto_gnutls.h @@ -1,6 +1,6 @@ /* zip_crypto_gnutls.h -- definitions for GnuTLS wrapper. - Copyright (C) 2018-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -45,9 +45,9 @@ typedef struct { union { - struct aes128_ctx ctx_128; - struct aes192_ctx ctx_192; - struct aes256_ctx ctx_256; + struct aes128_ctx ctx_128; + struct aes192_ctx ctx_192; + struct aes256_ctx ctx_256; } ctx; zip_uint16_t key_size; } _zip_crypto_aes_t; diff --git a/zip_crypto_mbedtls.h b/zip_crypto_mbedtls.h index 7381951..a82b2fd 100644 --- a/zip_crypto_mbedtls.h +++ b/zip_crypto_mbedtls.h @@ -1,6 +1,6 @@ /* zip_crypto_mbedtls.h -- definitions for mbedtls wrapper - Copyright (C) 2018-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at diff --git a/zip_crypto_openssl.h b/zip_crypto_openssl.h index 51bd4ed..d959b8d 100644 --- a/zip_crypto_openssl.h +++ b/zip_crypto_openssl.h @@ -1,6 +1,6 @@ /* zip_crypto_openssl.h -- definitions for OpenSSL wrapper. - Copyright (C) 2018-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at diff --git a/zip_crypto_win.c b/zip_crypto_win.c index 7eb42c3..8202bfe 100644 --- a/zip_crypto_win.c +++ b/zip_crypto_win.c @@ -1,6 +1,6 @@ /* zip_crypto_win.c -- Windows Crypto API wrapper. - Copyright (C) 2018-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -31,6 +31,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include +#include #include "zipint.h" @@ -89,12 +90,13 @@ There is no #ifdef to control that, because this is working for all supported OS bool _zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, zip_uint16_t iterations, zip_uint8_t *output, zip_uint16_t output_length) { BCRYPT_ALG_HANDLE hAlgorithm = NULL; + bool result; if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG))) { - return false; + return false; } - bool result = BCRYPT_SUCCESS(BCryptDeriveKeyPBKDF2(hAlgorithm, (PUCHAR)key, (ULONG)key_length, (PUCHAR)salt, salt_length, iterations, output, output_length, 0)); + result = BCRYPT_SUCCESS(BCryptDeriveKeyPBKDF2(hAlgorithm, (PUCHAR)key, (ULONG)key_length, (PUCHAR)salt, salt_length, iterations, output, output_length, 0)); BCryptCloseAlgorithmProvider(hAlgorithm, 0); @@ -120,13 +122,13 @@ typedef struct { static void hmacFree(PRF_CTX *pContext) { if (pContext->hOuterHash) - BCryptDestroyHash(pContext->hOuterHash); + BCryptDestroyHash(pContext->hOuterHash); if (pContext->hInnerHash) - BCryptDestroyHash(pContext->hInnerHash); + BCryptDestroyHash(pContext->hInnerHash); free(pContext->pbOuterHash); free(pContext->pbInnerHash); if (pContext->hAlgorithm) - BCryptCloseAlgorithmProvider(pContext->hAlgorithm, 0); + BCryptCloseAlgorithmProvider(pContext->hAlgorithm, 0); } static BOOL @@ -135,13 +137,13 @@ hmacPrecomputeDigest(BCRYPT_HASH_HANDLE hHash, PUCHAR pbPassword, DWORD cbPasswo DWORD i; if (cbPassword > BLOCK_SIZE) { - return FALSE; + return FALSE; } memset(buffer, mask, sizeof(buffer)); for (i = 0; i < cbPassword; ++i) { - buffer[i] = (char)(pbPassword[i] ^ mask); + buffer[i] = (char)(pbPassword[i] ^ mask); } return BCRYPT_SUCCESS(BCryptHashData(hHash, buffer, sizeof(buffer), 0)); @@ -154,27 +156,27 @@ hmacInit(PRF_CTX *pContext, PUCHAR pbPassword, DWORD cbPassword) { BYTE key[DIGEST_SIZE]; if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&pContext->hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, 0)) || !BCRYPT_SUCCESS(BCryptGetProperty(pContext->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&pContext->cbHashObject, sizeof(pContext->cbHashObject), &cbResult, 0)) || ((pContext->pbInnerHash = malloc(pContext->cbHashObject)) == NULL) || ((pContext->pbOuterHash = malloc(pContext->cbHashObject)) == NULL) || !BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &pContext->hInnerHash, pContext->pbInnerHash, pContext->cbHashObject, NULL, 0, 0)) || !BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &pContext->hOuterHash, pContext->pbOuterHash, pContext->cbHashObject, NULL, 0, 0))) { - goto hmacInit_end; + goto hmacInit_end; } if (cbPassword > BLOCK_SIZE) { - BCRYPT_HASH_HANDLE hHash = NULL; - PUCHAR pbHashObject = malloc(pContext->cbHashObject); - if (pbHashObject == NULL) { - goto hmacInit_end; - } + BCRYPT_HASH_HANDLE hHash = NULL; + PUCHAR pbHashObject = malloc(pContext->cbHashObject); + if (pbHashObject == NULL) { + goto hmacInit_end; + } - bStatus = BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &hHash, pbHashObject, pContext->cbHashObject, NULL, 0, 0)) && BCRYPT_SUCCESS(BCryptHashData(hHash, pbPassword, cbPassword, 0)) && BCRYPT_SUCCESS(BCryptGetProperty(hHash, BCRYPT_HASH_LENGTH, (PUCHAR)&cbPassword, sizeof(cbPassword), &cbResult, 0)) && BCRYPT_SUCCESS(BCryptFinishHash(hHash, key, cbPassword, 0)); + bStatus = BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &hHash, pbHashObject, pContext->cbHashObject, NULL, 0, 0)) && BCRYPT_SUCCESS(BCryptHashData(hHash, pbPassword, cbPassword, 0)) && BCRYPT_SUCCESS(BCryptGetProperty(hHash, BCRYPT_HASH_LENGTH, (PUCHAR)&cbPassword, sizeof(cbPassword), &cbResult, 0)) && BCRYPT_SUCCESS(BCryptFinishHash(hHash, key, cbPassword, 0)); - if (hHash) - BCryptDestroyHash(hHash); - free(pbHashObject); + if (hHash) + BCryptDestroyHash(hHash); + free(pbHashObject); - if (!bStatus) { - goto hmacInit_end; - } + if (!bStatus) { + goto hmacInit_end; + } - pbPassword = key; + pbPassword = key; } bStatus = hmacPrecomputeDigest(pContext->hInnerHash, pbPassword, cbPassword, 0x36) && hmacPrecomputeDigest(pContext->hOuterHash, pbPassword, cbPassword, 0x5C); @@ -182,7 +184,7 @@ hmacInit(PRF_CTX *pContext, PUCHAR pbPassword, DWORD cbPassword) { hmacInit_end: if (bStatus == FALSE) - hmacFree(pContext); + hmacFree(pContext); return bStatus; } @@ -194,13 +196,13 @@ hmacCalculateInternal(BCRYPT_HASH_HANDLE hHashTemplate, PUCHAR pbData, DWORD cbD PUCHAR pbHashObject = malloc(cbHashObject); if (pbHashObject == NULL) { - return FALSE; + return FALSE; } if (BCRYPT_SUCCESS(BCryptDuplicateHash(hHashTemplate, &hHash, pbHashObject, cbHashObject, 0))) { - success = BCRYPT_SUCCESS(BCryptHashData(hHash, pbData, cbData, 0)) && BCRYPT_SUCCESS(BCryptFinishHash(hHash, pbOutput, cbOutput, 0)); + success = BCRYPT_SUCCESS(BCryptHashData(hHash, pbData, cbData, 0)) && BCRYPT_SUCCESS(BCryptFinishHash(hHash, pbOutput, cbOutput, 0)); - BCryptDestroyHash(hHash); + BCryptDestroyHash(hHash); } free(pbHashObject); @@ -219,7 +221,7 @@ hmacCalculate(PRF_CTX *pContext, PUCHAR pbData, DWORD cbData, PUCHAR pbDigest) { static void myxor(LPBYTE ptr1, LPBYTE ptr2, DWORD dwLen) { while (dwLen--) - *ptr1++ ^= *ptr2++; + *ptr1++ ^= *ptr2++; } BOOL @@ -232,52 +234,52 @@ pbkdf2(PUCHAR pbPassword, ULONG cbPassword, PUCHAR pbSalt, ULONG cbSalt, DWORD c PRF_CTX prfCtx = {0}; if (U == NULL) { - return FALSE; + return FALSE; } if (pbPassword == NULL || cbPassword == 0 || pbSalt == NULL || cbSalt == 0 || cIterations == 0 || pbDerivedKey == NULL || cbDerivedKey == 0) { - free(U); - return FALSE; + free(U); + return FALSE; } if (!hmacInit(&prfCtx, pbPassword, cbPassword)) { - goto PBKDF2_end; + goto PBKDF2_end; } l = (DWORD)ceil((double)cbDerivedKey / (double)DIGEST_SIZE); r = cbDerivedKey - (l - 1) * DIGEST_SIZE; for (i = 1; i <= l; i++) { - ZeroMemory(Ti, DIGEST_SIZE); - for (j = 0; j < cIterations; j++) { - if (j == 0) { - /* construct first input for PRF */ - memcpy(U, pbSalt, cbSalt); - U[cbSalt] = (BYTE)((i & 0xFF000000) >> 24); - U[cbSalt + 1] = (BYTE)((i & 0x00FF0000) >> 16); - U[cbSalt + 2] = (BYTE)((i & 0x0000FF00) >> 8); - U[cbSalt + 3] = (BYTE)((i & 0x000000FF)); - dwULen = cbSalt + 4; - } - else { - memcpy(U, V, DIGEST_SIZE); - dwULen = DIGEST_SIZE; - } + ZeroMemory(Ti, DIGEST_SIZE); + for (j = 0; j < cIterations; j++) { + if (j == 0) { + /* construct first input for PRF */ + memcpy(U, pbSalt, cbSalt); + U[cbSalt] = (BYTE)((i & 0xFF000000) >> 24); + U[cbSalt + 1] = (BYTE)((i & 0x00FF0000) >> 16); + U[cbSalt + 2] = (BYTE)((i & 0x0000FF00) >> 8); + U[cbSalt + 3] = (BYTE)((i & 0x000000FF)); + dwULen = cbSalt + 4; + } + else { + memcpy(U, V, DIGEST_SIZE); + dwULen = DIGEST_SIZE; + } - if (!hmacCalculate(&prfCtx, U, dwULen, V)) { - goto PBKDF2_end; - } + if (!hmacCalculate(&prfCtx, U, dwULen, V)) { + goto PBKDF2_end; + } - myxor(Ti, V, DIGEST_SIZE); - } + myxor(Ti, V, DIGEST_SIZE); + } - if (i != l) { - memcpy(&pbDerivedKey[(i - 1) * DIGEST_SIZE], Ti, DIGEST_SIZE); - } - else { - /* Take only the first r bytes */ - memcpy(&pbDerivedKey[(i - 1) * DIGEST_SIZE], Ti, r); - } + if (i != l) { + memcpy(&pbDerivedKey[(i - 1) * DIGEST_SIZE], Ti, DIGEST_SIZE); + } + else { + /* Take only the first r bytes */ + memcpy(&pbDerivedKey[(i - 1) * DIGEST_SIZE], Ti, r); + } } bStatus = TRUE; @@ -312,35 +314,35 @@ _zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t * ULONG key_length = key_size / 8; if (aes == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&aes->hAlgorithm, BCRYPT_AES_ALGORITHM, NULL, 0))) { - _zip_crypto_aes_free(aes); - return NULL; + _zip_crypto_aes_free(aes); + return NULL; } if (!BCRYPT_SUCCESS(BCryptSetProperty(aes->hAlgorithm, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0))) { - _zip_crypto_aes_free(aes); - return NULL; + _zip_crypto_aes_free(aes); + return NULL; } if (!BCRYPT_SUCCESS(BCryptGetProperty(aes->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&aes->cbKeyObject, sizeof(aes->cbKeyObject), &cbResult, 0))) { - _zip_crypto_aes_free(aes); - return NULL; + _zip_crypto_aes_free(aes); + return NULL; } aes->pbKeyObject = malloc(aes->cbKeyObject); if (aes->pbKeyObject == NULL) { - _zip_crypto_aes_free(aes); - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + _zip_crypto_aes_free(aes); + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } if (!BCRYPT_SUCCESS(BCryptGenerateSymmetricKey(aes->hAlgorithm, &aes->hKey, aes->pbKeyObject, aes->cbKeyObject, (PUCHAR)key, key_length, 0))) { - _zip_crypto_aes_free(aes); - return NULL; + _zip_crypto_aes_free(aes); + return NULL; } return aes; @@ -349,19 +351,19 @@ _zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t * void _zip_crypto_aes_free(_zip_crypto_aes_t *aes) { if (aes == NULL) { - return; + return; } if (aes->hKey != NULL) { - BCryptDestroyKey(aes->hKey); + BCryptDestroyKey(aes->hKey); } if (aes->pbKeyObject != NULL) { - free(aes->pbKeyObject); + free(aes->pbKeyObject); } if (aes->hAlgorithm != NULL) { - BCryptCloseAlgorithmProvider(aes->hAlgorithm, 0); + BCryptCloseAlgorithmProvider(aes->hAlgorithm, 0); } free(aes); @@ -392,53 +394,53 @@ _zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_ _zip_crypto_hmac_t *hmac; if (secret_length > INT_MAX) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } hmac = (_zip_crypto_hmac_t *)calloc(1, sizeof(*hmac)); if (hmac == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } status = BCryptOpenAlgorithmProvider(&hmac->hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG); if (!BCRYPT_SUCCESS(status)) { - _zip_crypto_hmac_free(hmac); - return NULL; + _zip_crypto_hmac_free(hmac); + return NULL; } status = BCryptGetProperty(hmac->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&hmac->cbHashObject, sizeof(hmac->cbHashObject), &cbResult, 0); if (!BCRYPT_SUCCESS(status)) { - _zip_crypto_hmac_free(hmac); - return NULL; + _zip_crypto_hmac_free(hmac); + return NULL; } hmac->pbHashObject = malloc(hmac->cbHashObject); if (hmac->pbHashObject == NULL) { - _zip_crypto_hmac_free(hmac); - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + _zip_crypto_hmac_free(hmac); + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } status = BCryptGetProperty(hmac->hAlgorithm, BCRYPT_HASH_LENGTH, (PUCHAR)&hmac->cbHash, sizeof(hmac->cbHash), &cbResult, 0); if (!BCRYPT_SUCCESS(status)) { - _zip_crypto_hmac_free(hmac); - return NULL; + _zip_crypto_hmac_free(hmac); + return NULL; } hmac->pbHash = malloc(hmac->cbHash); if (hmac->pbHash == NULL) { - _zip_crypto_hmac_free(hmac); - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + _zip_crypto_hmac_free(hmac); + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } status = BCryptCreateHash(hmac->hAlgorithm, &hmac->hHash, hmac->pbHashObject, hmac->cbHashObject, (PUCHAR)secret, (ULONG)secret_length, 0); if (!BCRYPT_SUCCESS(status)) { - _zip_crypto_hmac_free(hmac); - return NULL; + _zip_crypto_hmac_free(hmac); + return NULL; } return hmac; @@ -447,23 +449,23 @@ _zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_ void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) { if (hmac == NULL) { - return; + return; } if (hmac->hHash != NULL) { - BCryptDestroyHash(hmac->hHash); + BCryptDestroyHash(hmac->hHash); } if (hmac->pbHash != NULL) { - free(hmac->pbHash); + free(hmac->pbHash); } if (hmac->pbHashObject != NULL) { - free(hmac->pbHashObject); + free(hmac->pbHashObject); } if (hmac->hAlgorithm) { - BCryptCloseAlgorithmProvider(hmac->hAlgorithm, 0); + BCryptCloseAlgorithmProvider(hmac->hAlgorithm, 0); } free(hmac); @@ -472,7 +474,7 @@ _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) { bool _zip_crypto_hmac(_zip_crypto_hmac_t *hmac, zip_uint8_t *data, zip_uint64_t length) { if (hmac == NULL || length > ULONG_MAX) { - return false; + return false; } return BCRYPT_SUCCESS(BCryptHashData(hmac->hHash, data, (ULONG)length, 0)); @@ -481,7 +483,7 @@ _zip_crypto_hmac(_zip_crypto_hmac_t *hmac, zip_uint8_t *data, zip_uint64_t lengt bool _zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data) { if (hmac == NULL) { - return false; + return false; } return BCRYPT_SUCCESS(BCryptFinishHash(hmac->hHash, data, hmac->cbHash, 0)); diff --git a/zip_crypto_win.h b/zip_crypto_win.h index d5c22a9..be9fdc6 100644 --- a/zip_crypto_win.h +++ b/zip_crypto_win.h @@ -1,6 +1,6 @@ /* zip_crypto_win.h -- Windows Crypto API wrapper. - Copyright (C) 2018-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at diff --git a/zip_delete.c b/zip_delete.c index 97701a0..7d82d9a 100644 --- a/zip_delete.c +++ b/zip_delete.c @@ -1,6 +1,6 @@ /* zip_delete.c -- delete file from zip archive - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,27 +40,27 @@ zip_delete(zip_t *za, zip_uint64_t idx) { const char *name; if (idx >= za->nentry) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if (ZIP_IS_RDONLY(za)) { - zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; } if ((name = _zip_get_name(za, idx, 0, &za->error)) == NULL) { - return -1; + return -1; } if (!_zip_hash_delete(za->names, (const zip_uint8_t *)name, &za->error)) { - return -1; + return -1; } /* allow duplicate file names, because the file will * be removed directly afterwards */ if (_zip_unchange(za, idx, 1) != 0) - return -1; + return -1; za->entry[idx].deleted = 1; diff --git a/zip_dir_add.c b/zip_dir_add.c index c40b1cb..89eb432 100644 --- a/zip_dir_add.c +++ b/zip_dir_add.c @@ -1,6 +1,6 @@ /* zip_dir_add.c -- add directory - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -48,31 +48,31 @@ zip_dir_add(zip_t *za, const char *name, zip_flags_t flags) { zip_source_t *source; if (ZIP_IS_RDONLY(za)) { - zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; } if (name == NULL) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } s = NULL; len = strlen(name); if (name[len - 1] != '/') { - if ((s = (char *)malloc(len + 2)) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; - } - strcpy(s, name); - s[len] = '/'; - s[len + 1] = '\0'; + if ((s = (char *)malloc(len + 2)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + strcpy(s, name); + s[len] = '/'; + s[len + 1] = '\0'; } if ((source = zip_source_buffer(za, NULL, 0, 0)) == NULL) { - free(s); - return -1; + free(s); + return -1; } idx = _zip_file_replace(za, ZIP_UINT64_MAX, s ? s : name, source, flags); @@ -80,12 +80,12 @@ zip_dir_add(zip_t *za, const char *name, zip_flags_t flags) { free(s); if (idx < 0) - zip_source_free(source); + zip_source_free(source); else { - if (zip_file_set_external_attributes(za, (zip_uint64_t)idx, 0, ZIP_OPSYS_DEFAULT, ZIP_EXT_ATTRIB_DEFAULT_DIR) < 0) { - zip_delete(za, (zip_uint64_t)idx); - return -1; - } + if (zip_file_set_external_attributes(za, (zip_uint64_t)idx, 0, ZIP_OPSYS_DEFAULT, ZIP_EXT_ATTRIB_DEFAULT_DIR) < 0) { + zip_delete(za, (zip_uint64_t)idx); + return -1; + } } return idx; diff --git a/zip_dirent.c b/zip_dirent.c index 1691071..a7c336b 100644 --- a/zip_dirent.c +++ b/zip_dirent.c @@ -1,6 +1,6 @@ /* zip_dirent.c -- read directory entry (local or central), clean dirent - Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -50,10 +50,10 @@ _zip_cdir_free(zip_cdir_t *cd) { zip_uint64_t i; if (!cd) - return; + return; for (i = 0; i < cd->nentry; i++) - _zip_entry_finalize(cd->entry + i); + _zip_entry_finalize(cd->entry + i); free(cd->entry); _zip_string_free(cd->comment); free(cd); @@ -65,8 +65,8 @@ _zip_cdir_new(zip_uint64_t nentry, zip_error_t *error) { zip_cdir_t *cd; if ((cd = (zip_cdir_t *)malloc(sizeof(*cd))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } cd->entry = NULL; @@ -76,8 +76,8 @@ _zip_cdir_new(zip_uint64_t nentry, zip_error_t *error) { cd->is_zip64 = false; if (!_zip_cdir_grow(cd, nentry, error)) { - _zip_cdir_free(cd); - return NULL; + _zip_cdir_free(cd); + return NULL; } return cd; @@ -90,25 +90,25 @@ _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *err zip_entry_t *new_entry; if (additional_entries == 0) { - return true; + return true; } new_alloc = cd->nentry_alloc + additional_entries; if (new_alloc < additional_entries || new_alloc > SIZE_MAX / sizeof(*(cd->entry))) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return false; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; } if ((new_entry = (zip_entry_t *)realloc(cd->entry, sizeof(*(cd->entry)) * (size_t)new_alloc)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return false; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; } cd->entry = new_entry; for (i = cd->nentry; i < new_alloc; i++) { - _zip_entry_init(cd->entry + i); + _zip_entry_init(cd->entry + i); } cd->nentry = cd->nentry_alloc = new_alloc; @@ -129,52 +129,52 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor int ret; if ((off = zip_source_tell_write(za->src)) < 0) { - _zip_error_set_from_source(&za->error, za->src); - return -1; + _zip_error_set_from_source(&za->error, za->src); + return -1; } offset = (zip_uint64_t)off; is_zip64 = false; for (i = 0; i < survivors; i++) { - zip_entry_t *entry = za->entry + filelist[i].idx; + zip_entry_t *entry = za->entry + filelist[i].idx; - if ((ret = _zip_dirent_write(za, entry->changes ? entry->changes : entry->orig, ZIP_FL_CENTRAL)) < 0) - return -1; - if (ret) - is_zip64 = true; + if ((ret = _zip_dirent_write(za, entry->changes ? entry->changes : entry->orig, ZIP_FL_CENTRAL)) < 0) + return -1; + if (ret) + is_zip64 = true; } if ((off = zip_source_tell_write(za->src)) < 0) { - _zip_error_set_from_source(&za->error, za->src); - return -1; + _zip_error_set_from_source(&za->error, za->src); + return -1; } size = (zip_uint64_t)off - offset; if (offset > ZIP_UINT32_MAX || survivors > ZIP_UINT16_MAX) - is_zip64 = true; + is_zip64 = true; if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; } if (is_zip64) { - _zip_buffer_put(buffer, EOCD64_MAGIC, 4); - _zip_buffer_put_64(buffer, EOCD64LEN - 12); - _zip_buffer_put_16(buffer, 45); - _zip_buffer_put_16(buffer, 45); - _zip_buffer_put_32(buffer, 0); - _zip_buffer_put_32(buffer, 0); - _zip_buffer_put_64(buffer, survivors); - _zip_buffer_put_64(buffer, survivors); - _zip_buffer_put_64(buffer, size); - _zip_buffer_put_64(buffer, offset); - _zip_buffer_put(buffer, EOCD64LOC_MAGIC, 4); - _zip_buffer_put_32(buffer, 0); - _zip_buffer_put_64(buffer, offset + size); - _zip_buffer_put_32(buffer, 1); + _zip_buffer_put(buffer, EOCD64_MAGIC, 4); + _zip_buffer_put_64(buffer, EOCD64LEN - 12); + _zip_buffer_put_16(buffer, 45); + _zip_buffer_put_16(buffer, 45); + _zip_buffer_put_32(buffer, 0); + _zip_buffer_put_32(buffer, 0); + _zip_buffer_put_64(buffer, survivors); + _zip_buffer_put_64(buffer, survivors); + _zip_buffer_put_64(buffer, size); + _zip_buffer_put_64(buffer, offset); + _zip_buffer_put(buffer, EOCD64LOC_MAGIC, 4); + _zip_buffer_put_32(buffer, 0); + _zip_buffer_put_64(buffer, offset + size); + _zip_buffer_put_32(buffer, 1); } _zip_buffer_put(buffer, EOCD_MAGIC, 4); @@ -189,22 +189,22 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor _zip_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0)); if (!_zip_buffer_ok(buffer)) { - zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); - _zip_buffer_free(buffer); - return -1; + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(buffer); + return -1; } if (_zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer)) < 0) { - _zip_buffer_free(buffer); - return -1; + _zip_buffer_free(buffer); + return -1; } _zip_buffer_free(buffer); if (comment) { - if (_zip_write(za, comment->raw, comment->length) < 0) { - return -1; - } + if (_zip_write(za, comment->raw, comment->length) < 0) { + return -1; + } } return (zip_int64_t)size; @@ -216,12 +216,12 @@ _zip_dirent_clone(const zip_dirent_t *sde) { zip_dirent_t *tde; if ((tde = (zip_dirent_t *)malloc(sizeof(*tde))) == NULL) - return NULL; + return NULL; if (sde) - memcpy(tde, sde, sizeof(*sde)); + memcpy(tde, sde, sizeof(*sde)); else - _zip_dirent_init(tde); + _zip_dirent_init(tde); tde->changed = 0; tde->cloned = 1; @@ -233,23 +233,23 @@ _zip_dirent_clone(const zip_dirent_t *sde) { void _zip_dirent_finalize(zip_dirent_t *zde) { if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) { - _zip_string_free(zde->filename); - zde->filename = NULL; + _zip_string_free(zde->filename); + zde->filename = NULL; } if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD) { - _zip_ef_free(zde->extra_fields); - zde->extra_fields = NULL; + _zip_ef_free(zde->extra_fields); + zde->extra_fields = NULL; } if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT) { - _zip_string_free(zde->comment); - zde->comment = NULL; + _zip_string_free(zde->comment); + zde->comment = NULL; } if (!zde->cloned || zde->changed & ZIP_DIRENT_PASSWORD) { - if (zde->password) { - _zip_crypto_clear(zde->password, strlen(zde->password)); - } - free(zde->password); - zde->password = NULL; + if (zde->password) { + _zip_crypto_clear(zde->password, strlen(zde->password)); + } + free(zde->password); + zde->password = NULL; } } @@ -257,7 +257,7 @@ _zip_dirent_finalize(zip_dirent_t *zde) { void _zip_dirent_free(zip_dirent_t *zde) { if (zde == NULL) - return; + return; _zip_dirent_finalize(zde); free(zde); @@ -295,7 +295,7 @@ _zip_dirent_init(zip_dirent_t *de) { bool _zip_dirent_needs_zip64(const zip_dirent_t *de, zip_flags_t flags) { if (de->uncomp_size >= ZIP_UINT32_MAX || de->comp_size >= ZIP_UINT32_MAX || ((flags & ZIP_FL_CENTRAL) && de->offset >= ZIP_UINT32_MAX)) - return true; + return true; return false; } @@ -306,7 +306,7 @@ _zip_dirent_new(void) { zip_dirent_t *de; if ((de = (zip_dirent_t *)malloc(sizeof(*de))) == NULL) - return NULL; + return NULL; _zip_dirent_init(de); return de; @@ -335,32 +335,32 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo size = local ? LENTRYSIZE : CDENTRYSIZE; if (buffer) { - if (_zip_buffer_left(buffer) < size) { - zip_error_set(error, ZIP_ER_NOZIP, 0); - return -1; - } + if (_zip_buffer_left(buffer) < size) { + zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } } else { - if ((buffer = _zip_buffer_new_from_source(src, size, buf, error)) == NULL) { - return -1; - } + if ((buffer = _zip_buffer_new_from_source(src, size, buf, error)) == NULL) { + return -1; + } } if (memcmp(_zip_buffer_get(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) { - zip_error_set(error, ZIP_ER_NOZIP, 0); - if (!from_buffer) { - _zip_buffer_free(buffer); - } - return -1; + zip_error_set(error, ZIP_ER_NOZIP, 0); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; } /* convert buffercontents to zip_dirent */ _zip_dirent_init(zde); if (!local) - zde->version_madeby = _zip_buffer_get_16(buffer); + zde->version_madeby = _zip_buffer_get_16(buffer); else - zde->version_madeby = 0; + zde->version_madeby = 0; zde->version_needed = _zip_buffer_get_16(buffer); zde->bitflags = _zip_buffer_get_16(buffer); zde->comp_method = _zip_buffer_get_16(buffer); @@ -378,39 +378,39 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo ef_len = _zip_buffer_get_16(buffer); if (local) { - comment_len = 0; - zde->disk_number = 0; - zde->int_attrib = 0; - zde->ext_attrib = 0; - zde->offset = 0; + comment_len = 0; + zde->disk_number = 0; + zde->int_attrib = 0; + zde->ext_attrib = 0; + zde->offset = 0; } else { - comment_len = _zip_buffer_get_16(buffer); - zde->disk_number = _zip_buffer_get_16(buffer); - zde->int_attrib = _zip_buffer_get_16(buffer); - zde->ext_attrib = _zip_buffer_get_32(buffer); - zde->offset = _zip_buffer_get_32(buffer); + comment_len = _zip_buffer_get_16(buffer); + zde->disk_number = _zip_buffer_get_16(buffer); + zde->int_attrib = _zip_buffer_get_16(buffer); + zde->ext_attrib = _zip_buffer_get_32(buffer); + zde->offset = _zip_buffer_get_32(buffer); } if (!_zip_buffer_ok(buffer)) { - zip_error_set(error, ZIP_ER_INTERNAL, 0); - if (!from_buffer) { - _zip_buffer_free(buffer); - } - return -1; + zip_error_set(error, ZIP_ER_INTERNAL, 0); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; } if (zde->bitflags & ZIP_GPBF_ENCRYPTED) { - if (zde->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) { - /* TODO */ - zde->encryption_method = ZIP_EM_UNKNOWN; - } - else { - zde->encryption_method = ZIP_EM_TRAD_PKWARE; - } + if (zde->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) { + /* TODO */ + zde->encryption_method = ZIP_EM_UNKNOWN; + } + else { + zde->encryption_method = ZIP_EM_TRAD_PKWARE; + } } else { - zde->encryption_method = ZIP_EM_NONE; + zde->encryption_method = ZIP_EM_NONE; } zde->filename = NULL; @@ -420,80 +420,80 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo variable_size = (zip_uint32_t)filename_len + (zip_uint32_t)ef_len + (zip_uint32_t)comment_len; if (from_buffer) { - if (_zip_buffer_left(buffer) < variable_size) { - zip_error_set(error, ZIP_ER_INCONS, 0); - return -1; - } + if (_zip_buffer_left(buffer) < variable_size) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW); + return -1; + } } else { - _zip_buffer_free(buffer); + _zip_buffer_free(buffer); - if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) { - return -1; - } + if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) { + return -1; + } } if (filename_len) { - zde->filename = _zip_read_string(buffer, src, filename_len, 1, error); - if (!zde->filename) { - if (zip_error_code_zip(error) == ZIP_ER_EOF) { - zip_error_set(error, ZIP_ER_INCONS, 0); - } - if (!from_buffer) { - _zip_buffer_free(buffer); - } - return -1; - } + zde->filename = _zip_read_string(buffer, src, filename_len, 1, error); + if (!zde->filename) { + if (zip_error_code_zip(error) == ZIP_ER_EOF) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW); + } + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } - if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) { - if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) { - zip_error_set(error, ZIP_ER_INCONS, 0); - if (!from_buffer) { - _zip_buffer_free(buffer); - } - return -1; - } - } + if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) { + if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_FILENAME); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + } } if (ef_len) { - zip_uint8_t *ef = _zip_read_data(buffer, src, ef_len, 0, error); + zip_uint8_t *ef = _zip_read_data(buffer, src, ef_len, 0, error); - if (ef == NULL) { - if (!from_buffer) { - _zip_buffer_free(buffer); - } - return -1; - } - if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, &zde->extra_fields, error)) { - free(ef); - if (!from_buffer) { - _zip_buffer_free(buffer); - } - return -1; - } - free(ef); - if (local) - zde->local_extra_fields_read = 1; + if (ef == NULL) { + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, &zde->extra_fields, error)) { + free(ef); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + free(ef); + if (local) + zde->local_extra_fields_read = 1; } if (comment_len) { - zde->comment = _zip_read_string(buffer, src, comment_len, 0, error); - if (!zde->comment) { - if (!from_buffer) { - _zip_buffer_free(buffer); - } - return -1; - } - if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) { - if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) { - zip_error_set(error, ZIP_ER_INCONS, 0); - if (!from_buffer) { - _zip_buffer_free(buffer); - } - return -1; - } - } + zde->comment = _zip_read_string(buffer, src, comment_len, 0, error); + if (!zde->comment) { + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) { + if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_COMMENT); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + } } zde->filename = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_NAME, zde->filename); @@ -502,96 +502,96 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo /* Zip64 */ if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) { - zip_uint16_t got_len; - zip_buffer_t *ef_buffer; - const zip_uint8_t *ef = _zip_ef_get_by_id(zde->extra_fields, &got_len, ZIP_EF_ZIP64, 0, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error); - /* TODO: if got_len == 0 && !ZIP64_EOCD: no error, 0xffffffff is valid value */ - if (ef == NULL) { - if (!from_buffer) { - _zip_buffer_free(buffer); - } - return -1; - } + zip_uint16_t got_len; + zip_buffer_t *ef_buffer; + const zip_uint8_t *ef = _zip_ef_get_by_id(zde->extra_fields, &got_len, ZIP_EF_ZIP64, 0, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error); + /* TODO: if got_len == 0 && !ZIP64_EOCD: no error, 0xffffffff is valid value */ + if (ef == NULL) { + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } - if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - if (!from_buffer) { - _zip_buffer_free(buffer); - } - return -1; - } + if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } - if (zde->uncomp_size == ZIP_UINT32_MAX) { - zde->uncomp_size = _zip_buffer_get_64(ef_buffer); - } - else if (local) { - /* From appnote.txt: This entry in the Local header MUST - include BOTH original and compressed file size fields. */ - (void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */ - } - if (zde->comp_size == ZIP_UINT32_MAX) { - zde->comp_size = _zip_buffer_get_64(ef_buffer); - } - if (!local) { - if (zde->offset == ZIP_UINT32_MAX) { - zde->offset = _zip_buffer_get_64(ef_buffer); - } - if (zde->disk_number == ZIP_UINT16_MAX) { - zde->disk_number = _zip_buffer_get_32(ef_buffer); - } - } + if (zde->uncomp_size == ZIP_UINT32_MAX) { + zde->uncomp_size = _zip_buffer_get_64(ef_buffer); + } + else if (local) { + /* From appnote.txt: This entry in the Local header MUST + include BOTH original and compressed file size fields. */ + (void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */ + } + if (zde->comp_size == ZIP_UINT32_MAX) { + zde->comp_size = _zip_buffer_get_64(ef_buffer); + } + if (!local) { + if (zde->offset == ZIP_UINT32_MAX) { + zde->offset = _zip_buffer_get_64(ef_buffer); + } + if (zde->disk_number == ZIP_UINT16_MAX) { + zde->disk_number = _zip_buffer_get_32(ef_buffer); + } + } - if (!_zip_buffer_eof(ef_buffer)) { - /* accept additional fields if values match */ - bool ok = true; - switch (got_len) { - case 28: - _zip_buffer_set_offset(ef_buffer, 24); - if (zde->disk_number != _zip_buffer_get_32(ef_buffer)) { - ok = false; - } - /* fallthrough */ - case 24: - _zip_buffer_set_offset(ef_buffer, 0); - if ((zde->uncomp_size != _zip_buffer_get_64(ef_buffer)) || (zde->comp_size != _zip_buffer_get_64(ef_buffer)) || (zde->offset != _zip_buffer_get_64(ef_buffer))) { - ok = false; - } - break; + if (!_zip_buffer_eof(ef_buffer)) { + /* accept additional fields if values match */ + bool ok = true; + switch (got_len) { + case 28: + _zip_buffer_set_offset(ef_buffer, 24); + if (zde->disk_number != _zip_buffer_get_32(ef_buffer)) { + ok = false; + } + /* fallthrough */ + case 24: + _zip_buffer_set_offset(ef_buffer, 0); + if ((zde->uncomp_size != _zip_buffer_get_64(ef_buffer)) || (zde->comp_size != _zip_buffer_get_64(ef_buffer)) || (zde->offset != _zip_buffer_get_64(ef_buffer))) { + ok = false; + } + break; - default: - ok = false; - } - if (!ok) { - zip_error_set(error, ZIP_ER_INCONS, 0); - _zip_buffer_free(ef_buffer); - if (!from_buffer) { - _zip_buffer_free(buffer); - } - return -1; - } - } - _zip_buffer_free(ef_buffer); + default: + ok = false; + } + if (!ok) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_ZIP64_EF); + _zip_buffer_free(ef_buffer); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + } + _zip_buffer_free(ef_buffer); } if (!_zip_buffer_ok(buffer)) { - zip_error_set(error, ZIP_ER_INTERNAL, 0); - if (!from_buffer) { - _zip_buffer_free(buffer); - } - return -1; + zip_error_set(error, ZIP_ER_INTERNAL, 0); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; } if (!from_buffer) { - _zip_buffer_free(buffer); + _zip_buffer_free(buffer); } /* zip_source_seek / zip_source_tell don't support values > ZIP_INT64_MAX */ if (zde->offset > ZIP_INT64_MAX) { - zip_error_set(error, ZIP_ER_SEEK, EFBIG); - return -1; + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return -1; } if (!_zip_dirent_process_winzip_aes(zde, error)) { - return -1; + return -1; } zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields); @@ -609,24 +609,24 @@ _zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL); if (ef == NULL || ef_len < 5 || ef[0] != 1) { - return str; + return str; } if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) { - return str; + return str; } _zip_buffer_get_8(buffer); ef_crc = _zip_buffer_get_32(buffer); if (_zip_string_crc32(str) == ef_crc) { - zip_uint16_t len = (zip_uint16_t)_zip_buffer_left(buffer); - zip_string_t *ef_str = _zip_string_new(_zip_buffer_get(buffer, len), len, ZIP_FL_ENC_UTF_8, NULL); + zip_uint16_t len = (zip_uint16_t)_zip_buffer_left(buffer); + zip_string_t *ef_str = _zip_string_new(_zip_buffer_get(buffer, len), len, ZIP_FL_ENC_UTF_8, NULL); - if (ef_str != NULL) { - _zip_string_free(str); - str = ef_str; - } + if (ef_str != NULL) { + _zip_string_free(str); + str = ef_str; + } } _zip_buffer_free(buffer); @@ -645,19 +645,19 @@ _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error) { if (de->comp_method != ZIP_CM_WINZIP_AES) { - return true; + return true; } ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, ZIP_EF_WINZIP_AES, 0, ZIP_EF_BOTH, NULL); if (ef == NULL || ef_len < 7) { - zip_error_set(error, ZIP_ER_INCONS, 0); - return false; + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF); + return false; } if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) { - zip_error_set(error, ZIP_ER_INTERNAL, 0); - return false; + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return false; } /* version */ @@ -665,48 +665,48 @@ _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error) { crc_valid = true; switch (_zip_buffer_get_16(buffer)) { case 1: - break; + break; case 2: - if (de->uncomp_size < 20 /* TODO: constant */) { - crc_valid = false; - } - break; + if (de->uncomp_size < 20 /* TODO: constant */) { + crc_valid = false; + } + break; default: - zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0); - _zip_buffer_free(buffer); - return false; + zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0); + _zip_buffer_free(buffer); + return false; } /* vendor */ if (memcmp(_zip_buffer_get(buffer, 2), "AE", 2) != 0) { - zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0); - _zip_buffer_free(buffer); - return false; + zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0); + _zip_buffer_free(buffer); + return false; } /* mode */ switch (_zip_buffer_get_8(buffer)) { case 1: - enc_method = ZIP_EM_AES_128; - break; + enc_method = ZIP_EM_AES_128; + break; case 2: - enc_method = ZIP_EM_AES_192; - break; + enc_method = ZIP_EM_AES_192; + break; case 3: - enc_method = ZIP_EM_AES_256; - break; + enc_method = ZIP_EM_AES_256; + break; default: - zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0); - _zip_buffer_free(buffer); - return false; + zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0); + _zip_buffer_free(buffer); + return false; } if (ef_len != 7) { - zip_error_set(error, ZIP_ER_INCONS, 0); - _zip_buffer_free(buffer); - return false; + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF); + _zip_buffer_free(buffer); + return false; } de->crc_valid = crc_valid; @@ -729,22 +729,22 @@ _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) { size = local ? LENTRYSIZE : CDENTRYSIZE; if (zip_source_seek(src, local ? 26 : 28, SEEK_CUR) < 0) { - _zip_error_set_from_source(error, src); - return -1; + _zip_error_set_from_source(error, src); + return -1; } if ((buffer = _zip_buffer_new_from_source(src, local ? 4 : 6, b, error)) == NULL) { - return -1; + return -1; } for (i = 0; i < (local ? 2 : 3); i++) { - size += _zip_buffer_get_16(buffer); + size += _zip_buffer_get_16(buffer); } if (!_zip_buffer_eof(buffer)) { - zip_error_set(error, ZIP_ER_INTERNAL, 0); - _zip_buffer_free(buffer); - return -1; + zip_error_set(error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(buffer); + return -1; } _zip_buffer_free(buffer); @@ -781,30 +781,30 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) { com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN); if ((name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_ASCII) || (name_enc == ZIP_ENCODING_ASCII && com_enc == ZIP_ENCODING_UTF8_KNOWN) || (name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_UTF8_KNOWN)) - de->bitflags |= ZIP_GPBF_ENCODING_UTF_8; + de->bitflags |= ZIP_GPBF_ENCODING_UTF_8; else { - de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8; - if (name_enc == ZIP_ENCODING_UTF8_KNOWN) { - ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, &za->error); - if (ef == NULL) - return -1; - } - if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN) { - zip_extra_field_t *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, &za->error); - if (ef2 == NULL) { - _zip_ef_free(ef); - return -1; - } - ef2->next = ef; - ef = ef2; - } + de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8; + if (name_enc == ZIP_ENCODING_UTF8_KNOWN) { + ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, &za->error); + if (ef == NULL) + return -1; + } + if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN) { + zip_extra_field_t *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, &za->error); + if (ef2 == NULL) { + _zip_ef_free(ef); + return -1; + } + ef2->next = ef; + ef = ef2; + } } if (de->encryption_method == ZIP_EM_NONE) { - de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED; + de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED; } else { - de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED; + de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED; } is_really_zip64 = _zip_dirent_needs_zip64(de, flags); @@ -812,94 +812,94 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) { is_winzip_aes = de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256; if (is_zip64) { - zip_uint8_t ef_zip64[EFZIP64SIZE]; - zip_buffer_t *ef_buffer = _zip_buffer_new(ef_zip64, sizeof(ef_zip64)); - if (ef_buffer == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - _zip_ef_free(ef); - return -1; - } + zip_uint8_t ef_zip64[EFZIP64SIZE]; + zip_buffer_t *ef_buffer = _zip_buffer_new(ef_zip64, sizeof(ef_zip64)); + if (ef_buffer == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_ef_free(ef); + return -1; + } - if (flags & ZIP_FL_LOCAL) { - if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) { - _zip_buffer_put_64(ef_buffer, de->uncomp_size); - _zip_buffer_put_64(ef_buffer, de->comp_size); - } - } - else { - if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) { - if (de->uncomp_size >= ZIP_UINT32_MAX) { - _zip_buffer_put_64(ef_buffer, de->uncomp_size); - } - if (de->comp_size >= ZIP_UINT32_MAX) { - _zip_buffer_put_64(ef_buffer, de->comp_size); - } - if (de->offset >= ZIP_UINT32_MAX) { - _zip_buffer_put_64(ef_buffer, de->offset); - } - } - } + if (flags & ZIP_FL_LOCAL) { + if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) { + _zip_buffer_put_64(ef_buffer, de->uncomp_size); + _zip_buffer_put_64(ef_buffer, de->comp_size); + } + } + else { + if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) { + if (de->uncomp_size >= ZIP_UINT32_MAX) { + _zip_buffer_put_64(ef_buffer, de->uncomp_size); + } + if (de->comp_size >= ZIP_UINT32_MAX) { + _zip_buffer_put_64(ef_buffer, de->comp_size); + } + if (de->offset >= ZIP_UINT32_MAX) { + _zip_buffer_put_64(ef_buffer, de->offset); + } + } + } - if (!_zip_buffer_ok(ef_buffer)) { - zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); - _zip_buffer_free(ef_buffer); - _zip_ef_free(ef); - return -1; - } + if (!_zip_buffer_ok(ef_buffer)) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(ef_buffer); + _zip_ef_free(ef); + return -1; + } - ef64 = _zip_ef_new(ZIP_EF_ZIP64, (zip_uint16_t)(_zip_buffer_offset(ef_buffer)), ef_zip64, ZIP_EF_BOTH); - _zip_buffer_free(ef_buffer); - ef64->next = ef; - ef = ef64; + ef64 = _zip_ef_new(ZIP_EF_ZIP64, (zip_uint16_t)(_zip_buffer_offset(ef_buffer)), ef_zip64, ZIP_EF_BOTH); + _zip_buffer_free(ef_buffer); + ef64->next = ef; + ef = ef64; } if (is_winzip_aes) { - zip_uint8_t data[EF_WINZIP_AES_SIZE]; - zip_buffer_t *ef_buffer = _zip_buffer_new(data, sizeof(data)); - zip_extra_field_t *ef_winzip; + zip_uint8_t data[EF_WINZIP_AES_SIZE]; + zip_buffer_t *ef_buffer = _zip_buffer_new(data, sizeof(data)); + zip_extra_field_t *ef_winzip; - if (ef_buffer == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - _zip_ef_free(ef); - return -1; - } + if (ef_buffer == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_ef_free(ef); + return -1; + } - _zip_buffer_put_16(ef_buffer, 2); - _zip_buffer_put(ef_buffer, "AE", 2); - _zip_buffer_put_8(ef_buffer, (zip_uint8_t)(de->encryption_method & 0xff)); - _zip_buffer_put_16(ef_buffer, (zip_uint16_t)de->comp_method); + _zip_buffer_put_16(ef_buffer, 2); + _zip_buffer_put(ef_buffer, "AE", 2); + _zip_buffer_put_8(ef_buffer, (zip_uint8_t)(de->encryption_method & 0xff)); + _zip_buffer_put_16(ef_buffer, (zip_uint16_t)de->comp_method); - if (!_zip_buffer_ok(ef_buffer)) { - zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); - _zip_buffer_free(ef_buffer); - _zip_ef_free(ef); - return -1; - } + if (!_zip_buffer_ok(ef_buffer)) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(ef_buffer); + _zip_ef_free(ef); + return -1; + } - ef_winzip = _zip_ef_new(ZIP_EF_WINZIP_AES, EF_WINZIP_AES_SIZE, data, ZIP_EF_BOTH); - _zip_buffer_free(ef_buffer); - ef_winzip->next = ef; - ef = ef_winzip; + ef_winzip = _zip_ef_new(ZIP_EF_WINZIP_AES, EF_WINZIP_AES_SIZE, data, ZIP_EF_BOTH); + _zip_buffer_free(ef_buffer); + ef_winzip->next = ef; + ef = ef_winzip; } if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - _zip_ef_free(ef); - return -1; + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_ef_free(ef); + return -1; } _zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4); if ((flags & ZIP_FL_LOCAL) == 0) { - _zip_buffer_put_16(buffer, de->version_madeby); + _zip_buffer_put_16(buffer, de->version_madeby); } _zip_buffer_put_16(buffer, ZIP_MAX(is_really_zip64 ? 45 : 0, de->version_needed)); _zip_buffer_put_16(buffer, de->bitflags); if (is_winzip_aes) { - _zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES); + _zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES); } else { - _zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method); + _zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method); } _zip_u2d_time(de->last_mod, &dostime, &dosdate); @@ -907,34 +907,34 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) { _zip_buffer_put_16(buffer, dosdate); if (is_winzip_aes && de->uncomp_size < 20) { - _zip_buffer_put_32(buffer, 0); + _zip_buffer_put_32(buffer, 0); } else { - _zip_buffer_put_32(buffer, de->crc); + _zip_buffer_put_32(buffer, de->crc); } if (((flags & ZIP_FL_LOCAL) == ZIP_FL_LOCAL) && ((de->comp_size >= ZIP_UINT32_MAX) || (de->uncomp_size >= ZIP_UINT32_MAX))) { - /* In local headers, if a ZIP64 EF is written, it MUST contain - * both compressed and uncompressed sizes (even if one of the - * two is smaller than 0xFFFFFFFF); on the other hand, those - * may only appear when the corresponding standard entry is - * 0xFFFFFFFF. (appnote.txt 4.5.3) */ - _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); - _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); + /* In local headers, if a ZIP64 EF is written, it MUST contain + * both compressed and uncompressed sizes (even if one of the + * two is smaller than 0xFFFFFFFF); on the other hand, those + * may only appear when the corresponding standard entry is + * 0xFFFFFFFF. (appnote.txt 4.5.3) */ + _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); + _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); } else { - if (de->comp_size < ZIP_UINT32_MAX) { - _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size); - } - else { - _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); - } - if (de->uncomp_size < ZIP_UINT32_MAX) { - _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size); - } - else { - _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); - } + if (de->comp_size < ZIP_UINT32_MAX) { + _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size); + } + else { + _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); + } + if (de->uncomp_size < ZIP_UINT32_MAX) { + _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size); + } + else { + _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); + } } _zip_buffer_put_16(buffer, _zip_string_length(de->filename)); @@ -943,57 +943,57 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) { _zip_buffer_put_16(buffer, (zip_uint16_t)ef_total_size); if ((flags & ZIP_FL_LOCAL) == 0) { - _zip_buffer_put_16(buffer, _zip_string_length(de->comment)); - _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number); - _zip_buffer_put_16(buffer, de->int_attrib); - _zip_buffer_put_32(buffer, de->ext_attrib); - if (de->offset < ZIP_UINT32_MAX) - _zip_buffer_put_32(buffer, (zip_uint32_t)de->offset); - else - _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); + _zip_buffer_put_16(buffer, _zip_string_length(de->comment)); + _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number); + _zip_buffer_put_16(buffer, de->int_attrib); + _zip_buffer_put_32(buffer, de->ext_attrib); + if (de->offset < ZIP_UINT32_MAX) + _zip_buffer_put_32(buffer, (zip_uint32_t)de->offset); + else + _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); } if (!_zip_buffer_ok(buffer)) { - zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); - _zip_buffer_free(buffer); - _zip_ef_free(ef); - return -1; + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(buffer); + _zip_ef_free(ef); + return -1; } if (_zip_write(za, buf, _zip_buffer_offset(buffer)) < 0) { - _zip_buffer_free(buffer); - _zip_ef_free(ef); - return -1; + _zip_buffer_free(buffer); + _zip_ef_free(ef); + return -1; } _zip_buffer_free(buffer); if (de->filename) { - if (_zip_string_write(za, de->filename) < 0) { - _zip_ef_free(ef); - return -1; - } + if (_zip_string_write(za, de->filename) < 0) { + _zip_ef_free(ef); + return -1; + } } if (ef) { - if (_zip_ef_write(za, ef, ZIP_EF_BOTH) < 0) { - _zip_ef_free(ef); - return -1; - } + if (_zip_ef_write(za, ef, ZIP_EF_BOTH) < 0) { + _zip_ef_free(ef); + return -1; + } } _zip_ef_free(ef); if (de->extra_fields) { - if (_zip_ef_write(za, de->extra_fields, flags) < 0) { - return -1; - } + if (_zip_ef_write(za, de->extra_fields, flags) < 0) { + return -1; + } } if ((flags & ZIP_FL_LOCAL) == 0) { - if (de->comment) { - if (_zip_string_write(za, de->comment) < 0) { - return -1; - } - } + if (de->comment) { + if (_zip_string_write(za, de->comment) < 0) { + return -1; + } + } } @@ -1030,18 +1030,18 @@ _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) { zip_extra_field_t *ef; if ((raw = _zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL)) == NULL) { - /* error already set */ - return NULL; + /* error already set */ + return NULL; } if (len + 5 > ZIP_UINT16_MAX) { - zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */ - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */ + return NULL; } if ((buffer = _zip_buffer_new(NULL, len + 5)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } _zip_buffer_put_8(buffer, 1); @@ -1049,9 +1049,9 @@ _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) { _zip_buffer_put(buffer, raw, len); if (!_zip_buffer_ok(buffer)) { - zip_error_set(error, ZIP_ER_INTERNAL, 0); - _zip_buffer_free(buffer); - return NULL; + zip_error_set(error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(buffer); + return NULL; } ef = _zip_ef_new(id, (zip_uint16_t)(_zip_buffer_offset(buffer)), _zip_buffer_data(buffer), ZIP_EF_BOTH); @@ -1064,26 +1064,26 @@ _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) { zip_dirent_t * _zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) { if (error == NULL) - error = &za->error; + error = &za->error; if (idx >= za->nentry) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } if ((flags & ZIP_FL_UNCHANGED) || za->entry[idx].changes == NULL) { - if (za->entry[idx].orig == NULL) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; - } - if (za->entry[idx].deleted && (flags & ZIP_FL_UNCHANGED) == 0) { - zip_error_set(error, ZIP_ER_DELETED, 0); - return NULL; - } - return za->entry[idx].orig; + if (za->entry[idx].orig == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + if (za->entry[idx].deleted && (flags & ZIP_FL_UNCHANGED) == 0) { + zip_error_set(error, ZIP_ER_DELETED, 0); + return NULL; + } + return za->entry[idx].orig; } else - return za->entry[idx].changes; + return za->entry[idx].changes; } @@ -1098,13 +1098,13 @@ _zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) { tpm = localtime(&intime); #endif if (tpm == NULL) { - /* if localtime() fails, return an arbitrary date (1980-01-01 00:00:00) */ - *ddate = (1 << 5) + 1; - *dtime = 0; - return; + /* if localtime() fails, return an arbitrary date (1980-01-01 00:00:00) */ + *ddate = (1 << 5) + 1; + *dtime = 0; + return; } if (tpm->tm_year < 80) { - tpm->tm_year = 80; + tpm->tm_year = 80; } *ddate = (zip_uint16_t)(((tpm->tm_year + 1900 - 1980) << 9) + ((tpm->tm_mon + 1) << 5) + tpm->tm_mday); @@ -1119,45 +1119,45 @@ _zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes zip_uint16_t length; if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) { - zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK; - de->bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask); + zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK; + de->bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask); } if (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) { - de->int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0); + de->int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0); } /* manually set attributes are preferred over attributes provided by source */ if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES)) { - de->ext_attrib = attributes->external_file_attributes; + de->ext_attrib = attributes->external_file_attributes; } if (de->comp_method == ZIP_CM_LZMA) { - de->version_needed = 63; + de->version_needed = 63; } else if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) { - de->version_needed = 51; + de->version_needed = 51; } else if (de->comp_method == ZIP_CM_BZIP2) { - de->version_needed = 46; + de->version_needed = 46; } else if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) { - de->version_needed = 45; + de->version_needed = 45; } else if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) { - de->version_needed = 20; + de->version_needed = 20; } else if ((length = _zip_string_length(de->filename)) > 0 && de->filename->raw[length - 1] == '/') { - de->version_needed = 20; + de->version_needed = 20; } else { - de->version_needed = 10; + de->version_needed = 10; } if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) { - de->version_needed = ZIP_MAX(de->version_needed, attributes->version_needed); + de->version_needed = ZIP_MAX(de->version_needed, attributes->version_needed); } de->version_madeby = 63 | (de->version_madeby & 0xff00); if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM)) { - de->version_madeby = (de->version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8); + de->version_madeby = (de->version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8); } } diff --git a/zip_discard.c b/zip_discard.c index 12f0636..42f4eb8 100644 --- a/zip_discard.c +++ b/zip_discard.c @@ -1,6 +1,6 @@ /* zip_discard.c -- discard and free struct zip - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -46,11 +46,11 @@ zip_discard(zip_t *za) { zip_uint64_t i; if (za == NULL) - return; + return; if (za->src) { - zip_source_close(za->src); - zip_source_free(za->src); + zip_source_close(za->src); + zip_source_free(za->src); } free(za->default_password); @@ -60,13 +60,13 @@ zip_discard(zip_t *za) { _zip_hash_free(za->names); if (za->entry) { - for (i = 0; i < za->nentry; i++) - _zip_entry_finalize(za->entry + i); - free(za->entry); + for (i = 0; i < za->nentry; i++) + _zip_entry_finalize(za->entry + i); + free(za->entry); } for (i = 0; i < za->nopen_source; i++) { - _zip_source_invalidate(za->open_source[i]); + _zip_source_invalidate(za->open_source[i]); } free(za->open_source); diff --git a/zip_entry.c b/zip_entry.c index 52ecaef..dfc6419 100644 --- a/zip_entry.c +++ b/zip_entry.c @@ -1,6 +1,6 @@ /* zip_entry.c -- struct zip_entry helper functions - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at diff --git a/zip_err_str.c b/zip_err_str.c index de141ff..b7b28dd 100644 --- a/zip_err_str.c +++ b/zip_err_str.c @@ -1,84 +1,77 @@ /* This file was generated automatically by CMake - from zip.h; make changes there. + from zip.h and zipint.h; make changes there. */ #include "zipint.h" -const char * const _zip_err_str[] = { - "No error", - "Multi-disk zip archives not supported", - "Renaming temporary file failed", - "Closing zip archive failed", - "Seek error", - "Read error", - "Write error", - "CRC error", - "Containing zip archive was closed", - "No such file", - "File already exists", - "Can't open file", - "Failure to create temporary file", - "Zlib error", - "Malloc failure", - "Entry has been changed", - "Compression method not supported", - "Premature end of file", - "Invalid argument", - "Not a zip archive", - "Internal error", - "Zip archive inconsistent", - "Can't remove file", - "Entry has been deleted", - "Encryption method not supported", - "Read-only archive", - "No password provided", - "Wrong password provided", - "Operation not supported", - "Resource still in use", - "Tell error", - "Compressed data invalid", - "Operation cancelled", -}; - -const int _zip_nerr_str = sizeof(_zip_err_str)/sizeof(_zip_err_str[0]); - +#define L ZIP_ET_LIBZIP #define N ZIP_ET_NONE #define S ZIP_ET_SYS #define Z ZIP_ET_ZLIB -const int _zip_err_type[] = { - N, - N, - S, - S, - S, - S, - S, - N, - N, - N, - N, - S, - S, - Z, - N, - N, - N, - N, - N, - N, - N, - N, - S, - N, - N, - N, - N, - N, - N, - N, - S, - N, - N, +#define E ZIP_DETAIL_ET_ENTRY +#define G ZIP_DETAIL_ET_GLOBAL + +const struct _zip_err_info _zip_err_str[] = { + { N, "No error" }, + { N, "Multi-disk zip archives not supported" }, + { S, "Renaming temporary file failed" }, + { S, "Closing zip archive failed" }, + { S, "Seek error" }, + { S, "Read error" }, + { S, "Write error" }, + { N, "CRC error" }, + { N, "Containing zip archive was closed" }, + { N, "No such file" }, + { N, "File already exists" }, + { S, "Can't open file" }, + { S, "Failure to create temporary file" }, + { Z, "Zlib error" }, + { N, "Malloc failure" }, + { N, "Entry has been changed" }, + { N, "Compression method not supported" }, + { N, "Premature end of file" }, + { N, "Invalid argument" }, + { N, "Not a zip archive" }, + { N, "Internal error" }, + { L, "Zip archive inconsistent" }, + { S, "Can't remove file" }, + { N, "Entry has been deleted" }, + { N, "Encryption method not supported" }, + { N, "Read-only archive" }, + { N, "No password provided" }, + { N, "Wrong password provided" }, + { N, "Operation not supported" }, + { N, "Resource still in use" }, + { S, "Tell error" }, + { N, "Compressed data invalid" }, + { N, "Operation cancelled" }, }; + +const int _zip_err_str_count = sizeof(_zip_err_str)/sizeof(_zip_err_str[0]); + +const struct _zip_err_info _zip_err_details[] = { + { G, "no detail" }, + { G, "central directory overlaps EOCD, or there is space between them" }, + { G, "archive comment length incorrect" }, + { G, "central directory length invalid" }, + { E, "central header invalid" }, + { G, "central directory count of entries is incorrect" }, + { E, "local and central headers do not match" }, + { G, "wrong EOCD length" }, + { G, "EOCD64 overlaps EOCD, or there is space between them" }, + { G, "EOCD64 magic incorrect" }, + { G, "EOCD64 and EOCD do not match" }, + { G, "invalid value in central directory" }, + { E, "variable size fields overflow header" }, + { E, "invalid UTF-8 in filename" }, + { E, "invalid UTF-8 in comment" }, + { E, "invalid Zip64 extra field" }, + { E, "invalid WinZip AES extra field" }, + { E, "garbage at end of extra fields" }, + { E, "extra field length is invalid" }, + { E, "file length in header doesn't match actual file length" }, +}; + +const int _zip_err_details_count = sizeof(_zip_err_details)/sizeof(_zip_err_details[0]); diff --git a/zip_error.c b/zip_error.c index a0f74f0..6c7e49f 100644 --- a/zip_error.c +++ b/zip_error.c @@ -1,6 +1,6 @@ /* zip_error.c -- zip_error_t helper functions - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -67,30 +67,31 @@ zip_error_init_with_code(zip_error_t *error, int ze) { zip_error_init(error); error->zip_err = ze; switch (zip_error_system_type(error)) { - case ZIP_ET_SYS: - error->sys_err = errno; - break; - - default: - error->sys_err = 0; - break; + case ZIP_ET_SYS: + case ZIP_ET_LIBZIP: + error->sys_err = errno; + break; + + default: + error->sys_err = 0; + break; } } ZIP_EXTERN int zip_error_system_type(const zip_error_t *error) { - if (error->zip_err < 0 || error->zip_err >= _zip_nerr_str) - return ZIP_ET_NONE; + if (error->zip_err < 0 || error->zip_err >= _zip_err_str_count) + return ZIP_ET_NONE; - return _zip_err_type[error->zip_err]; + return _zip_err_str[error->zip_err].type; } void _zip_error_clear(zip_error_t *err) { if (err == NULL) - return; + return; err->zip_err = ZIP_ER_OK; err->sys_err = 0; @@ -100,7 +101,7 @@ _zip_error_clear(zip_error_t *err) { void _zip_error_copy(zip_error_t *dst, const zip_error_t *src) { if (dst == NULL) { - return; + return; } dst->zip_err = src->zip_err; @@ -111,12 +112,12 @@ _zip_error_copy(zip_error_t *dst, const zip_error_t *src) { void _zip_error_get(const zip_error_t *err, int *zep, int *sep) { if (zep) - *zep = err->zip_err; + *zep = err->zip_err; if (sep) { - if (zip_error_system_type(err) != ZIP_ET_NONE) - *sep = err->sys_err; - else - *sep = 0; + if (zip_error_system_type(err) != ZIP_ET_NONE) + *sep = err->sys_err; + else + *sep = 0; } } @@ -124,8 +125,8 @@ _zip_error_get(const zip_error_t *err, int *zep, int *sep) { void zip_error_set(zip_error_t *err, int ze, int se) { if (err) { - err->zip_err = ze; - err->sys_err = se; + err->zip_err = ze; + err->sys_err = se; } } @@ -141,7 +142,7 @@ zip_error_to_data(const zip_error_t *error, void *data, zip_uint64_t length) { int *e = (int *)data; if (length < sizeof(int) * 2) { - return -1; + return -1; } e[0] = zip_error_code_zip(error); diff --git a/zip_error_clear.c b/zip_error_clear.c index eec1568..f655539 100644 --- a/zip_error_clear.c +++ b/zip_error_clear.c @@ -1,6 +1,6 @@ /* zip_error_clear.c -- clear zip error - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -38,7 +38,7 @@ ZIP_EXTERN void zip_error_clear(zip_t *za) { if (za == NULL) - return; + return; _zip_error_clear(&za->error); } diff --git a/zip_error_get.c b/zip_error_get.c index 9588b4c..f310ed3 100644 --- a/zip_error_get.c +++ b/zip_error_get.c @@ -1,6 +1,6 @@ /* zip_error_get.c -- get zip error - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at diff --git a/zip_error_get_sys_type.c b/zip_error_get_sys_type.c index 3dfe5c2..d9eb47a 100644 --- a/zip_error_get_sys_type.c +++ b/zip_error_get_sys_type.c @@ -1,6 +1,6 @@ /* zip_error_get_sys_type.c -- return type of system error code - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -37,8 +37,9 @@ ZIP_EXTERN int zip_error_get_sys_type(int ze) { - if (ze < 0 || ze >= _zip_nerr_str) - return 0; + if (ze < 0 || ze >= _zip_err_str_count) { + return 0; + } - return _zip_err_type[ze]; + return _zip_err_str[ze].type; } diff --git a/zip_error_strerror.c b/zip_error_strerror.c index 93b24ea..c283d88 100644 --- a/zip_error_strerror.c +++ b/zip_error_strerror.c @@ -1,6 +1,6 @@ /* zip_error_sterror.c -- get string representation of struct zip_error - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -39,45 +39,70 @@ #include "zipint.h" - ZIP_EXTERN const char * zip_error_strerror(zip_error_t *err) { - const char *zs, *ss; + const char *zip_error_string, *system_error_string; char buf[128], *s; zip_error_fini(err); - if (err->zip_err < 0 || err->zip_err >= _zip_nerr_str) { - sprintf(buf, "Unknown error %d", err->zip_err); - zs = NULL; - ss = buf; + if (err->zip_err < 0 || err->zip_err >= _zip_err_str_count) { + snprintf(buf, sizeof(buf), "Unknown error %d", err->zip_err); + buf[sizeof(buf) - 1] = '\0'; /* make sure string is NUL-terminated */ + zip_error_string = NULL; + system_error_string = buf; } else { - zs = _zip_err_str[err->zip_err]; + zip_error_string = _zip_err_str[err->zip_err].description; - switch (_zip_err_type[err->zip_err]) { - case ZIP_ET_SYS: - ss = strerror(err->sys_err); - break; - - case ZIP_ET_ZLIB: - ss = zError(err->sys_err); - break; - - default: - ss = NULL; - } + switch (_zip_err_str[err->zip_err].type) { + case ZIP_ET_SYS: + system_error_string = strerror(err->sys_err); + break; + + case ZIP_ET_ZLIB: + system_error_string = zError(err->sys_err); + break; + + case ZIP_ET_LIBZIP: { + zip_uint8_t error = GET_ERROR_FROM_DETAIL(err->sys_err); + int index = GET_INDEX_FROM_DETAIL(err->sys_err); + + if (error == 0) { + system_error_string = NULL; + } + else if (error >= _zip_err_details_count) { + snprintf(buf, sizeof(buf), "invalid detail error %u", error); + buf[sizeof(buf) - 1] = '\0'; /* make sure string is NUL-terminated */ + system_error_string = buf; + } + else if (_zip_err_details[error].type == ZIP_DETAIL_ET_ENTRY && index < MAX_DETAIL_INDEX) { + snprintf(buf, sizeof(buf), "entry %d: %s", index, _zip_err_details[error].description); + buf[sizeof(buf) - 1] = '\0'; /* make sure string is NUL-terminated */ + system_error_string = buf; + } + else { + system_error_string = _zip_err_details[error].description; + } + break; + } + + default: + system_error_string = NULL; + } } - if (ss == NULL) - return zs; + if (system_error_string == NULL) { + return zip_error_string; + } else { - if ((s = (char *)malloc(strlen(ss) + (zs ? strlen(zs) + 2 : 0) + 1)) == NULL) - return _zip_err_str[ZIP_ER_MEMORY]; + if ((s = (char *)malloc(strlen(system_error_string) + (zip_error_string ? strlen(zip_error_string) + 2 : 0) + 1)) == NULL) { + return _zip_err_str[ZIP_ER_MEMORY].description; + } - sprintf(s, "%s%s%s", (zs ? zs : ""), (zs ? ": " : ""), ss); - err->str = s; + sprintf(s, "%s%s%s", (zip_error_string ? zip_error_string : ""), (zip_error_string ? ": " : ""), system_error_string); + err->str = s; - return s; + return s; } } diff --git a/zip_error_to_str.c b/zip_error_to_str.c index 34a3331..f13ac19 100644 --- a/zip_error_to_str.c +++ b/zip_error_to_str.c @@ -1,6 +1,6 @@ /* zip_error_to_str.c -- get string representation of zip error code - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -44,22 +44,23 @@ ZIP_EXTERN int zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se) { const char *zs, *ss; - if (ze < 0 || ze >= _zip_nerr_str) - return snprintf(buf, len, "Unknown error %d", ze); + if (ze < 0 || ze >= _zip_err_str_count) { + return snprintf(buf, len, "Unknown error %d", ze); + } - zs = _zip_err_str[ze]; + zs = _zip_err_str[ze].description; - switch (_zip_err_type[ze]) { - case ZIP_ET_SYS: - ss = strerror(se); - break; - - case ZIP_ET_ZLIB: - ss = zError(se); - break; - - default: - ss = NULL; + switch (_zip_err_str[ze].type) { + case ZIP_ET_SYS: + ss = strerror(se); + break; + + case ZIP_ET_ZLIB: + ss = zError(se); + break; + + default: + ss = NULL; } return snprintf(buf, len, "%s%s%s", zs, (ss ? ": " : ""), (ss ? ss : "")); diff --git a/zip_extra_field.c b/zip_extra_field.c index 7114a25..8983f75 100644 --- a/zip_extra_field.c +++ b/zip_extra_field.c @@ -1,6 +1,6 @@ /* zip_extra_field.c -- manipulate extra fields - Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -44,19 +44,19 @@ _zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error) { head = prev = NULL; while (ef) { - if ((def = _zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - _zip_ef_free(head); - return NULL; - } + if ((def = _zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + _zip_ef_free(head); + return NULL; + } - if (head == NULL) - head = def; - if (prev) - prev->next = def; - prev = def; + if (head == NULL) + head = def; + if (prev) + prev->next = def; + prev = def; - ef = ef->next; + ef = ef->next; } return head; @@ -72,27 +72,27 @@ _zip_ef_delete_by_id(zip_extra_field_t *ef, zip_uint16_t id, zip_uint16_t id_idx head = ef; prev = NULL; for (; ef; ef = (prev ? prev->next : head)) { - if ((ef->flags & flags & ZIP_EF_BOTH) && ((ef->id == id) || (id == ZIP_EXTRA_FIELD_ALL))) { - if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) { - ef->flags &= ~(flags & ZIP_EF_BOTH); - if ((ef->flags & ZIP_EF_BOTH) == 0) { - if (prev) - prev->next = ef->next; - else - head = ef->next; - ef->next = NULL; - _zip_ef_free(ef); + if ((ef->flags & flags & ZIP_EF_BOTH) && ((ef->id == id) || (id == ZIP_EXTRA_FIELD_ALL))) { + if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) { + ef->flags &= ~(flags & ZIP_EF_BOTH); + if ((ef->flags & ZIP_EF_BOTH) == 0) { + if (prev) + prev->next = ef->next; + else + head = ef->next; + ef->next = NULL; + _zip_ef_free(ef); - if (id_idx == ZIP_EXTRA_FIELD_ALL) - continue; - } - } + if (id_idx == ZIP_EXTRA_FIELD_ALL) + continue; + } + } - i++; - if (i > id_idx) - break; - } - prev = ef; + i++; + if (i > id_idx) + break; + } + prev = ef; } return head; @@ -104,10 +104,10 @@ _zip_ef_free(zip_extra_field_t *ef) { zip_extra_field_t *ef2; while (ef) { - ef2 = ef->next; - free(ef->data); - free(ef); - ef = ef2; + ef2 = ef->next; + free(ef->data); + free(ef); + ef = ef2; } } @@ -120,19 +120,19 @@ _zip_ef_get_by_id(const zip_extra_field_t *ef, zip_uint16_t *lenp, zip_uint16_t i = 0; for (; ef; ef = ef->next) { - if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) { - if (i < id_idx) { - i++; - continue; - } + if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) { + if (i < id_idx) { + i++; + continue; + } - if (lenp) - *lenp = ef->size; - if (ef->size > 0) - return ef->data; - else - return empty; - } + if (lenp) + *lenp = ef->size; + if (ef->size > 0) + return ef->data; + else + return empty; + } } zip_error_set(error, ZIP_ER_NOENT, 0); @@ -146,28 +146,28 @@ _zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from) { int duplicate; if (to == NULL) - return from; + return from; for (tail = to; tail->next; tail = tail->next) - ; + ; for (; from; from = ef2) { - ef2 = from->next; + ef2 = from->next; - duplicate = 0; - for (tt = to; tt; tt = tt->next) { - if (tt->id == from->id && tt->size == from->size && (tt->size == 0 || memcmp(tt->data, from->data, tt->size) == 0)) { - tt->flags |= (from->flags & ZIP_EF_BOTH); - duplicate = 1; - break; - } - } + duplicate = 0; + for (tt = to; tt; tt = tt->next) { + if (tt->id == from->id && tt->size == from->size && (tt->size == 0 || memcmp(tt->data, from->data, tt->size) == 0)) { + tt->flags |= (from->flags & ZIP_EF_BOTH); + duplicate = 1; + break; + } + } - from->next = NULL; - if (duplicate) - _zip_ef_free(from); - else - tail = tail->next = from; + from->next = NULL; + if (duplicate) + _zip_ef_free(from); + else + tail = tail->next = from; } return to; @@ -179,20 +179,20 @@ _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_fla zip_extra_field_t *ef; if ((ef = (zip_extra_field_t *)malloc(sizeof(*ef))) == NULL) - return NULL; + return NULL; ef->next = NULL; ef->flags = flags; ef->id = id; ef->size = size; if (size > 0) { - if ((ef->data = (zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) { - free(ef); - return NULL; - } + if ((ef->data = (zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) { + free(ef); + return NULL; + } } else - ef->data = NULL; + ef->data = NULL; return ef; } @@ -204,63 +204,63 @@ _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_ zip_extra_field_t *ef, *ef2, *ef_head; if ((buffer = _zip_buffer_new((zip_uint8_t *)data, len)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return false; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; } ef_head = ef = NULL; while (_zip_buffer_ok(buffer) && _zip_buffer_left(buffer) >= 4) { - zip_uint16_t fid, flen; - zip_uint8_t *ef_data; + zip_uint16_t fid, flen; + zip_uint8_t *ef_data; - fid = _zip_buffer_get_16(buffer); - flen = _zip_buffer_get_16(buffer); - ef_data = _zip_buffer_get(buffer, flen); + fid = _zip_buffer_get_16(buffer); + flen = _zip_buffer_get_16(buffer); + ef_data = _zip_buffer_get(buffer, flen); - if (ef_data == NULL) { - zip_error_set(error, ZIP_ER_INCONS, 0); - _zip_buffer_free(buffer); - _zip_ef_free(ef_head); - return false; - } + if (ef_data == NULL) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_EF_LENGTH); + _zip_buffer_free(buffer); + _zip_ef_free(ef_head); + return false; + } - if ((ef2 = _zip_ef_new(fid, flen, ef_data, flags)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - _zip_buffer_free(buffer); - _zip_ef_free(ef_head); - return false; - } + if ((ef2 = _zip_ef_new(fid, flen, ef_data, flags)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + _zip_buffer_free(buffer); + _zip_ef_free(ef_head); + return false; + } - if (ef_head) { - ef->next = ef2; - ef = ef2; - } - else - ef_head = ef = ef2; + if (ef_head) { + ef->next = ef2; + ef = ef2; + } + else + ef_head = ef = ef2; } if (!_zip_buffer_eof(buffer)) { - /* Android APK files align stored file data with padding in extra fields; ignore. */ - /* see https://android.googlesource.com/platform/build/+/master/tools/zipalign/ZipAlign.cpp */ - size_t glen = _zip_buffer_left(buffer); - zip_uint8_t *garbage; - garbage = _zip_buffer_get(buffer, glen); - if (glen >= 4 || garbage == NULL || memcmp(garbage, "\0\0\0", glen) != 0) { - zip_error_set(error, ZIP_ER_INCONS, 0); - _zip_buffer_free(buffer); - _zip_ef_free(ef_head); - return false; - } + /* Android APK files align stored file data with padding in extra fields; ignore. */ + /* see https://android.googlesource.com/platform/build/+/master/tools/zipalign/ZipAlign.cpp */ + size_t glen = _zip_buffer_left(buffer); + zip_uint8_t *garbage; + garbage = _zip_buffer_get(buffer, glen); + if (glen >= 4 || garbage == NULL || memcmp(garbage, "\0\0\0", glen) != 0) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EF_TRAILING_GARBAGE); + _zip_buffer_free(buffer); + _zip_ef_free(ef_head); + return false; + } } _zip_buffer_free(buffer); if (ef_head_p) { - *ef_head_p = ef_head; + *ef_head_p = ef_head; } else { - _zip_ef_free(ef_head); + _zip_ef_free(ef_head); } return true; @@ -276,20 +276,20 @@ _zip_ef_remove_internal(zip_extra_field_t *ef) { prev = NULL; while (ef) { - if (ZIP_EF_IS_INTERNAL(ef->id)) { - next = ef->next; - if (ef_head == ef) - ef_head = next; - ef->next = NULL; - _zip_ef_free(ef); - if (prev) - prev->next = next; - ef = next; - } - else { - prev = ef; - ef = ef->next; - } + if (ZIP_EF_IS_INTERNAL(ef->id)) { + next = ef->next; + if (ef_head == ef) + ef_head = next; + ef->next = NULL; + _zip_ef_free(ef); + if (prev) + prev->next = next; + ef = next; + } + else { + prev = ef; + ef = ef->next; + } } return ef_head; @@ -302,8 +302,8 @@ _zip_ef_size(const zip_extra_field_t *ef, zip_flags_t flags) { size = 0; for (; ef; ef = ef->next) { - if (ef->flags & flags & ZIP_EF_BOTH) - size = (zip_uint16_t)(size + 4 + ef->size); + if (ef->flags & flags & ZIP_EF_BOTH) + size = (zip_uint16_t)(size + 4 + ef->size); } return size; @@ -316,30 +316,30 @@ _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags) { zip_buffer_t *buffer = _zip_buffer_new(b, sizeof(b)); if (buffer == NULL) { - return -1; + return -1; } for (; ef; ef = ef->next) { - if (ef->flags & flags & ZIP_EF_BOTH) { - _zip_buffer_set_offset(buffer, 0); - _zip_buffer_put_16(buffer, ef->id); - _zip_buffer_put_16(buffer, ef->size); - if (!_zip_buffer_ok(buffer)) { - zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); - _zip_buffer_free(buffer); - return -1; - } - if (_zip_write(za, b, 4) < 0) { - _zip_buffer_free(buffer); - return -1; - } - if (ef->size > 0) { - if (_zip_write(za, ef->data, ef->size) < 0) { - _zip_buffer_free(buffer); - return -1; - } - } - } + if (ef->flags & flags & ZIP_EF_BOTH) { + _zip_buffer_set_offset(buffer, 0); + _zip_buffer_put_16(buffer, ef->id); + _zip_buffer_put_16(buffer, ef->size); + if (!_zip_buffer_ok(buffer)) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(buffer); + return -1; + } + if (_zip_write(za, b, 4) < 0) { + _zip_buffer_free(buffer); + return -1; + } + if (ef->size > 0) { + if (_zip_write(za, ef->data, ef->size) < 0) { + _zip_buffer_free(buffer); + return -1; + } + } + } } _zip_buffer_free(buffer); @@ -355,71 +355,71 @@ _zip_read_local_ef(zip_t *za, zip_uint64_t idx) { zip_uint16_t fname_len, ef_len; if (idx >= za->nentry) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } e = za->entry + idx; if (e->orig == NULL || e->orig->local_extra_fields_read) - return 0; + return 0; if (e->orig->offset + 26 > ZIP_INT64_MAX) { - zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG); - return -1; + zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG); + return -1; } if (zip_source_seek(za->src, (zip_int64_t)(e->orig->offset + 26), SEEK_SET) < 0) { - _zip_error_set_from_source(&za->error, za->src); - return -1; + _zip_error_set_from_source(&za->error, za->src); + return -1; } if ((buffer = _zip_buffer_new_from_source(za->src, sizeof(b), b, &za->error)) == NULL) { - return -1; + return -1; } fname_len = _zip_buffer_get_16(buffer); ef_len = _zip_buffer_get_16(buffer); if (!_zip_buffer_eof(buffer)) { - _zip_buffer_free(buffer); - zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); - return -1; + _zip_buffer_free(buffer); + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; } _zip_buffer_free(buffer); if (ef_len > 0) { - zip_extra_field_t *ef; - zip_uint8_t *ef_raw; + zip_extra_field_t *ef; + zip_uint8_t *ef_raw; - if (zip_source_seek(za->src, fname_len, SEEK_CUR) < 0) { - zip_error_set(&za->error, ZIP_ER_SEEK, errno); - return -1; - } + if (zip_source_seek(za->src, fname_len, SEEK_CUR) < 0) { + zip_error_set(&za->error, ZIP_ER_SEEK, errno); + return -1; + } - ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error); + ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error); - if (ef_raw == NULL) - return -1; + if (ef_raw == NULL) + return -1; - if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) { - free(ef_raw); - return -1; - } - free(ef_raw); + if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) { + free(ef_raw); + return -1; + } + free(ef_raw); - if (ef) { - ef = _zip_ef_remove_internal(ef); - e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef); - } + if (ef) { + ef = _zip_ef_remove_internal(ef); + e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef); + } } e->orig->local_extra_fields_read = 1; if (e->changes && e->changes->local_extra_fields_read == 0) { - e->changes->extra_fields = e->orig->extra_fields; - e->changes->local_extra_fields_read = 1; + e->changes->extra_fields = e->orig->extra_fields; + e->changes->local_extra_fields_read = 1; } return 0; diff --git a/zip_extra_field_api.c b/zip_extra_field_api.c index 605f95d..9a828e4 100644 --- a/zip_extra_field_api.c +++ b/zip_extra_field_api.c @@ -1,6 +1,6 @@ /* zip_extra_field_api.c -- public extra fields API functions - Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,25 +40,25 @@ zip_file_extra_field_delete(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zi zip_dirent_t *de; if ((flags & ZIP_EF_BOTH) == 0) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if (_zip_get_dirent(za, idx, 0, NULL) == NULL) - return -1; + return -1; if (ZIP_IS_RDONLY(za)) { - zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; } if (_zip_file_extra_field_prepare_for_change(za, idx) < 0) - return -1; + return -1; de = za->entry[idx].changes; @@ -72,25 +72,25 @@ zip_file_extra_field_delete_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_i zip_dirent_t *de; if ((flags & ZIP_EF_BOTH) == 0) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if (_zip_get_dirent(za, idx, 0, NULL) == NULL) - return -1; + return -1; if (ZIP_IS_RDONLY(za)) { - zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; } if (_zip_file_extra_field_prepare_for_change(za, idx) < 0) - return -1; + return -1; de = za->entry[idx].changes; @@ -108,34 +108,34 @@ zip_file_extra_field_get(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_u int i; if ((flags & ZIP_EF_BOTH) == 0) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; } if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL) - return NULL; + return NULL; if (flags & ZIP_FL_LOCAL) - if (_zip_read_local_ef(za, idx) < 0) - return NULL; + if (_zip_read_local_ef(za, idx) < 0) + return NULL; i = 0; for (ef = de->extra_fields; ef; ef = ef->next) { - if (ef->flags & flags & ZIP_EF_BOTH) { - if (i < ef_idx) { - i++; - continue; - } + if (ef->flags & flags & ZIP_EF_BOTH) { + if (i < ef_idx) { + i++; + continue; + } - if (idp) - *idp = ef->id; - if (lenp) - *lenp = ef->size; - if (ef->size > 0) - return ef->data; - else - return empty; - } + if (idp) + *idp = ef->id; + if (lenp) + *lenp = ef->size; + if (ef->size > 0) + return ef->data; + else + return empty; + } } zip_error_set(&za->error, ZIP_ER_NOENT, 0); @@ -148,16 +148,16 @@ zip_file_extra_field_get_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_dirent_t *de; if ((flags & ZIP_EF_BOTH) == 0) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; } if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL) - return NULL; + return NULL; if (flags & ZIP_FL_LOCAL) - if (_zip_read_local_ef(za, idx) < 0) - return NULL; + if (_zip_read_local_ef(za, idx) < 0) + return NULL; return _zip_ef_get_by_id(de->extra_fields, lenp, ef_id, ef_idx, flags, &za->error); } @@ -170,21 +170,21 @@ zip_file_extra_fields_count(zip_t *za, zip_uint64_t idx, zip_flags_t flags) { zip_uint16_t n; if ((flags & ZIP_EF_BOTH) == 0) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL) - return -1; + return -1; if (flags & ZIP_FL_LOCAL) - if (_zip_read_local_ef(za, idx) < 0) - return -1; + if (_zip_read_local_ef(za, idx) < 0) + return -1; n = 0; for (ef = de->extra_fields; ef; ef = ef->next) - if (ef->flags & flags & ZIP_EF_BOTH) - n++; + if (ef->flags & flags & ZIP_EF_BOTH) + n++; return (zip_int16_t)n; } @@ -197,21 +197,21 @@ zip_file_extra_fields_count_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_i zip_uint16_t n; if ((flags & ZIP_EF_BOTH) == 0) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL) - return -1; + return -1; if (flags & ZIP_FL_LOCAL) - if (_zip_read_local_ef(za, idx) < 0) - return -1; + if (_zip_read_local_ef(za, idx) < 0) + return -1; n = 0; for (ef = de->extra_fields; ef; ef = ef->next) - if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) - n++; + if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) + n++; return (zip_int16_t)n; } @@ -225,25 +225,25 @@ zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_ui int i, found, new_len; if ((flags & ZIP_EF_BOTH) == 0) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if (_zip_get_dirent(za, idx, 0, NULL) == NULL) - return -1; + return -1; if (ZIP_IS_RDONLY(za)) { - zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; } if (ZIP_EF_IS_INTERNAL(ef_id)) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if (_zip_file_extra_field_prepare_for_change(za, idx) < 0) - return -1; + return -1; de = za->entry[idx].changes; @@ -253,67 +253,67 @@ zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_ui found = 0; for (; ef; ef = ef->next) { - if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) { - if (i == ef_idx) { - found = 1; - break; - } - i++; - } - ef_prev = ef; + if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) { + if (i == ef_idx) { + found = 1; + break; + } + i++; + } + ef_prev = ef; } if (i < ef_idx && ef_idx != ZIP_EXTRA_FIELD_NEW) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if (flags & ZIP_EF_LOCAL) - ls = _zip_ef_size(de->extra_fields, ZIP_EF_LOCAL); + ls = _zip_ef_size(de->extra_fields, ZIP_EF_LOCAL); else - ls = 0; + ls = 0; if (flags & ZIP_EF_CENTRAL) - cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL); + cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL); else - cs = 0; + cs = 0; new_len = ls > cs ? ls : cs; if (found) - new_len -= ef->size + 4; + new_len -= ef->size + 4; new_len += len + 4; if (new_len > ZIP_UINT16_MAX) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if ((ef_new = _zip_ef_new(ef_id, len, data, flags)) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; } if (found) { - if ((ef->flags & ZIP_EF_BOTH) == (flags & ZIP_EF_BOTH)) { - ef_new->next = ef->next; - ef->next = NULL; - _zip_ef_free(ef); - if (ef_prev) - ef_prev->next = ef_new; - else - de->extra_fields = ef_new; - } - else { - ef->flags &= ~(flags & ZIP_EF_BOTH); - ef_new->next = ef->next; - ef->next = ef_new; - } + if ((ef->flags & ZIP_EF_BOTH) == (flags & ZIP_EF_BOTH)) { + ef_new->next = ef->next; + ef->next = NULL; + _zip_ef_free(ef); + if (ef_prev) + ef_prev->next = ef_new; + else + de->extra_fields = ef_new; + } + else { + ef->flags &= ~(flags & ZIP_EF_BOTH); + ef_new->next = ef->next; + ef->next = ef_new; + } } else if (ef_prev) { - ef_new->next = ef_prev->next; - ef_prev->next = ef_new; + ef_new->next = ef_prev->next; + ef_prev->next = ef_new; } else - de->extra_fields = ef_new; + de->extra_fields = ef_new; return 0; } @@ -324,30 +324,30 @@ _zip_file_extra_field_prepare_for_change(zip_t *za, zip_uint64_t idx) { zip_entry_t *e; if (idx >= za->nentry) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } e = za->entry + idx; if (e->changes && (e->changes->changed & ZIP_DIRENT_EXTRA_FIELD)) - return 0; + return 0; if (e->orig) { - if (_zip_read_local_ef(za, idx) < 0) - return -1; + if (_zip_read_local_ef(za, idx) < 0) + return -1; } if (e->changes == NULL) { - if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; - } + if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } } if (e->orig && e->orig->extra_fields) { - if ((e->changes->extra_fields = _zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL) - return -1; + if ((e->changes->extra_fields = _zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL) + return -1; } e->changes->changed |= ZIP_DIRENT_EXTRA_FIELD; diff --git a/zip_fclose.c b/zip_fclose.c index 6eb9dc9..3984b98 100644 --- a/zip_fclose.c +++ b/zip_fclose.c @@ -1,6 +1,6 @@ /* zip_fclose.c -- close file in zip archive - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -42,11 +42,11 @@ zip_fclose(zip_file_t *zf) { int ret; if (zf->src) - zip_source_free(zf->src); + zip_source_free(zf->src); ret = 0; if (zf->error.zip_err) - ret = zf->error.zip_err; + ret = zf->error.zip_err; zip_error_fini(&zf->error); free(zf); diff --git a/zip_fdopen.c b/zip_fdopen.c index 5a732cd..c2708c6 100644 --- a/zip_fdopen.c +++ b/zip_fdopen.c @@ -1,6 +1,6 @@ /* zip_fdopen.c -- open read-only archive from file descriptor - Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -47,37 +47,37 @@ zip_fdopen(int fd_orig, int _flags, int *zep) { struct zip_error error; if (_flags < 0 || (_flags & ~(ZIP_CHECKCONS | ZIP_RDONLY))) { - _zip_set_open_error(zep, NULL, ZIP_ER_INVAL); - return NULL; + _zip_set_open_error(zep, NULL, ZIP_ER_INVAL); + return NULL; } /* We dup() here to avoid messing with the passed in fd. We could not restore it to the original state in case of error. */ if ((fd = dup(fd_orig)) < 0) { - _zip_set_open_error(zep, NULL, ZIP_ER_OPEN); - return NULL; + _zip_set_open_error(zep, NULL, ZIP_ER_OPEN); + return NULL; } if ((fp = fdopen(fd, "rb")) == NULL) { - close(fd); - _zip_set_open_error(zep, NULL, ZIP_ER_OPEN); - return NULL; + close(fd); + _zip_set_open_error(zep, NULL, ZIP_ER_OPEN); + return NULL; } zip_error_init(&error); if ((src = zip_source_filep_create(fp, 0, -1, &error)) == NULL) { - fclose(fp); - _zip_set_open_error(zep, &error, 0); - zip_error_fini(&error); - return NULL; + fclose(fp); + _zip_set_open_error(zep, &error, 0); + zip_error_fini(&error); + return NULL; } if ((za = zip_open_from_source(src, _flags, &error)) == NULL) { - zip_source_free(src); - _zip_set_open_error(zep, &error, 0); - zip_error_fini(&error); - return NULL; + zip_source_free(src); + _zip_set_open_error(zep, &error, 0); + zip_error_fini(&error); + return NULL; } zip_error_fini(&error); diff --git a/zip_file_add.c b/zip_file_add.c index c019d8d..02b6599 100644 --- a/zip_file_add.c +++ b/zip_file_add.c @@ -1,6 +1,6 @@ /* zip_file_add.c -- add file via callback function - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -36,16 +36,16 @@ /* NOTE: Return type is signed so we can return -1 on error. - The index can not be larger than ZIP_INT64_MAX since the size - of the central directory cannot be larger than - ZIP_UINT64_MAX, and each entry is larger than 2 bytes. + The index can not be larger than ZIP_INT64_MAX since the size + of the central directory cannot be larger than + ZIP_UINT64_MAX, and each entry is larger than 2 bytes. */ ZIP_EXTERN zip_int64_t zip_file_add(zip_t *za, const char *name, zip_source_t *source, zip_flags_t flags) { if (name == NULL || source == NULL) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } return _zip_file_replace(za, ZIP_UINT64_MAX, name, source, flags); diff --git a/zip_file_error_clear.c b/zip_file_error_clear.c index 47e5da6..b47e3d2 100644 --- a/zip_file_error_clear.c +++ b/zip_file_error_clear.c @@ -1,6 +1,6 @@ /* zip_file_error_clear.c -- clear zip file error - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -38,7 +38,7 @@ ZIP_EXTERN void zip_file_error_clear(zip_file_t *zf) { if (zf == NULL) - return; + return; _zip_error_clear(&zf->error); } diff --git a/zip_file_error_get.c b/zip_file_error_get.c index 1ed68df..cce1ac2 100644 --- a/zip_file_error_get.c +++ b/zip_file_error_get.c @@ -1,6 +1,6 @@ /* zip_file_error_get.c -- get zip file error - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at diff --git a/zip_file_get_comment.c b/zip_file_get_comment.c index 8f68141..59b768a 100644 --- a/zip_file_get_comment.c +++ b/zip_file_get_comment.c @@ -1,6 +1,6 @@ /* zip_file_get_comment.c -- get file comment - Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -43,13 +43,13 @@ zip_file_get_comment(zip_t *za, zip_uint64_t idx, zip_uint32_t *lenp, zip_flags_ const zip_uint8_t *str; if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL) - return NULL; + return NULL; if ((str = _zip_string_get(de->comment, &len, flags, &za->error)) == NULL) - return NULL; + return NULL; if (lenp) - *lenp = len; + *lenp = len; return (const char *)str; } diff --git a/zip_file_get_external_attributes.c b/zip_file_get_external_attributes.c index ebc2058..f642918 100644 --- a/zip_file_get_external_attributes.c +++ b/zip_file_get_external_attributes.c @@ -1,6 +1,6 @@ /* zip_file_get_external_attributes.c -- get opsys/external attributes - Copyright (C) 2013-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2013-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -38,13 +38,13 @@ zip_file_get_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_dirent_t *de; if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL) - return -1; + return -1; if (opsys) - *opsys = (zip_uint8_t)((de->version_madeby >> 8) & 0xff); + *opsys = (zip_uint8_t)((de->version_madeby >> 8) & 0xff); if (attributes) - *attributes = de->ext_attrib; + *attributes = de->ext_attrib; return 0; } diff --git a/zip_file_get_offset.c b/zip_file_get_offset.c index 2cf4480..c9c8fd8 100644 --- a/zip_file_get_offset.c +++ b/zip_file_get_offset.c @@ -1,6 +1,6 @@ /* zip_file_get_offset.c -- get offset of file data in archive. - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -50,24 +50,24 @@ _zip_file_get_offset(const zip_t *za, zip_uint64_t idx, zip_error_t *error) { zip_int32_t size; if (za->entry[idx].orig == NULL) { - zip_error_set(error, ZIP_ER_INTERNAL, 0); - return 0; + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return 0; } offset = za->entry[idx].orig->offset; if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) { - _zip_error_set_from_source(error, za->src); - return 0; + _zip_error_set_from_source(error, za->src); + return 0; } /* TODO: cache? */ if ((size = _zip_dirent_size(za->src, ZIP_EF_LOCAL, error)) < 0) - return 0; + return 0; if (offset + (zip_uint32_t)size > ZIP_INT64_MAX) { - zip_error_set(error, ZIP_ER_SEEK, EFBIG); - return 0; + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return 0; } return offset + (zip_uint32_t)size; @@ -79,38 +79,38 @@ _zip_file_get_end(const zip_t *za, zip_uint64_t index, zip_error_t *error) { zip_dirent_t *entry; if ((offset = _zip_file_get_offset(za, index, error)) == 0) { - return 0; + return 0; } entry = za->entry[index].orig; if (offset + entry->comp_size < offset || offset + entry->comp_size > ZIP_INT64_MAX) { - zip_error_set(error, ZIP_ER_SEEK, EFBIG); - return 0; + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return 0; } offset += entry->comp_size; if (entry->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) { - zip_uint8_t buf[4]; - if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) { - _zip_error_set_from_source(error, za->src); - return 0; - } - if (zip_source_read(za->src, buf, 4) != 4) { - _zip_error_set_from_source(error, za->src); - return 0; - } - if (memcmp(buf, DATADES_MAGIC, 4) == 0) { - offset += 4; - } - offset += 12; - if (_zip_dirent_needs_zip64(entry, 0)) { - offset += 8; - } - if (offset > ZIP_INT64_MAX) { - zip_error_set(error, ZIP_ER_SEEK, EFBIG); - return 0; - } + zip_uint8_t buf[4]; + if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) { + _zip_error_set_from_source(error, za->src); + return 0; + } + if (zip_source_read(za->src, buf, 4) != 4) { + _zip_error_set_from_source(error, za->src); + return 0; + } + if (memcmp(buf, DATADES_MAGIC, 4) == 0) { + offset += 4; + } + offset += 12; + if (_zip_dirent_needs_zip64(entry, 0)) { + offset += 8; + } + if (offset > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return 0; + } } return offset; diff --git a/zip_file_rename.c b/zip_file_rename.c index 7ca428c..d65f64a 100644 --- a/zip_file_rename.c +++ b/zip_file_rename.c @@ -1,6 +1,6 @@ /* zip_file_rename.c -- rename file in zip archive - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -43,24 +43,24 @@ zip_file_rename(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags int old_is_dir, new_is_dir; if (idx >= za->nentry || (name != NULL && strlen(name) > ZIP_UINT16_MAX)) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if (ZIP_IS_RDONLY(za)) { - zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; } if ((old_name = zip_get_name(za, idx, 0)) == NULL) - return -1; + return -1; new_is_dir = (name != NULL && name[strlen(name) - 1] == '/'); old_is_dir = (old_name[strlen(old_name) - 1] == '/'); if (new_is_dir != old_is_dir) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } return _zip_set_name(za, idx, name, flags); diff --git a/zip_file_replace.c b/zip_file_replace.c index 87401f4..a8cf86c 100644 --- a/zip_file_replace.c +++ b/zip_file_replace.c @@ -1,6 +1,6 @@ /* zip_file_replace.c -- replace file via callback function - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -38,12 +38,12 @@ ZIP_EXTERN int zip_file_replace(zip_t *za, zip_uint64_t idx, zip_source_t *source, zip_flags_t flags) { if (idx >= za->nentry || source == NULL) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if (_zip_file_replace(za, idx, NULL, source, flags) == -1) - return -1; + return -1; return 0; } @@ -56,31 +56,31 @@ _zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *s zip_uint64_t za_nentry_prev; if (ZIP_IS_RDONLY(za)) { - zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; } za_nentry_prev = za->nentry; if (idx == ZIP_UINT64_MAX) { - zip_int64_t i = -1; + zip_int64_t i = -1; - if (flags & ZIP_FL_OVERWRITE) - i = _zip_name_locate(za, name, flags, NULL); + if (flags & ZIP_FL_OVERWRITE) + i = _zip_name_locate(za, name, flags, NULL); - if (i == -1) { - /* create and use new entry, used by zip_add */ - if ((i = _zip_add_entry(za)) < 0) - return -1; - } - idx = (zip_uint64_t)i; + if (i == -1) { + /* create and use new entry, used by zip_add */ + if ((i = _zip_add_entry(za)) < 0) + return -1; + } + idx = (zip_uint64_t)i; } if (name && _zip_set_name(za, idx, name, flags) != 0) { - if (za->nentry != za_nentry_prev) { - _zip_entry_finalize(za->entry + idx); - za->nentry = za_nentry_prev; - } - return -1; + if (za->nentry != za_nentry_prev) { + _zip_entry_finalize(za->entry + idx); + za->nentry = za_nentry_prev; + } + return -1; } /* does not change any name related data, so we can do it here; @@ -88,15 +88,15 @@ _zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *s _zip_unchange_data(za->entry + idx); if (za->entry[idx].orig != NULL && (za->entry[idx].changes == NULL || (za->entry[idx].changes->changed & ZIP_DIRENT_COMP_METHOD) == 0)) { - if (za->entry[idx].changes == NULL) { - if ((za->entry[idx].changes = _zip_dirent_clone(za->entry[idx].orig)) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; - } - } + if (za->entry[idx].changes == NULL) { + if ((za->entry[idx].changes = _zip_dirent_clone(za->entry[idx].orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } - za->entry[idx].changes->comp_method = ZIP_CM_REPLACED_DEFAULT; - za->entry[idx].changes->changed |= ZIP_DIRENT_COMP_METHOD; + za->entry[idx].changes->comp_method = ZIP_CM_REPLACED_DEFAULT; + za->entry[idx].changes->changed |= ZIP_DIRENT_COMP_METHOD; } za->entry[idx].source = source; diff --git a/zip_file_set_comment.c b/zip_file_set_comment.c index c309db8..0276a47 100644 --- a/zip_file_set_comment.c +++ b/zip_file_set_comment.c @@ -1,6 +1,6 @@ /* zip_file_set_comment.c -- set comment for file in archive - Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -44,57 +44,57 @@ zip_file_set_comment(zip_t *za, zip_uint64_t idx, const char *comment, zip_uint1 int changed; if (_zip_get_dirent(za, idx, 0, NULL) == NULL) - return -1; + return -1; if (ZIP_IS_RDONLY(za)) { - zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; } if (len > 0 && comment == NULL) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if (len > 0) { - if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, flags, &za->error)) == NULL) - return -1; - if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED) - cstr->encoding = ZIP_ENCODING_UTF8_KNOWN; + if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, flags, &za->error)) == NULL) + return -1; + if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED) + cstr->encoding = ZIP_ENCODING_UTF8_KNOWN; } else - cstr = NULL; + cstr = NULL; e = za->entry + idx; if (e->changes) { - _zip_string_free(e->changes->comment); - e->changes->comment = NULL; - e->changes->changed &= ~ZIP_DIRENT_COMMENT; + _zip_string_free(e->changes->comment); + e->changes->comment = NULL; + e->changes->changed &= ~ZIP_DIRENT_COMMENT; } if (e->orig && e->orig->comment) - changed = !_zip_string_equal(e->orig->comment, cstr); + changed = !_zip_string_equal(e->orig->comment, cstr); else - changed = (cstr != NULL); + changed = (cstr != NULL); if (changed) { - if (e->changes == NULL) { - if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - _zip_string_free(cstr); - return -1; - } - } - e->changes->comment = cstr; - e->changes->changed |= ZIP_DIRENT_COMMENT; + if (e->changes == NULL) { + if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_string_free(cstr); + return -1; + } + } + e->changes->comment = cstr; + e->changes->changed |= ZIP_DIRENT_COMMENT; } else { - _zip_string_free(cstr); - if (e->changes && e->changes->changed == 0) { - _zip_dirent_free(e->changes); - e->changes = NULL; - } + _zip_string_free(cstr); + if (e->changes && e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } } return 0; diff --git a/zip_file_set_encryption.c b/zip_file_set_encryption.c index a66a1b5..aa0d707 100644 --- a/zip_file_set_encryption.c +++ b/zip_file_set_encryption.c @@ -1,6 +1,6 @@ /* zip_file_set_encryption.c -- set encryption for file in archive - Copyright (C) 2016-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -43,18 +43,18 @@ zip_file_set_encryption(zip_t *za, zip_uint64_t idx, zip_uint16_t method, const zip_uint16_t old_method; if (idx >= za->nentry) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if (ZIP_IS_RDONLY(za)) { - zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; } if (method != ZIP_EM_NONE && _zip_get_encryption_implementation(method, ZIP_CODEC_ENCODE) == NULL) { - zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + return -1; } e = za->entry + idx; @@ -62,54 +62,54 @@ zip_file_set_encryption(zip_t *za, zip_uint64_t idx, zip_uint16_t method, const old_method = (e->orig == NULL ? ZIP_EM_NONE : e->orig->encryption_method); if (method == old_method && password == NULL) { - if (e->changes) { - if (e->changes->changed & ZIP_DIRENT_PASSWORD) { - _zip_crypto_clear(e->changes->password, strlen(e->changes->password)); - free(e->changes->password); - e->changes->password = (e->orig == NULL ? NULL : e->orig->password); - } - e->changes->changed &= ~(ZIP_DIRENT_ENCRYPTION_METHOD | ZIP_DIRENT_PASSWORD); - if (e->changes->changed == 0) { - _zip_dirent_free(e->changes); - e->changes = NULL; - } - } + if (e->changes) { + if (e->changes->changed & ZIP_DIRENT_PASSWORD) { + _zip_crypto_clear(e->changes->password, strlen(e->changes->password)); + free(e->changes->password); + e->changes->password = (e->orig == NULL ? NULL : e->orig->password); + } + e->changes->changed &= ~(ZIP_DIRENT_ENCRYPTION_METHOD | ZIP_DIRENT_PASSWORD); + if (e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + } } else { - char *our_password = NULL; + char *our_password = NULL; - if (password) { - if ((our_password = strdup(password)) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; - } - } + if (password) { + if ((our_password = strdup(password)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } - if (e->changes == NULL) { - if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { - if (our_password) { - _zip_crypto_clear(our_password, strlen(our_password)); - } - free(our_password); - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; - } - } + if (e->changes == NULL) { + if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { + if (our_password) { + _zip_crypto_clear(our_password, strlen(our_password)); + } + free(our_password); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } - e->changes->encryption_method = method; - e->changes->changed |= ZIP_DIRENT_ENCRYPTION_METHOD; - if (password) { - e->changes->password = our_password; - e->changes->changed |= ZIP_DIRENT_PASSWORD; - } - else { - if (e->changes->changed & ZIP_DIRENT_PASSWORD) { - _zip_crypto_clear(e->changes->password, strlen(e->changes->password)); - free(e->changes->password); - e->changes->password = e->orig ? e->orig->password : NULL; - e->changes->changed &= ~ZIP_DIRENT_PASSWORD; - } - } + e->changes->encryption_method = method; + e->changes->changed |= ZIP_DIRENT_ENCRYPTION_METHOD; + if (password) { + e->changes->password = our_password; + e->changes->changed |= ZIP_DIRENT_PASSWORD; + } + else { + if (e->changes->changed & ZIP_DIRENT_PASSWORD) { + _zip_crypto_clear(e->changes->password, strlen(e->changes->password)); + free(e->changes->password); + e->changes->password = e->orig ? e->orig->password : NULL; + e->changes->changed &= ~ZIP_DIRENT_PASSWORD; + } + } } return 0; diff --git a/zip_file_set_external_attributes.c b/zip_file_set_external_attributes.c index bb2ea61..6ca01f2 100644 --- a/zip_file_set_external_attributes.c +++ b/zip_file_set_external_attributes.c @@ -1,6 +1,6 @@ /* zip_file_set_external_attributes.c -- set external attributes for entry - Copyright (C) 2013-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2013-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -41,11 +41,11 @@ zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_uint32_t unchanged_attributes; if (_zip_get_dirent(za, idx, 0, NULL) == NULL) - return -1; + return -1; if (ZIP_IS_RDONLY(za)) { - zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; } e = za->entry + idx; @@ -56,26 +56,26 @@ zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags, changed = (opsys != unchanged_opsys || attributes != unchanged_attributes); if (changed) { - if (e->changes == NULL) { - if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; - } - } - e->changes->version_madeby = (zip_uint16_t)((opsys << 8) | (e->changes->version_madeby & 0xff)); - e->changes->ext_attrib = attributes; - e->changes->changed |= ZIP_DIRENT_ATTRIBUTES; + if (e->changes == NULL) { + if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + e->changes->version_madeby = (zip_uint16_t)((opsys << 8) | (e->changes->version_madeby & 0xff)); + e->changes->ext_attrib = attributes; + e->changes->changed |= ZIP_DIRENT_ATTRIBUTES; } else if (e->changes) { - e->changes->changed &= ~ZIP_DIRENT_ATTRIBUTES; - if (e->changes->changed == 0) { - _zip_dirent_free(e->changes); - e->changes = NULL; - } - else { - e->changes->version_madeby = (zip_uint16_t)((unchanged_opsys << 8) | (e->changes->version_madeby & 0xff)); - e->changes->ext_attrib = unchanged_attributes; - } + e->changes->changed &= ~ZIP_DIRENT_ATTRIBUTES; + if (e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + else { + e->changes->version_madeby = (zip_uint16_t)((unchanged_opsys << 8) | (e->changes->version_madeby & 0xff)); + e->changes->ext_attrib = unchanged_attributes; + } } return 0; diff --git a/zip_file_set_mtime.c b/zip_file_set_mtime.c index 838548e..2753d59 100644 --- a/zip_file_set_mtime.c +++ b/zip_file_set_mtime.c @@ -45,20 +45,20 @@ zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags) zip_entry_t *e; if (_zip_get_dirent(za, idx, 0, NULL) == NULL) - return -1; + return -1; if (ZIP_IS_RDONLY(za)) { - zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; } e = za->entry + idx; if (e->changes == NULL) { - if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; - } + if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } } e->changes->last_mod = mtime; diff --git a/zip_file_strerror.c b/zip_file_strerror.c index 1fa7fff..e21c1dc 100644 --- a/zip_file_strerror.c +++ b/zip_file_strerror.c @@ -1,6 +1,6 @@ /* zip_file_sterror.c -- get string representation of zip file error - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at diff --git a/zip_fopen.c b/zip_fopen.c index 4f1a051..513f78b 100644 --- a/zip_fopen.c +++ b/zip_fopen.c @@ -1,6 +1,6 @@ /* zip_fopen.c -- open file in zip archive for reading - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,7 +40,7 @@ zip_fopen(zip_t *za, const char *fname, zip_flags_t flags) { zip_int64_t idx; if ((idx = zip_name_locate(za, fname, flags)) < 0) - return NULL; + return NULL; return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, za->default_password); } diff --git a/zip_fopen_encrypted.c b/zip_fopen_encrypted.c index 9e9b13e..5a48437 100644 --- a/zip_fopen_encrypted.c +++ b/zip_fopen_encrypted.c @@ -1,6 +1,6 @@ /* zip_fopen_encrypted.c -- open file for reading with password - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,7 +40,7 @@ zip_fopen_encrypted(zip_t *za, const char *fname, zip_flags_t flags, const char zip_int64_t idx; if ((idx = zip_name_locate(za, fname, flags)) < 0) - return NULL; + return NULL; return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, password); } diff --git a/zip_fopen_index.c b/zip_fopen_index.c index e5205b7..1f7ce8c 100644 --- a/zip_fopen_index.c +++ b/zip_fopen_index.c @@ -1,6 +1,6 @@ /* zip_fopen_index.c -- open file in zip archive for reading by index - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at diff --git a/zip_fopen_index_encrypted.c b/zip_fopen_index_encrypted.c index 6712c32..dfdeffa 100644 --- a/zip_fopen_index_encrypted.c +++ b/zip_fopen_index_encrypted.c @@ -1,6 +1,6 @@ /* zip_fopen_index_encrypted.c -- open file for reading by index w/ password - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -45,18 +45,22 @@ zip_fopen_index_encrypted(zip_t *za, zip_uint64_t index, zip_flags_t flags, cons zip_file_t *zf; zip_source_t *src; - if ((src = _zip_source_zip_new(za, za, index, flags, 0, 0, password)) == NULL) - return NULL; + if (password != NULL && password[0] == '\0') { + password = NULL; + } + + if ((src = _zip_source_zip_new(za, index, flags, 0, 0, password, &za->error)) == NULL) + return NULL; if (zip_source_open(src) < 0) { - _zip_error_set_from_source(&za->error, src); - zip_source_free(src); - return NULL; + _zip_error_set_from_source(&za->error, src); + zip_source_free(src); + return NULL; } if ((zf = _zip_file_new(za)) == NULL) { - zip_source_free(src); - return NULL; + zip_source_free(src); + return NULL; } zf->src = src; @@ -70,8 +74,8 @@ _zip_file_new(zip_t *za) { zip_file_t *zf; if ((zf = (zip_file_t *)malloc(sizeof(struct zip_file))) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; } zf->za = za; diff --git a/zip_fread.c b/zip_fread.c index 646d712..edad9d2 100644 --- a/zip_fread.c +++ b/zip_fread.c @@ -1,6 +1,6 @@ /* zip_fread.c -- read from file - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,22 +40,22 @@ zip_fread(zip_file_t *zf, void *outbuf, zip_uint64_t toread) { zip_int64_t n; if (!zf) - return -1; + return -1; if (zf->error.zip_err != 0) - return -1; + return -1; if (toread > ZIP_INT64_MAX) { - zip_error_set(&zf->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&zf->error, ZIP_ER_INVAL, 0); + return -1; } if ((zf->eof) || (toread == 0)) - return 0; + return 0; if ((n = zip_source_read(zf->src, outbuf, toread)) < 0) { - _zip_error_set_from_source(&zf->error, zf->src); - return -1; + _zip_error_set_from_source(&zf->error, zf->src); + return -1; } return n; diff --git a/zip_fseek.c b/zip_fseek.c index dc6d978..542ca07 100644 --- a/zip_fseek.c +++ b/zip_fseek.c @@ -1,6 +1,6 @@ /* zip_fseek.c -- seek in file - Copyright (C) 2016-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -37,14 +37,14 @@ ZIP_EXTERN zip_int8_t zip_fseek(zip_file_t *zf, zip_int64_t offset, int whence) { if (!zf) - return -1; + return -1; if (zf->error.zip_err != 0) - return -1; + return -1; if (zip_source_seek(zf->src, offset, whence) < 0) { - _zip_error_set_from_source(&zf->error, zf->src); - return -1; + _zip_error_set_from_source(&zf->error, zf->src); + return -1; } return 0; diff --git a/zip_ftell.c b/zip_ftell.c index 944db7b..42067a1 100644 --- a/zip_ftell.c +++ b/zip_ftell.c @@ -1,6 +1,6 @@ /* zip_ftell.c -- tell position in file - Copyright (C) 2016-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -39,15 +39,15 @@ zip_ftell(zip_file_t *zf) { zip_int64_t res; if (!zf) - return -1; + return -1; if (zf->error.zip_err != 0) - return -1; + return -1; res = zip_source_tell(zf->src); if (res < 0) { - _zip_error_set_from_source(&zf->error, zf->src); - return -1; + _zip_error_set_from_source(&zf->error, zf->src); + return -1; } return res; diff --git a/zip_get_archive_comment.c b/zip_get_archive_comment.c index 953c6f4..6752380 100644 --- a/zip_get_archive_comment.c +++ b/zip_get_archive_comment.c @@ -1,6 +1,6 @@ /* zip_get_archive_comment.c -- get archive comment - Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -44,15 +44,15 @@ zip_get_archive_comment(zip_t *za, int *lenp, zip_flags_t flags) { const zip_uint8_t *str; if ((flags & ZIP_FL_UNCHANGED) || (za->comment_changes == NULL)) - comment = za->comment_orig; + comment = za->comment_orig; else - comment = za->comment_changes; + comment = za->comment_changes; if ((str = _zip_string_get(comment, &len, flags, &za->error)) == NULL) - return NULL; + return NULL; if (lenp) - *lenp = (int)len; + *lenp = (int)len; return (const char *)str; } diff --git a/zip_get_archive_flag.c b/zip_get_archive_flag.c index fa4dd50..e4d412c 100644 --- a/zip_get_archive_flag.c +++ b/zip_get_archive_flag.c @@ -1,6 +1,6 @@ /* zip_get_archive_flag.c -- get archive global flag - Copyright (C) 2008-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2008-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at diff --git a/zip_get_encryption_implementation.c b/zip_get_encryption_implementation.c index 3909e6f..191e805 100644 --- a/zip_get_encryption_implementation.c +++ b/zip_get_encryption_implementation.c @@ -1,6 +1,6 @@ /* zip_get_encryption_implementation.c -- get encryption implementation - Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -39,24 +39,24 @@ zip_encryption_implementation _zip_get_encryption_implementation(zip_uint16_t em, int operation) { switch (em) { case ZIP_EM_TRAD_PKWARE: - return operation == ZIP_CODEC_DECODE ? zip_source_pkware_decode : zip_source_pkware_encode; + return operation == ZIP_CODEC_DECODE ? zip_source_pkware_decode : zip_source_pkware_encode; #if defined(HAVE_CRYPTO) case ZIP_EM_AES_128: case ZIP_EM_AES_192: case ZIP_EM_AES_256: - return operation == ZIP_CODEC_DECODE ? zip_source_winzip_aes_decode : zip_source_winzip_aes_encode; + return operation == ZIP_CODEC_DECODE ? zip_source_winzip_aes_decode : zip_source_winzip_aes_encode; #endif default: - return NULL; + return NULL; } } ZIP_EXTERN int zip_encryption_method_supported(zip_uint16_t method, int encode) { if (method == ZIP_EM_NONE) { - return 1; + return 1; } return _zip_get_encryption_implementation(method, encode ? ZIP_CODEC_ENCODE : ZIP_CODEC_DECODE) != NULL; } diff --git a/zip_get_file_comment.c b/zip_get_file_comment.c index f800686..dd11816 100644 --- a/zip_get_file_comment.c +++ b/zip_get_file_comment.c @@ -1,6 +1,6 @@ /* zip_get_file_comment.c -- get file comment - Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -42,8 +42,8 @@ zip_get_file_comment(zip_t *za, zip_uint64_t idx, int *lenp, int flags) { const char *s; if ((s = zip_file_get_comment(za, idx, &len, (zip_flags_t)flags)) != NULL) { - if (lenp) - *lenp = (int)len; + if (lenp) + *lenp = (int)len; } return s; diff --git a/zip_get_name.c b/zip_get_name.c index 4344209..8777868 100644 --- a/zip_get_name.c +++ b/zip_get_name.c @@ -1,6 +1,6 @@ /* zip_get_name.c -- get filename for a file in zip file - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -49,10 +49,10 @@ _zip_get_name(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error const zip_uint8_t *str; if ((de = _zip_get_dirent(za, idx, flags, error)) == NULL) - return NULL; + return NULL; if ((str = _zip_string_get(de->filename, NULL, flags, error)) == NULL) - return NULL; + return NULL; return (const char *)str; } diff --git a/zip_get_num_entries.c b/zip_get_num_entries.c index 410d26e..16d901c 100644 --- a/zip_get_num_entries.c +++ b/zip_get_num_entries.c @@ -1,6 +1,6 @@ /* zip_get_num_entries.c -- get number of entries in archive - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,13 +40,13 @@ zip_get_num_entries(zip_t *za, zip_flags_t flags) { zip_uint64_t n; if (za == NULL) - return -1; + return -1; if (flags & ZIP_FL_UNCHANGED) { - n = za->nentry; - while (n > 0 && za->entry[n - 1].orig == NULL) - --n; - return (zip_int64_t)n; + n = za->nentry; + while (n > 0 && za->entry[n - 1].orig == NULL) + --n; + return (zip_int64_t)n; } return (zip_int64_t)za->nentry; } diff --git a/zip_get_num_files.c b/zip_get_num_files.c index 4895eaa..1c6d6bb 100644 --- a/zip_get_num_files.c +++ b/zip_get_num_files.c @@ -1,6 +1,6 @@ /* zip_get_num_files.c -- get number of files in archive - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,11 +40,11 @@ ZIP_EXTERN int zip_get_num_files(zip_t *za) { if (za == NULL) - return -1; + return -1; if (za->nentry > INT_MAX) { - zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0); + return -1; } return (int)za->nentry; diff --git a/zip_hash.c b/zip_hash.c index 3206dbf..e01d935 100644 --- a/zip_hash.c +++ b/zip_hash.c @@ -1,6 +1,6 @@ /* zip_hash.c -- hash table string -> uint64 - Copyright (C) 2015-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2015-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -67,9 +67,9 @@ struct zip_hash { static void free_list(zip_hash_entry_t *entry) { while (entry != NULL) { - zip_hash_entry_t *next = entry->next; - free(entry); - entry = next; + zip_hash_entry_t *next = entry->next; + free(entry); + entry = next; } } @@ -80,12 +80,12 @@ hash_string(const zip_uint8_t *name) { zip_uint64_t value = HASH_START; if (name == NULL) { - return 0; + return 0; } while (*name != 0) { - value = (zip_uint64_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % 0x100000000ul); - name++; + value = (zip_uint64_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % 0x100000000ul); + name++; } return (zip_uint32_t)value; @@ -98,30 +98,30 @@ hash_resize(zip_hash_t *hash, zip_uint32_t new_size, zip_error_t *error) { zip_hash_entry_t **new_table; if (new_size == hash->table_size) { - return true; + return true; } if ((new_table = (zip_hash_entry_t **)calloc(new_size, sizeof(zip_hash_entry_t *))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return false; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; } if (hash->nentries > 0) { - zip_uint32_t i; + zip_uint32_t i; - for (i = 0; i < hash->table_size; i++) { - zip_hash_entry_t *entry = hash->table[i]; - while (entry) { - zip_hash_entry_t *next = entry->next; + for (i = 0; i < hash->table_size; i++) { + zip_hash_entry_t *entry = hash->table[i]; + while (entry) { + zip_hash_entry_t *next = entry->next; - zip_uint32_t new_index = entry->hash_value % new_size; + zip_uint32_t new_index = entry->hash_value % new_size; - entry->next = new_table[new_index]; - new_table[new_index] = entry; + entry->next = new_table[new_index]; + new_table[new_index] = entry; - entry = next; - } - } + entry = next; + } + } } free(hash->table); @@ -138,14 +138,14 @@ size_for_capacity(zip_uint64_t capacity) { zip_uint32_t v; if (needed_size > ZIP_UINT32_MAX) { - v = ZIP_UINT32_MAX; + v = ZIP_UINT32_MAX; } else { - v = (zip_uint32_t)needed_size; + v = (zip_uint32_t)needed_size; } if (v > HASH_MAX_SIZE) { - return HASH_MAX_SIZE; + return HASH_MAX_SIZE; } /* From Bit Twiddling Hacks by Sean Eron Anderson @@ -168,8 +168,8 @@ _zip_hash_new(zip_error_t *error) { zip_hash_t *hash; if ((hash = (zip_hash_t *)malloc(sizeof(zip_hash_t))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } hash->table_size = 0; @@ -185,16 +185,16 @@ _zip_hash_free(zip_hash_t *hash) { zip_uint32_t i; if (hash == NULL) { - return; + return; } if (hash->table != NULL) { - for (i = 0; i < hash->table_size; i++) { - if (hash->table[i] != NULL) { - free_list(hash->table[i]); - } - } - free(hash->table); + for (i = 0; i < hash->table_size; i++) { + if (hash->table[i] != NULL) { + free_list(hash->table[i]); + } + } + free(hash->table); } free(hash); } @@ -207,51 +207,51 @@ _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip zip_hash_entry_t *entry; if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return false; + zip_error_set(error, ZIP_ER_INVAL, 0); + return false; } if (hash->table_size == 0) { - if (!hash_resize(hash, HASH_MIN_SIZE, error)) { - return false; - } + if (!hash_resize(hash, HASH_MIN_SIZE, error)) { + return false; + } } hash_value = hash_string(name); table_index = hash_value % hash->table_size; for (entry = hash->table[table_index]; entry != NULL; entry = entry->next) { - if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) { - if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) { - zip_error_set(error, ZIP_ER_EXISTS, 0); - return false; - } - else { - break; - } - } + if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) { + if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) { + zip_error_set(error, ZIP_ER_EXISTS, 0); + return false; + } + else { + break; + } + } } if (entry == NULL) { - if ((entry = (zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return false; - } - entry->name = name; - entry->next = hash->table[table_index]; - hash->table[table_index] = entry; - entry->hash_value = hash_value; - entry->orig_index = -1; - hash->nentries++; - if (hash->nentries > hash->table_size * HASH_MAX_FILL && hash->table_size < HASH_MAX_SIZE) { - if (!hash_resize(hash, hash->table_size * 2, error)) { - return false; - } - } + if ((entry = (zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + entry->name = name; + entry->next = hash->table[table_index]; + hash->table[table_index] = entry; + entry->hash_value = hash_value; + entry->orig_index = -1; + hash->nentries++; + if (hash->nentries > hash->table_size * HASH_MAX_FILL && hash->table_size < HASH_MAX_SIZE) { + if (!hash_resize(hash, hash->table_size * 2, error)) { + return false; + } + } } if (flags & ZIP_FL_UNCHANGED) { - entry->orig_index = (zip_int64_t)index; + entry->orig_index = (zip_int64_t)index; } entry->current_index = (zip_int64_t)index; @@ -266,40 +266,40 @@ _zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error) zip_hash_entry_t *entry, *previous; if (hash == NULL || name == NULL) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return false; + zip_error_set(error, ZIP_ER_INVAL, 0); + return false; } if (hash->nentries > 0) { - hash_value = hash_string(name); - index = hash_value % hash->table_size; - previous = NULL; - entry = hash->table[index]; - while (entry) { - if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) { - if (entry->orig_index == -1) { - if (previous) { - previous->next = entry->next; - } - else { - hash->table[index] = entry->next; - } - free(entry); - hash->nentries--; - if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) { - if (!hash_resize(hash, hash->table_size / 2, error)) { - return false; - } - } - } - else { - entry->current_index = -1; - } - return true; - } - previous = entry; - entry = entry->next; - } + hash_value = hash_string(name); + index = hash_value % hash->table_size; + previous = NULL; + entry = hash->table[index]; + while (entry) { + if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) { + if (entry->orig_index == -1) { + if (previous) { + previous->next = entry->next; + } + else { + hash->table[index] = entry->next; + } + free(entry); + hash->nentries--; + if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) { + if (!hash_resize(hash, hash->table_size / 2, error)) { + return false; + } + } + } + else { + entry->current_index = -1; + } + return true; + } + previous = entry; + entry = entry->next; + } } zip_error_set(error, ZIP_ER_NOENT, 0); @@ -314,28 +314,28 @@ _zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, z zip_hash_entry_t *entry; if (hash == NULL || name == NULL) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; } if (hash->nentries > 0) { - hash_value = hash_string(name); - index = hash_value % hash->table_size; - for (entry = hash->table[index]; entry != NULL; entry = entry->next) { - if (strcmp((const char *)name, (const char *)entry->name) == 0) { - if (flags & ZIP_FL_UNCHANGED) { - if (entry->orig_index != -1) { - return entry->orig_index; - } - } - else { - if (entry->current_index != -1) { - return entry->current_index; - } - } - break; - } - } + hash_value = hash_string(name); + index = hash_value % hash->table_size; + for (entry = hash->table[index]; entry != NULL; entry = entry->next) { + if (strcmp((const char *)name, (const char *)entry->name) == 0) { + if (flags & ZIP_FL_UNCHANGED) { + if (entry->orig_index != -1) { + return entry->orig_index; + } + } + else { + if (entry->current_index != -1) { + return entry->current_index; + } + } + break; + } + } } zip_error_set(error, ZIP_ER_NOENT, 0); @@ -348,17 +348,17 @@ _zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t zip_uint32_t new_size; if (capacity == 0) { - return true; + return true; } new_size = size_for_capacity(capacity); if (new_size <= hash->table_size) { - return true; + return true; } if (!hash_resize(hash, new_size, error)) { - return false; + return false; } return true; @@ -371,39 +371,39 @@ _zip_hash_revert(zip_hash_t *hash, zip_error_t *error) { zip_hash_entry_t *entry, *previous; for (i = 0; i < hash->table_size; i++) { - previous = NULL; - entry = hash->table[i]; - while (entry) { - if (entry->orig_index == -1) { - zip_hash_entry_t *p; - if (previous) { - previous->next = entry->next; - } - else { - hash->table[i] = entry->next; - } - p = entry; - entry = entry->next; - /* previous does not change */ - free(p); - hash->nentries--; - } - else { - entry->current_index = entry->orig_index; - previous = entry; - entry = entry->next; - } - } + previous = NULL; + entry = hash->table[i]; + while (entry) { + if (entry->orig_index == -1) { + zip_hash_entry_t *p; + if (previous) { + previous->next = entry->next; + } + else { + hash->table[i] = entry->next; + } + p = entry; + entry = entry->next; + /* previous does not change */ + free(p); + hash->nentries--; + } + else { + entry->current_index = entry->orig_index; + previous = entry; + entry = entry->next; + } + } } if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) { - zip_uint32_t new_size = hash->table_size / 2; - while (hash->nentries < new_size * HASH_MIN_FILL && new_size > HASH_MIN_SIZE) { - new_size /= 2; - } - if (!hash_resize(hash, new_size, error)) { - return false; - } + zip_uint32_t new_size = hash->table_size / 2; + while (hash->nentries < new_size * HASH_MIN_FILL && new_size > HASH_MIN_SIZE) { + new_size /= 2; + } + if (!hash_resize(hash, new_size, error)) { + return false; + } } return true; diff --git a/zip_io_util.c b/zip_io_util.c index dd07cbb..3ee3670 100644 --- a/zip_io_util.c +++ b/zip_io_util.c @@ -1,6 +1,6 @@ /* zip_io_util.c -- I/O helper functions - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -41,18 +41,18 @@ _zip_read(zip_source_t *src, zip_uint8_t *b, zip_uint64_t length, zip_error_t *e zip_int64_t n; if (length > ZIP_INT64_MAX) { - zip_error_set(error, ZIP_ER_INTERNAL, 0); - return -1; + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return -1; } if ((n = zip_source_read(src, b, length)) < 0) { - _zip_error_set_from_source(error, src); - return -1; + _zip_error_set_from_source(error, src); + return -1; } if (n < (zip_int64_t)length) { - zip_error_set(error, ZIP_ER_EOF, 0); - return -1; + zip_error_set(error, ZIP_ER_EOF, 0); + return -1; } return 0; @@ -64,39 +64,39 @@ _zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp zip_uint8_t *r; if (length == 0 && !nulp) { - return NULL; + return NULL; } r = (zip_uint8_t *)malloc(length + (nulp ? 1 : 0)); if (!r) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } if (buffer) { - zip_uint8_t *data = _zip_buffer_get(buffer, length); + zip_uint8_t *data = _zip_buffer_get(buffer, length); - if (data == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - free(r); - return NULL; - } - memcpy(r, data, length); + if (data == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(r); + return NULL; + } + memcpy(r, data, length); } else { - if (_zip_read(src, r, length, error) < 0) { - free(r); - return NULL; - } + if (_zip_read(src, r, length, error) < 0) { + free(r); + return NULL; + } } if (nulp) { - zip_uint8_t *o; - /* replace any in-string NUL characters with spaces */ - r[length] = 0; - for (o = r; o < r + length; o++) - if (*o == '\0') - *o = ' '; + zip_uint8_t *o; + /* replace any in-string NUL characters with spaces */ + r[length] = 0; + for (o = r; o < r + length; o++) + if (*o == '\0') + *o = ' '; } return r; @@ -109,7 +109,7 @@ _zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t len, bool zip_string_t *s; if ((raw = _zip_read_data(buffer, src, len, nulp, error)) == NULL) - return NULL; + return NULL; s = _zip_string_new(raw, len, ZIP_FL_ENC_GUESS, error); free(raw); @@ -122,12 +122,12 @@ _zip_write(zip_t *za, const void *data, zip_uint64_t length) { zip_int64_t n; if ((n = zip_source_write(za->src, data, length)) < 0) { - _zip_error_set_from_source(&za->error, za->src); - return -1; + _zip_error_set_from_source(&za->error, za->src); + return -1; } if ((zip_uint64_t)n != length) { - zip_error_set(&za->error, ZIP_ER_WRITE, EINTR); - return -1; + zip_error_set(&za->error, ZIP_ER_WRITE, EINTR); + return -1; } return 0; diff --git a/zip_libzip_version.c b/zip_libzip_version.c index fadbc69..6e20724 100644 --- a/zip_libzip_version.c +++ b/zip_libzip_version.c @@ -1,6 +1,6 @@ /* zip_libzip_version.c -- return run-time version of library - Copyright (C) 2017-2019 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 diff --git a/zip_memdup.c b/zip_memdup.c index 05fcb7b..8f6175b 100644 --- a/zip_memdup.c +++ b/zip_memdup.c @@ -1,6 +1,6 @@ /* zip_memdup.c -- internal zip function, "strdup" with len - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -42,12 +42,12 @@ _zip_memdup(const void *mem, size_t len, zip_error_t *error) { void *ret; if (len == 0) - return NULL; + return NULL; ret = malloc(len); if (!ret) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } memcpy(ret, mem, len); diff --git a/zip_name_locate.c b/zip_name_locate.c index f7318ec..8a88404 100644 --- a/zip_name_locate.c +++ b/zip_name_locate.c @@ -1,6 +1,6 @@ /* zip_name_locate.c -- get index by name - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -53,40 +53,40 @@ _zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags, zip_error_t *e zip_uint64_t i; if (za == NULL) - return -1; + return -1; if (fname == NULL) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; } if (flags & (ZIP_FL_NOCASE | ZIP_FL_NODIR | ZIP_FL_ENC_CP437)) { - /* can't use hash table */ - cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp; + /* can't use hash table */ + cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp; - for (i = 0; i < za->nentry; i++) { - fn = _zip_get_name(za, i, flags, error); + for (i = 0; i < za->nentry; i++) { + fn = _zip_get_name(za, i, flags, error); - /* newly added (partially filled) entry or error */ - if (fn == NULL) - continue; + /* newly added (partially filled) entry or error */ + if (fn == NULL) + continue; - if (flags & ZIP_FL_NODIR) { - p = strrchr(fn, '/'); - if (p) - fn = p + 1; - } + if (flags & ZIP_FL_NODIR) { + p = strrchr(fn, '/'); + if (p) + fn = p + 1; + } - if (cmp(fname, fn) == 0) { - _zip_error_clear(error); - return (zip_int64_t)i; - } - } + if (cmp(fname, fn) == 0) { + _zip_error_clear(error); + return (zip_int64_t)i; + } + } - zip_error_set(error, ZIP_ER_NOENT, 0); - return -1; + zip_error_set(error, ZIP_ER_NOENT, 0); + return -1; } else { - return _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error); + return _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error); } } diff --git a/zip_new.c b/zip_new.c index 4f58ecc..3768d5b 100644 --- a/zip_new.c +++ b/zip_new.c @@ -1,6 +1,6 @@ /* zip_new.c -- create and init struct zip - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -47,13 +47,13 @@ _zip_new(zip_error_t *error) { za = (zip_t *)malloc(sizeof(struct zip)); if (!za) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } if ((za->names = _zip_hash_new(error)) == NULL) { - free(za); - return NULL; + free(za); + return NULL; } za->src = NULL; diff --git a/zip_open.c b/zip_open.c index 019cd98..1d2f69a 100644 --- a/zip_open.c +++ b/zip_open.c @@ -1,6 +1,6 @@ /* zip_open.c -- open zip archive by name - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -58,16 +58,16 @@ zip_open(const char *fn, int _flags, int *zep) { zip_error_init(&error); if ((src = zip_source_file_create(fn, 0, -1, &error)) == NULL) { - _zip_set_open_error(zep, &error, 0); - zip_error_fini(&error); - return NULL; + _zip_set_open_error(zep, &error, 0); + zip_error_fini(&error); + return NULL; } if ((za = zip_open_from_source(src, _flags, &error)) == NULL) { - zip_source_free(src); - _zip_set_open_error(zep, &error, 0); - zip_error_fini(&error); - return NULL; + zip_source_free(src); + _zip_set_open_error(zep, &error, 0); + zip_error_fini(&error); + return NULL; } zip_error_fini(&error); @@ -85,65 +85,65 @@ zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error) { exists_t exists; if (_flags < 0 || src == NULL) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } flags = (unsigned int)_flags; supported = zip_source_supports(src); if (needed_support_read == -1) { - needed_support_read = zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_STAT, -1); - needed_support_write = zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, -1); + needed_support_read = zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_STAT, -1); + needed_support_write = zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, -1); } if ((supported & needed_support_read) != needed_support_read) { - zip_error_set(error, ZIP_ER_OPNOTSUPP, 0); - return NULL; + zip_error_set(error, ZIP_ER_OPNOTSUPP, 0); + return NULL; } if ((supported & needed_support_write) != needed_support_write) { - flags |= ZIP_RDONLY; + flags |= ZIP_RDONLY; } if ((flags & (ZIP_RDONLY | ZIP_TRUNCATE)) == (ZIP_RDONLY | ZIP_TRUNCATE)) { - zip_error_set(error, ZIP_ER_RDONLY, 0); - return NULL; + zip_error_set(error, ZIP_ER_RDONLY, 0); + return NULL; } exists = _zip_file_exists(src, error); switch (exists) { case EXISTS_ERROR: - return NULL; + return NULL; case EXISTS_NOT: - if ((flags & ZIP_CREATE) == 0) { - zip_error_set(error, ZIP_ER_NOENT, 0); - return NULL; - } - return _zip_allocate_new(src, flags, error); + if ((flags & ZIP_CREATE) == 0) { + zip_error_set(error, ZIP_ER_NOENT, 0); + return NULL; + } + return _zip_allocate_new(src, flags, error); default: { - zip_t *za; - if (flags & ZIP_EXCL) { - zip_error_set(error, ZIP_ER_EXISTS, 0); - return NULL; - } - if (zip_source_open(src) < 0) { - _zip_error_set_from_source(error, src); - return NULL; - } + zip_t *za; + if (flags & ZIP_EXCL) { + zip_error_set(error, ZIP_ER_EXISTS, 0); + return NULL; + } + if (zip_source_open(src) < 0) { + _zip_error_set_from_source(error, src); + return NULL; + } - if (flags & ZIP_TRUNCATE) { - za = _zip_allocate_new(src, flags, error); - } - else { - /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL, just like open() */ - za = _zip_open(src, flags, error); - } + if (flags & ZIP_TRUNCATE) { + za = _zip_allocate_new(src, flags, error); + } + else { + /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL, just like open() */ + za = _zip_open(src, flags, error); + } - if (za == NULL) { - zip_source_close(src); - return NULL; - } - return za; + if (za == NULL) { + zip_source_close(src); + return NULL; + } + return za; } } } @@ -158,31 +158,31 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) { zip_stat_init(&st); if (zip_source_stat(src, &st) < 0) { - _zip_error_set_from_source(error, src); - return NULL; + _zip_error_set_from_source(error, src); + return NULL; } if ((st.valid & ZIP_STAT_SIZE) == 0) { - zip_error_set(error, ZIP_ER_SEEK, EOPNOTSUPP); - return NULL; + zip_error_set(error, ZIP_ER_SEEK, EOPNOTSUPP); + return NULL; } len = st.size; if ((za = _zip_allocate_new(src, flags, error)) == NULL) { - return NULL; + return NULL; } /* treat empty files as empty archives */ if (len == 0 && zip_source_accept_empty(src)) { - return za; + return za; } if ((cdir = _zip_find_central_dir(za, len)) == NULL) { - _zip_error_copy(error, &za->error); - /* keep src so discard does not get rid of it */ - zip_source_keep(src); - zip_discard(za); - return NULL; + _zip_error_copy(error, &za->error); + /* keep src so discard does not get rid of it */ + zip_source_keep(src); + zip_discard(za); + return NULL; } za->entry = cdir->entry; @@ -195,23 +195,23 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) { _zip_hash_reserve_capacity(za->names, za->nentry, &za->error); for (idx = 0; idx < za->nentry; idx++) { - const zip_uint8_t *name = _zip_string_get(za->entry[idx].orig->filename, NULL, 0, error); - if (name == NULL) { - /* keep src so discard does not get rid of it */ - zip_source_keep(src); - zip_discard(za); - return NULL; - } + const zip_uint8_t *name = _zip_string_get(za->entry[idx].orig->filename, NULL, 0, error); + if (name == NULL) { + /* keep src so discard does not get rid of it */ + zip_source_keep(src); + zip_discard(za); + return NULL; + } - if (_zip_hash_add(za->names, name, idx, ZIP_FL_UNCHANGED, &za->error) == false) { - if (za->error.zip_err != ZIP_ER_EXISTS || (flags & ZIP_CHECKCONS)) { - _zip_error_copy(error, &za->error); - /* keep src so discard does not get rid of it */ - zip_source_keep(src); - zip_discard(za); - return NULL; - } - } + if (_zip_hash_add(za->names, name, idx, ZIP_FL_UNCHANGED, &za->error) == false) { + if (za->error.zip_err != ZIP_ER_EXISTS || (flags & ZIP_CHECKCONS)) { + _zip_error_copy(error, &za->error); + /* keep src so discard does not get rid of it */ + zip_source_keep(src); + zip_discard(za); + return NULL; + } + } } za->ch_flags = za->flags; @@ -223,14 +223,20 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) { void _zip_set_open_error(int *zep, const zip_error_t *err, int ze) { if (err) { - ze = zip_error_code_zip(err); - if (zip_error_system_type(err) == ZIP_ET_SYS) { - errno = zip_error_code_system(err); - } + ze = zip_error_code_zip(err); + switch (zip_error_system_type(err)) { + case ZIP_ET_SYS: + case ZIP_ET_LIBZIP: + errno = zip_error_code_system(err); + break; + + default: + break; + } } if (zep) - *zep = ze; + *zep = ze; } @@ -249,156 +255,159 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err zip_buffer_t *cd_buffer; if (_zip_buffer_left(buffer) < EOCDLEN) { - /* not enough bytes left for comment */ - zip_error_set(error, ZIP_ER_NOZIP, 0); - return NULL; + /* not enough bytes left for comment */ + zip_error_set(error, ZIP_ER_NOZIP, 0); + return NULL; } /* check for end-of-central-dir magic */ if (memcmp(_zip_buffer_get(buffer, 4), EOCD_MAGIC, 4) != 0) { - zip_error_set(error, ZIP_ER_NOZIP, 0); - return NULL; + zip_error_set(error, ZIP_ER_NOZIP, 0); + return NULL; } if (eocd_offset >= EOCD64LOCLEN && memcmp(_zip_buffer_data(buffer) + eocd_offset - EOCD64LOCLEN, EOCD64LOC_MAGIC, 4) == 0) { - _zip_buffer_set_offset(buffer, eocd_offset - EOCD64LOCLEN); - cd = _zip_read_eocd64(za->src, buffer, buf_offset, za->flags, error); + _zip_buffer_set_offset(buffer, eocd_offset - EOCD64LOCLEN); + cd = _zip_read_eocd64(za->src, buffer, buf_offset, za->flags, error); } else { - _zip_buffer_set_offset(buffer, eocd_offset); - cd = _zip_read_eocd(buffer, buf_offset, za->flags, error); + _zip_buffer_set_offset(buffer, eocd_offset); + cd = _zip_read_eocd(buffer, buf_offset, za->flags, error); } if (cd == NULL) - return NULL; + return NULL; _zip_buffer_set_offset(buffer, eocd_offset + 20); comment_len = _zip_buffer_get_16(buffer); if (cd->offset + cd->size > buf_offset + eocd_offset) { - /* cdir spans past EOCD record */ - zip_error_set(error, ZIP_ER_INCONS, 0); - _zip_cdir_free(cd); - return NULL; + /* cdir spans past EOCD record */ + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD); + _zip_cdir_free(cd); + return NULL; } if (comment_len || (za->open_flags & ZIP_CHECKCONS)) { - zip_uint64_t tail_len; + zip_uint64_t tail_len; - _zip_buffer_set_offset(buffer, eocd_offset + EOCDLEN); - tail_len = _zip_buffer_left(buffer); + _zip_buffer_set_offset(buffer, eocd_offset + EOCDLEN); + tail_len = _zip_buffer_left(buffer); - if (tail_len < comment_len || ((za->open_flags & ZIP_CHECKCONS) && tail_len != comment_len)) { - zip_error_set(error, ZIP_ER_INCONS, 0); - _zip_cdir_free(cd); - return NULL; - } + if (tail_len < comment_len || ((za->open_flags & ZIP_CHECKCONS) && tail_len != comment_len)) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_COMMENT_LENGTH_INVALID); + _zip_cdir_free(cd); + return NULL; + } - if (comment_len) { - if ((cd->comment = _zip_string_new(_zip_buffer_get(buffer, comment_len), comment_len, ZIP_FL_ENC_GUESS, error)) == NULL) { - _zip_cdir_free(cd); - return NULL; - } - } + if (comment_len) { + if ((cd->comment = _zip_string_new(_zip_buffer_get(buffer, comment_len), comment_len, ZIP_FL_ENC_GUESS, error)) == NULL) { + _zip_cdir_free(cd); + return NULL; + } + } } if (cd->offset >= buf_offset) { - zip_uint8_t *data; - /* if buffer already read in, use it */ - _zip_buffer_set_offset(buffer, cd->offset - buf_offset); + zip_uint8_t *data; + /* if buffer already read in, use it */ + _zip_buffer_set_offset(buffer, cd->offset - buf_offset); - if ((data = _zip_buffer_get(buffer, cd->size)) == NULL) { - zip_error_set(error, ZIP_ER_INCONS, 0); - _zip_cdir_free(cd); - return NULL; - } - if ((cd_buffer = _zip_buffer_new(data, cd->size)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - _zip_cdir_free(cd); - return NULL; - } + if ((data = _zip_buffer_get(buffer, cd->size)) == NULL) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_LENGTH_INVALID); + _zip_cdir_free(cd); + return NULL; + } + if ((cd_buffer = _zip_buffer_new(data, cd->size)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + _zip_cdir_free(cd); + return NULL; + } } else { - cd_buffer = NULL; + cd_buffer = NULL; - if (zip_source_seek(za->src, (zip_int64_t)cd->offset, SEEK_SET) < 0) { - _zip_error_set_from_source(error, za->src); - _zip_cdir_free(cd); - return NULL; - } + if (zip_source_seek(za->src, (zip_int64_t)cd->offset, SEEK_SET) < 0) { + _zip_error_set_from_source(error, za->src); + _zip_cdir_free(cd); + return NULL; + } - /* possible consistency check: cd->offset = len-(cd->size+cd->comment_len+EOCDLEN) ? */ - if (zip_source_tell(za->src) != (zip_int64_t)cd->offset) { - zip_error_set(error, ZIP_ER_NOZIP, 0); - _zip_cdir_free(cd); - return NULL; - } + /* possible consistency check: cd->offset = len-(cd->size+cd->comment_len+EOCDLEN) ? */ + if (zip_source_tell(za->src) != (zip_int64_t)cd->offset) { + zip_error_set(error, ZIP_ER_NOZIP, 0); + _zip_cdir_free(cd); + return NULL; + } } left = (zip_uint64_t)cd->size; i = 0; while (left > 0) { - bool grown = false; - zip_int64_t entry_size; + bool grown = false; + zip_int64_t entry_size; - if (i == cd->nentry) { - /* InfoZIP has a hack to avoid using Zip64: it stores nentries % 0x10000 */ - /* This hack isn't applicable if we're using Zip64, or if there is no central directory entry following. */ + if (i == cd->nentry) { + /* InfoZIP has a hack to avoid using Zip64: it stores nentries % 0x10000 */ + /* This hack isn't applicable if we're using Zip64, or if there is no central directory entry following. */ - if (cd->is_zip64 || left < CDENTRYSIZE) { - break; + if (cd->is_zip64 || left < CDENTRYSIZE) { + break; + } + + if (!_zip_cdir_grow(cd, 0x10000, error)) { + _zip_cdir_free(cd); + _zip_buffer_free(cd_buffer); + return NULL; + } + grown = true; + } + + if ((cd->entry[i].orig = _zip_dirent_new()) == NULL || (entry_size = _zip_dirent_read(cd->entry[i].orig, za->src, cd_buffer, false, error)) < 0) { + if (zip_error_code_zip(error) == ZIP_ER_INCONS) { + zip_error_set(error, ZIP_ER_INCONS, ADD_INDEX_TO_DETAIL(zip_error_code_system(error), i)); } - - if (!_zip_cdir_grow(cd, 0x10000, error)) { - _zip_cdir_free(cd); - _zip_buffer_free(cd_buffer); - return NULL; - } - grown = true; - } - - if ((cd->entry[i].orig = _zip_dirent_new()) == NULL || (entry_size = _zip_dirent_read(cd->entry[i].orig, za->src, cd_buffer, false, error)) < 0) { - if (grown && zip_error_code_zip(error) == ZIP_ER_NOZIP) { - zip_error_set(error, ZIP_ER_INCONS, 0); - } - _zip_cdir_free(cd); - _zip_buffer_free(cd_buffer); - return NULL; - } - i++; - left -= (zip_uint64_t)entry_size; + else if (grown && zip_error_code_zip(error) == ZIP_ER_NOZIP) { + zip_error_set(error, ZIP_ER_INCONS, MAKE_DETAIL_WITH_INDEX(ZIP_ER_DETAIL_CDIR_ENTRY_INVALID, i)); + } + _zip_cdir_free(cd); + _zip_buffer_free(cd_buffer); + return NULL; + } + i++; + left -= (zip_uint64_t)entry_size; } if (i != cd->nentry || left > 0) { - zip_error_set(error, ZIP_ER_INCONS, 0); - _zip_buffer_free(cd_buffer); - _zip_cdir_free(cd); - return NULL; + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_WRONG_ENTRIES_COUNT); + _zip_buffer_free(cd_buffer); + _zip_cdir_free(cd); + return NULL; } if (za->open_flags & ZIP_CHECKCONS) { - bool ok; + bool ok; - if (cd_buffer) { - ok = _zip_buffer_eof(cd_buffer); - } - else { - zip_int64_t offset = zip_source_tell(za->src); + if (cd_buffer) { + ok = _zip_buffer_eof(cd_buffer); + } + else { + zip_int64_t offset = zip_source_tell(za->src); - if (offset < 0) { - _zip_error_set_from_source(error, za->src); - _zip_cdir_free(cd); - return NULL; - } - ok = ((zip_uint64_t)offset == cd->offset + cd->size); - } + if (offset < 0) { + _zip_error_set_from_source(error, za->src); + _zip_cdir_free(cd); + return NULL; + } + ok = ((zip_uint64_t)offset == cd->offset + cd->size); + } - if (!ok) { - zip_error_set(error, ZIP_ER_INCONS, 0); - _zip_buffer_free(cd_buffer); - _zip_cdir_free(cd); - return NULL; - } + if (!ok) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_LENGTH_INVALID); + _zip_buffer_free(cd_buffer); + _zip_cdir_free(cd); + return NULL; + } } _zip_buffer_free(cd_buffer); @@ -420,49 +429,52 @@ _zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error) { _zip_dirent_init(&temp); if (cd->nentry) { - max = cd->entry[0].orig->offset; - min = cd->entry[0].orig->offset; + max = cd->entry[0].orig->offset; + min = cd->entry[0].orig->offset; } else - min = max = 0; + min = max = 0; for (i = 0; i < cd->nentry; i++) { - if (cd->entry[i].orig->offset < min) - min = cd->entry[i].orig->offset; - if (min > (zip_uint64_t)cd->offset) { - zip_error_set(error, ZIP_ER_NOZIP, 0); - return -1; - } + if (cd->entry[i].orig->offset < min) + min = cd->entry[i].orig->offset; + if (min > (zip_uint64_t)cd->offset) { + zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } - j = cd->entry[i].orig->offset + cd->entry[i].orig->comp_size + _zip_string_length(cd->entry[i].orig->filename) + LENTRYSIZE; - if (j > max) - max = j; - if (max > (zip_uint64_t)cd->offset) { - zip_error_set(error, ZIP_ER_NOZIP, 0); - return -1; - } + j = cd->entry[i].orig->offset + cd->entry[i].orig->comp_size + _zip_string_length(cd->entry[i].orig->filename) + LENTRYSIZE; + if (j > max) + max = j; + if (max > (zip_uint64_t)cd->offset) { + zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } - if (zip_source_seek(za->src, (zip_int64_t)cd->entry[i].orig->offset, SEEK_SET) < 0) { - _zip_error_set_from_source(error, za->src); - return -1; - } + if (zip_source_seek(za->src, (zip_int64_t)cd->entry[i].orig->offset, SEEK_SET) < 0) { + _zip_error_set_from_source(error, za->src); + return -1; + } - if (_zip_dirent_read(&temp, za->src, NULL, true, error) == -1) { - _zip_dirent_finalize(&temp); - return -1; - } + if (_zip_dirent_read(&temp, za->src, NULL, true, error) == -1) { + if (zip_error_code_zip(error) == ZIP_ER_INCONS) { + zip_error_set(error, ZIP_ER_INCONS, ADD_INDEX_TO_DETAIL(zip_error_code_system(error), i)); + } + _zip_dirent_finalize(&temp); + return -1; + } - if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) { - zip_error_set(error, ZIP_ER_INCONS, 0); - _zip_dirent_finalize(&temp); - return -1; - } + if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) { + zip_error_set(error, ZIP_ER_INCONS, MAKE_DETAIL_WITH_INDEX(ZIP_ER_DETAIL_ENTRY_HEADER_MISMATCH, i)); + _zip_dirent_finalize(&temp); + return -1; + } - cd->entry[i].orig->extra_fields = _zip_ef_merge(cd->entry[i].orig->extra_fields, temp.extra_fields); - cd->entry[i].orig->local_extra_fields_read = 1; - temp.extra_fields = NULL; + cd->entry[i].orig->extra_fields = _zip_ef_merge(cd->entry[i].orig->extra_fields, temp.extra_fields); + cd->entry[i].orig->local_extra_fields_read = 1; + temp.extra_fields = NULL; - _zip_dirent_finalize(&temp); + _zip_dirent_finalize(&temp); } return (max - min) < ZIP_INT64_MAX ? (zip_int64_t)(max - min) : ZIP_INT64_MAX; @@ -481,14 +493,14 @@ _zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *local) { and global headers for the bitflags */ || (central->bitflags != local->bitflags) #endif - || (central->comp_method != local->comp_method) || (central->last_mod != local->last_mod) || !_zip_string_equal(central->filename, local->filename)) - return -1; + || (central->comp_method != local->comp_method) || (central->last_mod != local->last_mod) || !_zip_string_equal(central->filename, local->filename)) + return -1; if ((central->crc != local->crc) || (central->comp_size != local->comp_size) || (central->uncomp_size != local->uncomp_size)) { - /* InfoZip stores valid values in local header even when data descriptor is used. - This is in violation of the appnote. */ - if (((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local->crc != 0 || local->comp_size != 0 || local->uncomp_size != 0)) - return -1; + /* InfoZip stores valid values in local header even when data descriptor is used. + This is in violation of the appnote. */ + if (((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local->crc != 0 || local->comp_size != 0 || local->uncomp_size != 0)) + return -1; } return 0; @@ -500,14 +512,14 @@ _zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error) { zip_t *za; if ((za = _zip_new(error)) == NULL) { - return NULL; + return NULL; } za->src = src; za->open_flags = flags; if (flags & ZIP_RDONLY) { - za->flags |= ZIP_AFL_RDONLY; - za->ch_flags |= ZIP_AFL_RDONLY; + za->flags |= ZIP_AFL_RDONLY; + za->ch_flags |= ZIP_AFL_RDONLY; } return za; } @@ -522,12 +534,12 @@ _zip_file_exists(zip_source_t *src, zip_error_t *error) { zip_stat_init(&st); if (zip_source_stat(src, &st) != 0) { - zip_error_t *src_error = zip_source_error(src); - if (zip_error_code_zip(src_error) == ZIP_ER_READ && zip_error_code_system(src_error) == ENOENT) { - return EXISTS_NOT; - } - _zip_error_copy(error, src_error); - return EXISTS_ERROR; + zip_error_t *src_error = zip_source_error(src); + if (zip_error_code_zip(src_error) == ZIP_ER_READ && zip_error_code_system(src_error) == ENOENT) { + return EXISTS_NOT; + } + _zip_error_copy(error, src_error); + return EXISTS_ERROR; } return EXISTS_OK; @@ -546,76 +558,76 @@ _zip_find_central_dir(zip_t *za, zip_uint64_t len) { zip_buffer_t *buffer; if (len < EOCDLEN) { - zip_error_set(&za->error, ZIP_ER_NOZIP, 0); - return NULL; + zip_error_set(&za->error, ZIP_ER_NOZIP, 0); + return NULL; } buflen = (len < CDBUFSIZE ? len : CDBUFSIZE); if (zip_source_seek(za->src, -(zip_int64_t)buflen, SEEK_END) < 0) { - zip_error_t *src_error = zip_source_error(za->src); - if (zip_error_code_zip(src_error) != ZIP_ER_SEEK || zip_error_code_system(src_error) != EFBIG) { - /* seek before start of file on my machine */ - _zip_error_copy(&za->error, src_error); - return NULL; - } + zip_error_t *src_error = zip_source_error(za->src); + if (zip_error_code_zip(src_error) != ZIP_ER_SEEK || zip_error_code_system(src_error) != EFBIG) { + /* seek before start of file on my machine */ + _zip_error_copy(&za->error, src_error); + return NULL; + } } if ((buf_offset = zip_source_tell(za->src)) < 0) { - _zip_error_set_from_source(&za->error, za->src); - return NULL; + _zip_error_set_from_source(&za->error, za->src); + return NULL; } if ((buffer = _zip_buffer_new_from_source(za->src, buflen, NULL, &za->error)) == NULL) { - return NULL; + return NULL; } best = -1; cdir = NULL; if (buflen >= CDBUFSIZE) { - /* EOCD64 locator is before EOCD, so leave place for it */ - _zip_buffer_set_offset(buffer, EOCD64LOCLEN); + /* EOCD64 locator is before EOCD, so leave place for it */ + _zip_buffer_set_offset(buffer, EOCD64LOCLEN); } zip_error_set(&error, ZIP_ER_NOZIP, 0); match = _zip_buffer_get(buffer, 0); while ((match = _zip_memmem(match, _zip_buffer_left(buffer) - (EOCDLEN - 4), (const unsigned char *)EOCD_MAGIC, 4)) != NULL) { - _zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer))); - if ((cdirnew = _zip_read_cdir(za, buffer, (zip_uint64_t)buf_offset, &error)) != NULL) { - if (cdir) { - if (best <= 0) { - best = _zip_checkcons(za, cdir, &error); - } + _zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer))); + if ((cdirnew = _zip_read_cdir(za, buffer, (zip_uint64_t)buf_offset, &error)) != NULL) { + if (cdir) { + if (best <= 0) { + best = _zip_checkcons(za, cdir, &error); + } - a = _zip_checkcons(za, cdirnew, &error); - if (best < a) { - _zip_cdir_free(cdir); - cdir = cdirnew; - best = a; - } - else { - _zip_cdir_free(cdirnew); - } - } - else { - cdir = cdirnew; - if (za->open_flags & ZIP_CHECKCONS) - best = _zip_checkcons(za, cdir, &error); - else { - best = 0; - } - } - cdirnew = NULL; - } + a = _zip_checkcons(za, cdirnew, &error); + if (best < a) { + _zip_cdir_free(cdir); + cdir = cdirnew; + best = a; + } + else { + _zip_cdir_free(cdirnew); + } + } + else { + cdir = cdirnew; + if (za->open_flags & ZIP_CHECKCONS) + best = _zip_checkcons(za, cdir, &error); + else { + best = 0; + } + } + cdirnew = NULL; + } - match++; - _zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer))); + match++; + _zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer))); } _zip_buffer_free(buffer); if (best < 0) { - _zip_error_copy(&za->error, &error); - _zip_cdir_free(cdir); - return NULL; + _zip_error_copy(&za->error, &error); + _zip_cdir_free(cdir); + return NULL; } return cdir; @@ -627,11 +639,11 @@ _zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little const unsigned char *p; if ((biglen < littlelen) || (littlelen == 0)) - return NULL; + return NULL; p = big - 1; while ((p = (const unsigned char *)memchr(p + 1, little[0], (size_t)(big - (p + 1)) + (size_t)(biglen - littlelen) + 1)) != NULL) { - if (memcmp(p + 1, little + 1, littlelen - 1) == 0) - return (unsigned char *)p; + if (memcmp(p + 1, little + 1, littlelen - 1) == 0) + return (unsigned char *)p; } return NULL; @@ -644,8 +656,8 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags zip_uint64_t i, nentry, size, offset, eocd_offset; if (_zip_buffer_left(buffer) < EOCDLEN) { - zip_error_set(error, ZIP_ER_INCONS, 0); - return NULL; + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD_LENGTH_INVALID); + return NULL; } eocd_offset = _zip_buffer_offset(buffer); @@ -653,8 +665,8 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags _zip_buffer_get(buffer, 4); /* magic already verified */ if (_zip_buffer_get_32(buffer) != 0) { - zip_error_set(error, ZIP_ER_MULTIDISK, 0); - return NULL; + zip_error_set(error, ZIP_ER_MULTIDISK, 0); + return NULL; } /* number of cdir-entries on this disk */ @@ -663,31 +675,31 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags nentry = _zip_buffer_get_16(buffer); if (nentry != i) { - zip_error_set(error, ZIP_ER_NOZIP, 0); - return NULL; + zip_error_set(error, ZIP_ER_NOZIP, 0); + return NULL; } size = _zip_buffer_get_32(buffer); offset = _zip_buffer_get_32(buffer); if (offset + size < offset) { - zip_error_set(error, ZIP_ER_SEEK, EFBIG); - return NULL; + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return NULL; } if (offset + size > buf_offset + eocd_offset) { - /* cdir spans past EOCD record */ - zip_error_set(error, ZIP_ER_INCONS, 0); - return NULL; + /* cdir spans past EOCD record */ + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD); + return NULL; } if ((flags & ZIP_CHECKCONS) && offset + size != buf_offset + eocd_offset) { - zip_error_set(error, ZIP_ER_INCONS, 0); - return NULL; + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_LENGTH_INVALID); + return NULL; } if ((cd = _zip_cdir_new(nentry, error)) == NULL) - return NULL; + return NULL; cd->is_zip64 = false; cd->size = size; @@ -717,38 +729,38 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse /* valid seek value for start of EOCD */ if (eocd_offset > ZIP_INT64_MAX) { - zip_error_set(error, ZIP_ER_SEEK, EFBIG); - return NULL; + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return NULL; } /* does EOCD fit before EOCD locator? */ if (eocd_offset + EOCD64LEN > eocdloc_offset + buf_offset) { - zip_error_set(error, ZIP_ER_INCONS, 0); - return NULL; + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD64_OVERLAPS_EOCD); + return NULL; } /* make sure current position of buffer is beginning of EOCD */ if (eocd_offset >= buf_offset && eocd_offset + EOCD64LEN <= buf_offset + _zip_buffer_size(buffer)) { - _zip_buffer_set_offset(buffer, eocd_offset - buf_offset); - free_buffer = false; + _zip_buffer_set_offset(buffer, eocd_offset - buf_offset); + free_buffer = false; } else { - if (zip_source_seek(src, (zip_int64_t)eocd_offset, SEEK_SET) < 0) { - _zip_error_set_from_source(error, src); - return NULL; - } - if ((buffer = _zip_buffer_new_from_source(src, EOCD64LEN, eocd, error)) == NULL) { - return NULL; - } - free_buffer = true; + if (zip_source_seek(src, (zip_int64_t)eocd_offset, SEEK_SET) < 0) { + _zip_error_set_from_source(error, src); + return NULL; + } + if ((buffer = _zip_buffer_new_from_source(src, EOCD64LEN, eocd, error)) == NULL) { + return NULL; + } + free_buffer = true; } if (memcmp(_zip_buffer_get(buffer, 4), EOCD64_MAGIC, 4) != 0) { - zip_error_set(error, ZIP_ER_INCONS, 0); - if (free_buffer) { - _zip_buffer_free(buffer); - } - return NULL; + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD64_WRONG_MAGIC); + if (free_buffer) { + _zip_buffer_free(buffer); + } + return NULL; } /* size of EOCD */ @@ -756,11 +768,11 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse /* is there a hole between EOCD and EOCD locator, or do they overlap? */ if ((flags & ZIP_CHECKCONS) && size + eocd_offset + 12 != buf_offset + eocdloc_offset) { - zip_error_set(error, ZIP_ER_INCONS, 0); - if (free_buffer) { - _zip_buffer_free(buffer); - } - return NULL; + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD64_OVERLAPS_EOCD); + if (free_buffer) { + _zip_buffer_free(buffer); + } + return NULL; } _zip_buffer_get(buffer, 4); /* skip version made by/needed */ @@ -772,35 +784,35 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse otherwise, if the values are not the same, it's inconsistent; in any case, if the value is not 0, we don't support it */ if (num_disks == 0xffff) { - num_disks = num_disks64; + num_disks = num_disks64; } if (eocd_disk == 0xffff) { - eocd_disk = eocd_disk64; + eocd_disk = eocd_disk64; } if ((flags & ZIP_CHECKCONS) && (eocd_disk != eocd_disk64 || num_disks != num_disks64)) { - zip_error_set(error, ZIP_ER_INCONS, 0); - if (free_buffer) { - _zip_buffer_free(buffer); - } - return NULL; + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD64_MISMATCH); + if (free_buffer) { + _zip_buffer_free(buffer); + } + return NULL; } if (num_disks != 0 || eocd_disk != 0) { - zip_error_set(error, ZIP_ER_MULTIDISK, 0); - if (free_buffer) { - _zip_buffer_free(buffer); - } - return NULL; + zip_error_set(error, ZIP_ER_MULTIDISK, 0); + if (free_buffer) { + _zip_buffer_free(buffer); + } + return NULL; } nentry = _zip_buffer_get_64(buffer); i = _zip_buffer_get_64(buffer); if (nentry != i) { - zip_error_set(error, ZIP_ER_MULTIDISK, 0); - if (free_buffer) { - _zip_buffer_free(buffer); - } - return NULL; + zip_error_set(error, ZIP_ER_MULTIDISK, 0); + if (free_buffer) { + _zip_buffer_free(buffer); + } + return NULL; } size = _zip_buffer_get_64(buffer); @@ -808,38 +820,38 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse /* did we read past the end of the buffer? */ if (!_zip_buffer_ok(buffer)) { - zip_error_set(error, ZIP_ER_INTERNAL, 0); - if (free_buffer) { - _zip_buffer_free(buffer); - } - return NULL; + zip_error_set(error, ZIP_ER_INTERNAL, 0); + if (free_buffer) { + _zip_buffer_free(buffer); + } + return NULL; } if (free_buffer) { - _zip_buffer_free(buffer); + _zip_buffer_free(buffer); } if (offset > ZIP_INT64_MAX || offset + size < offset) { - zip_error_set(error, ZIP_ER_SEEK, EFBIG); - return NULL; + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return NULL; } if (offset + size > buf_offset + eocd_offset) { - /* cdir spans past EOCD record */ - zip_error_set(error, ZIP_ER_INCONS, 0); - return NULL; + /* cdir spans past EOCD record */ + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD); + return NULL; } if ((flags & ZIP_CHECKCONS) && offset + size != buf_offset + eocd_offset) { - zip_error_set(error, ZIP_ER_INCONS, 0); - return NULL; + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD); + return NULL; } if (nentry > size / CDENTRYSIZE) { - zip_error_set(error, ZIP_ER_INCONS, 0); - return NULL; + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_INVALID); + return NULL; } if ((cd = _zip_cdir_new(nentry, error)) == NULL) - return NULL; + return NULL; cd->is_zip64 = true; cd->size = size; diff --git a/zip_pkware.c b/zip_pkware.c index eb12b1e..1b1b461 100644 --- a/zip_pkware.c +++ b/zip_pkware.c @@ -75,18 +75,18 @@ _zip_pkware_encrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t zip_uint8_t tmp; for (i = 0; i < len; i++) { - b = in[i]; + b = in[i]; - if (out != NULL) { - tmp = crypt_byte(keys); - update_keys(keys, b); - b ^= tmp; - out[i] = b; - } - else { - /* during initialization, we're only interested in key updates */ - update_keys(keys, b); - } + if (out != NULL) { + tmp = crypt_byte(keys); + update_keys(keys, b); + b ^= tmp; + out[i] = b; + } + else { + /* during initialization, we're only interested in key updates */ + update_keys(keys, b); + } } } @@ -98,15 +98,15 @@ _zip_pkware_decrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t zip_uint8_t tmp; for (i = 0; i < len; i++) { - b = in[i]; + b = in[i]; - /* during initialization, we're only interested in key updates */ - if (out != NULL) { - tmp = crypt_byte(keys); - b ^= tmp; - out[i] = b; - } + /* during initialization, we're only interested in key updates */ + if (out != NULL) { + tmp = crypt_byte(keys); + b ^= tmp; + out[i] = b; + } - update_keys(keys, b); + update_keys(keys, b); } } diff --git a/zip_progress.c b/zip_progress.c index ddb47c7..a881df4 100644 --- a/zip_progress.c +++ b/zip_progress.c @@ -73,7 +73,7 @@ _zip_progress_end(zip_progress_t *progress) { void _zip_progress_free(zip_progress_t *progress) { if (progress == NULL) { - return; + return; } _zip_progress_free_progress_callback(progress); @@ -88,8 +88,8 @@ _zip_progress_new(zip_t *za) { zip_progress_t *progress = (zip_progress_t *)malloc(sizeof(*progress)); if (progress == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; } progress->za = za; @@ -109,7 +109,7 @@ _zip_progress_new(zip_t *za) { static void _zip_progress_free_progress_callback(zip_progress_t *progress) { if (progress->ud_progress_free) { - progress->ud_progress_free(progress->ud_progress); + progress->ud_progress_free(progress->ud_progress); } progress->callback_progress = NULL; @@ -120,7 +120,7 @@ _zip_progress_free_progress_callback(zip_progress_t *progress) { static void _zip_progress_free_cancel_callback(zip_progress_t *progress) { if (progress->ud_cancel_free) { - progress->ud_cancel_free(progress->ud_cancel); + progress->ud_cancel_free(progress->ud_cancel); } progress->callback_cancel = NULL; @@ -150,18 +150,18 @@ _zip_progress_set_cancel_callback(zip_progress_t *progress, zip_cancel_callback int _zip_progress_start(zip_progress_t *progress) { if (progress == NULL) { - return 0; + return 0; } if (progress->callback_progress != NULL) { - progress->last_update = 0.0; - progress->callback_progress(progress->za, 0.0, progress->ud_progress); + progress->last_update = 0.0; + progress->callback_progress(progress->za, 0.0, progress->ud_progress); } if (progress->callback_cancel != NULL) { - if (progress->callback_cancel(progress->za, progress->ud_cancel)) { - return -1; - } + if (progress->callback_cancel(progress->za, progress->ud_cancel)) { + return -1; + } } return 0; @@ -171,7 +171,7 @@ _zip_progress_start(zip_progress_t *progress) { int _zip_progress_subrange(zip_progress_t *progress, double start, double end) { if (progress == NULL) { - return 0; + return 0; } progress->start = start; @@ -185,22 +185,22 @@ _zip_progress_update(zip_progress_t *progress, double sub_current) { double current; if (progress == NULL) { - return 0; + return 0; } if (progress->callback_progress != NULL) { - current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start; + current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start; - if (current - progress->last_update > progress->precision) { - progress->callback_progress(progress->za, current, progress->ud_progress); - progress->last_update = current; - } + if (current - progress->last_update > progress->precision) { + progress->callback_progress(progress->za, current, progress->ud_progress); + progress->last_update = current; + } } if (progress->callback_cancel != NULL) { - if (progress->callback_cancel(progress->za, progress->ud_cancel)) { - return -1; - } + if (progress->callback_cancel(progress->za, progress->ud_cancel)) { + return -1; + } } return 0; @@ -210,24 +210,24 @@ _zip_progress_update(zip_progress_t *progress, double sub_current) { ZIP_EXTERN int zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) { if (callback != NULL) { - if (za->progress == NULL) { - if ((za->progress = _zip_progress_new(za)) == NULL) { - return -1; - } - } + if (za->progress == NULL) { + if ((za->progress = _zip_progress_new(za)) == NULL) { + return -1; + } + } - _zip_progress_set_progress_callback(za->progress, precision, callback, ud_free, ud); + _zip_progress_set_progress_callback(za->progress, precision, callback, ud_free, ud); } else { - if (za->progress != NULL) { - if (za->progress->callback_cancel == NULL) { - _zip_progress_free(za->progress); - za->progress = NULL; - } - else { - _zip_progress_free_progress_callback(za->progress); - } - } + if (za->progress != NULL) { + if (za->progress->callback_cancel == NULL) { + _zip_progress_free(za->progress); + za->progress = NULL; + } + else { + _zip_progress_free_progress_callback(za->progress); + } + } } return 0; @@ -237,24 +237,24 @@ zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progr ZIP_EXTERN int zip_register_cancel_callback_with_state(zip_t *za, zip_cancel_callback callback, void (*ud_free)(void *), void *ud) { if (callback != NULL) { - if (za->progress == NULL) { - if ((za->progress = _zip_progress_new(za)) == NULL) { - return -1; - } - } + if (za->progress == NULL) { + if ((za->progress = _zip_progress_new(za)) == NULL) { + return -1; + } + } - _zip_progress_set_cancel_callback(za->progress, callback, ud_free, ud); + _zip_progress_set_cancel_callback(za->progress, callback, ud_free, ud); } else { - if (za->progress != NULL) { - if (za->progress->callback_progress == NULL) { - _zip_progress_free(za->progress); - za->progress = NULL; - } - else { - _zip_progress_free_cancel_callback(za->progress); - } - } + if (za->progress != NULL) { + if (za->progress->callback_progress == NULL) { + _zip_progress_free(za->progress); + za->progress = NULL; + } + else { + _zip_progress_free_cancel_callback(za->progress); + } + } } return 0; @@ -278,16 +278,16 @@ zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callb struct legacy_ud *ud; if (progress_callback == NULL) { - zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL); + zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL); } if ((ud = (struct legacy_ud *)malloc(sizeof(*ud))) == NULL) { - return; + return; } ud->callback = progress_callback; if (zip_register_progress_callback_with_state(za, 0.001, _zip_legacy_progress_callback, free, ud) < 0) { - free(ud); + free(ud); } } diff --git a/zip_random_win32.c b/zip_random_win32.c index 19d488e..436306b 100644 --- a/zip_random_win32.c +++ b/zip_random_win32.c @@ -1,6 +1,6 @@ /* zip_random_win32.c -- fill the user's buffer with random stuff (Windows version) - Copyright (C) 2016-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -47,13 +47,13 @@ ZIP_EXTERN bool zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { HCRYPTPROV hprov; if (!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { - return false; + return false; } if (!CryptGenRandom(hprov, length, buffer)) { - return false; + return false; } if (!CryptReleaseContext(hprov, 0)) { - return false; + return false; } return true; } @@ -69,11 +69,11 @@ zip_random_uint32(void) { zip_uint32_t value; if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) { - return value; + return value; } if (!seeded) { - srand((unsigned int)time(NULL)); + srand((unsigned int)time(NULL)); } return (zip_uint32_t)rand(); diff --git a/zip_rename.c b/zip_rename.c index 75b456d..3e67b7c 100644 --- a/zip_rename.c +++ b/zip_rename.c @@ -1,6 +1,6 @@ /* zip_rename.c -- rename file in zip archive - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at diff --git a/zip_replace.c b/zip_replace.c index 30a2eb1..e9a2973 100644 --- a/zip_replace.c +++ b/zip_replace.c @@ -1,6 +1,6 @@ /* zip_replace.c -- replace file via callback function - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at diff --git a/zip_set_archive_comment.c b/zip_set_archive_comment.c index 3f050b3..ee6f2ba 100644 --- a/zip_set_archive_comment.c +++ b/zip_set_archive_comment.c @@ -1,6 +1,6 @@ /* zip_set_archive_comment.c -- set archive comment - Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -42,38 +42,38 @@ zip_set_archive_comment(zip_t *za, const char *comment, zip_uint16_t len) { zip_string_t *cstr; if (ZIP_IS_RDONLY(za)) { - zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; } if (len > 0 && comment == NULL) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if (len > 0) { - if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, ZIP_FL_ENC_GUESS, &za->error)) == NULL) - return -1; + if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, ZIP_FL_ENC_GUESS, &za->error)) == NULL) + return -1; - if (_zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_CP437) { - _zip_string_free(cstr); - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; - } + if (_zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_CP437) { + _zip_string_free(cstr); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } } else - cstr = NULL; + cstr = NULL; _zip_string_free(za->comment_changes); za->comment_changes = NULL; if (((za->comment_orig && _zip_string_equal(za->comment_orig, cstr)) || (za->comment_orig == NULL && cstr == NULL))) { - _zip_string_free(cstr); - za->comment_changed = 0; + _zip_string_free(cstr); + za->comment_changed = 0; } else { - za->comment_changes = cstr; - za->comment_changed = 1; + za->comment_changes = cstr; + za->comment_changed = 1; } return 0; diff --git a/zip_set_archive_flag.c b/zip_set_archive_flag.c index e0d5502..a5afc81 100644 --- a/zip_set_archive_flag.c +++ b/zip_set_archive_flag.c @@ -1,6 +1,6 @@ /* zip_get_archive_flag.c -- set archive global flag - Copyright (C) 2008-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2008-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,23 +40,23 @@ zip_set_archive_flag(zip_t *za, zip_flags_t flag, int value) { unsigned int new_flags; if (value) - new_flags = za->ch_flags | flag; + new_flags = za->ch_flags | flag; else - new_flags = za->ch_flags & ~flag; + new_flags = za->ch_flags & ~flag; if (new_flags == za->ch_flags) - return 0; + return 0; if (ZIP_IS_RDONLY(za)) { - zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; } if ((flag & ZIP_AFL_RDONLY) && value && (za->ch_flags & ZIP_AFL_RDONLY) == 0) { - if (_zip_changed(za, NULL)) { - zip_error_set(&za->error, ZIP_ER_CHANGED, 0); - return -1; - } + if (_zip_changed(za, NULL)) { + zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + return -1; + } } za->ch_flags = new_flags; diff --git a/zip_set_default_password.c b/zip_set_default_password.c index 41c7c51..625ac3f 100644 --- a/zip_set_default_password.c +++ b/zip_set_default_password.c @@ -1,6 +1,6 @@ /* zip_set_default_password.c -- set default password for decryption - Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -41,18 +41,18 @@ ZIP_EXTERN int zip_set_default_password(zip_t *za, const char *passwd) { if (za == NULL) - return -1; + return -1; free(za->default_password); - if (passwd) { - if ((za->default_password = strdup(passwd)) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; - } + if (passwd && passwd[0] != '\0') { + if ((za->default_password = strdup(passwd)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } } else - za->default_password = NULL; + za->default_password = NULL; return 0; } diff --git a/zip_set_file_comment.c b/zip_set_file_comment.c index 4277893..2e7dcb7 100644 --- a/zip_set_file_comment.c +++ b/zip_set_file_comment.c @@ -1,6 +1,6 @@ /* zip_set_file_comment.c -- set comment for file in archive - Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -39,8 +39,8 @@ ZIP_EXTERN int zip_set_file_comment(zip_t *za, zip_uint64_t idx, const char *comment, int len) { if (len < 0 || len > ZIP_UINT16_MAX) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } return zip_file_set_comment(za, idx, comment, (zip_uint16_t)len, 0); } diff --git a/zip_set_file_compression.c b/zip_set_file_compression.c index 927fbb7..d2027c9 100644 --- a/zip_set_file_compression.c +++ b/zip_set_file_compression.c @@ -1,6 +1,6 @@ /* zip_set_file_compression.c -- set compression for file in archive - Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,19 +40,19 @@ zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_ui zip_entry_t *e; zip_int32_t old_method; - if (idx >= za->nentry || flags > 9) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + if (idx >= za->nentry) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if (ZIP_IS_RDONLY(za)) { - zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; } if (!zip_compression_method_supported(method, true)) { - zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + return -1; } e = za->entry + idx; @@ -65,26 +65,26 @@ zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_ui * to levels */ if (method == old_method) { - if (e->changes) { - e->changes->changed &= ~ZIP_DIRENT_COMP_METHOD; - e->changes->compression_level = 0; - if (e->changes->changed == 0) { - _zip_dirent_free(e->changes); - e->changes = NULL; - } - } + if (e->changes) { + e->changes->changed &= ~ZIP_DIRENT_COMP_METHOD; + e->changes->compression_level = 0; + if (e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + } } else { - if (e->changes == NULL) { - if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; - } - } + if (e->changes == NULL) { + if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } - e->changes->comp_method = method; - e->changes->compression_level = (zip_uint16_t)flags; - e->changes->changed |= ZIP_DIRENT_COMP_METHOD; + e->changes->comp_method = method; + e->changes->compression_level = (zip_uint16_t)flags; + e->changes->changed |= ZIP_DIRENT_COMP_METHOD; } return 0; diff --git a/zip_set_name.c b/zip_set_name.c index 43c772e..af4ec93 100644 --- a/zip_set_name.c +++ b/zip_set_name.c @@ -1,6 +1,6 @@ /* zip_set_name.c -- rename helper function - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -48,109 +48,109 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags) zip_string_t *old_str; if (idx >= za->nentry) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if (ZIP_IS_RDONLY(za)) { - zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; } if (name && name[0] != '\0') { - /* TODO: check for string too long */ - if ((str = _zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL) - return -1; - if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED) - str->encoding = ZIP_ENCODING_UTF8_KNOWN; + /* TODO: check for string too long */ + if ((str = _zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL) + return -1; + if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED) + str->encoding = ZIP_ENCODING_UTF8_KNOWN; } else - str = NULL; + str = NULL; /* TODO: encoding flags needed for CP437? */ if ((i = _zip_name_locate(za, name, 0, NULL)) >= 0 && (zip_uint64_t)i != idx) { - _zip_string_free(str); - zip_error_set(&za->error, ZIP_ER_EXISTS, 0); - return -1; + _zip_string_free(str); + zip_error_set(&za->error, ZIP_ER_EXISTS, 0); + return -1; } /* no effective name change */ if (i >= 0 && (zip_uint64_t)i == idx) { - _zip_string_free(str); - return 0; + _zip_string_free(str); + return 0; } e = za->entry + idx; if (e->orig) - same_as_orig = _zip_string_equal(e->orig->filename, str); + same_as_orig = _zip_string_equal(e->orig->filename, str); else - same_as_orig = false; + same_as_orig = false; if (!same_as_orig && e->changes == NULL) { - if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - _zip_string_free(str); - return -1; - } + if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_string_free(str); + return -1; + } } if ((new_name = _zip_string_get(same_as_orig ? e->orig->filename : str, NULL, 0, &za->error)) == NULL) { - _zip_string_free(str); - return -1; + _zip_string_free(str); + return -1; } if (e->changes) { - old_str = e->changes->filename; + old_str = e->changes->filename; } else if (e->orig) { - old_str = e->orig->filename; + old_str = e->orig->filename; } else { - old_str = NULL; + old_str = NULL; } if (old_str) { - if ((old_name = _zip_string_get(old_str, NULL, 0, &za->error)) == NULL) { - _zip_string_free(str); - return -1; - } + if ((old_name = _zip_string_get(old_str, NULL, 0, &za->error)) == NULL) { + _zip_string_free(str); + return -1; + } } else { - old_name = NULL; + old_name = NULL; } if (_zip_hash_add(za->names, new_name, idx, 0, &za->error) == false) { - _zip_string_free(str); - return -1; + _zip_string_free(str); + return -1; } if (old_name) { - _zip_hash_delete(za->names, old_name, NULL); + _zip_hash_delete(za->names, old_name, NULL); } if (same_as_orig) { - if (e->changes) { - if (e->changes->changed & ZIP_DIRENT_FILENAME) { - _zip_string_free(e->changes->filename); - e->changes->changed &= ~ZIP_DIRENT_FILENAME; - if (e->changes->changed == 0) { - _zip_dirent_free(e->changes); - e->changes = NULL; - } - else { - /* TODO: what if not cloned? can that happen? */ - e->changes->filename = e->orig->filename; - } - } - } - _zip_string_free(str); + if (e->changes) { + if (e->changes->changed & ZIP_DIRENT_FILENAME) { + _zip_string_free(e->changes->filename); + e->changes->changed &= ~ZIP_DIRENT_FILENAME; + if (e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + else { + /* TODO: what if not cloned? can that happen? */ + e->changes->filename = e->orig->filename; + } + } + } + _zip_string_free(str); } else { - if (e->changes->changed & ZIP_DIRENT_FILENAME) { - _zip_string_free(e->changes->filename); - } - e->changes->changed |= ZIP_DIRENT_FILENAME; - e->changes->filename = str; + if (e->changes->changed & ZIP_DIRENT_FILENAME) { + _zip_string_free(e->changes->filename); + } + e->changes->changed |= ZIP_DIRENT_FILENAME; + e->changes->filename = str; } return 0; diff --git a/zip_source_accept_empty.c b/zip_source_accept_empty.c index e6d5151..10f4012 100644 --- a/zip_source_accept_empty.c +++ b/zip_source_accept_empty.c @@ -1,6 +1,6 @@ /* zip_source_accept_empty.c -- if empty source is a valid archive - Copyright (C) 2019 Dieter Baron and Thomas Klausner + Copyright (C) 2019-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,10 +40,10 @@ zip_source_accept_empty(zip_source_t *src) { int ret; if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY)) == 0) { - if (ZIP_SOURCE_IS_LAYERED(src)) { - return zip_source_accept_empty(src->src); - } - return true; + if (ZIP_SOURCE_IS_LAYERED(src)) { + return zip_source_accept_empty(src->src); + } + return true; } ret = (int)_zip_source_call(src, NULL, 0, ZIP_SOURCE_ACCEPT_EMPTY); diff --git a/zip_source_begin_write.c b/zip_source_begin_write.c index 432c2c1..cefb809 100644 --- a/zip_source_begin_write.c +++ b/zip_source_begin_write.c @@ -1,6 +1,6 @@ /* zip_source_begin_write.c -- start a new file for writing - Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -38,12 +38,12 @@ ZIP_EXTERN int zip_source_begin_write(zip_source_t *src) { if (ZIP_SOURCE_IS_OPEN_WRITING(src)) { - zip_error_set(&src->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; } if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_BEGIN_WRITE) < 0) { - return -1; + return -1; } src->write_state = ZIP_SOURCE_WRITE_OPEN; diff --git a/zip_source_begin_write_cloning.c b/zip_source_begin_write_cloning.c index 41b4c73..71911e7 100644 --- a/zip_source_begin_write_cloning.c +++ b/zip_source_begin_write_cloning.c @@ -1,6 +1,6 @@ /* zip_source_begin_write_cloning.c -- clone part of file for writing - Copyright (C) 2017-2019 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 @@ -38,12 +38,12 @@ ZIP_EXTERN int zip_source_begin_write_cloning(zip_source_t *src, zip_uint64_t offset) { if (ZIP_SOURCE_IS_OPEN_WRITING(src)) { - zip_error_set(&src->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; } if (_zip_source_call(src, NULL, offset, ZIP_SOURCE_BEGIN_WRITE_CLONING) < 0) { - return -1; + return -1; } src->write_state = ZIP_SOURCE_WRITE_OPEN; diff --git a/zip_source_buffer.c b/zip_source_buffer.c index 519d2c3..e0ab72b 100644 --- a/zip_source_buffer.c +++ b/zip_source_buffer.c @@ -1,6 +1,6 @@ /* zip_source_buffer.c -- create zip data source from buffer - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -87,7 +87,7 @@ zip_source_t *zip_source_buffer_fragment_with_attributes_create(const zip_buffer ZIP_EXTERN zip_source_t * zip_source_buffer(zip_t *za, const void *data, zip_uint64_t len, int freep) { if (za == NULL) - return NULL; + return NULL; return zip_source_buffer_with_attributes_create(data, len, freep, NULL, &za->error); } @@ -104,12 +104,12 @@ zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int zip_buffer_fragment_t fragment; if (data == NULL) { - if (len > 0) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; - } + if (len > 0) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } - return zip_source_buffer_fragment_with_attributes_create(NULL, 0, freep, attributes, error); + return zip_source_buffer_fragment_with_attributes_create(NULL, 0, freep, attributes, error); } fragment.data = (zip_uint8_t *)data; @@ -122,7 +122,7 @@ zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int ZIP_EXTERN zip_source_t * zip_source_buffer_fragment(zip_t *za, const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep) { if (za == NULL) { - return NULL; + return NULL; } return zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, &za->error); @@ -141,35 +141,35 @@ zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *f buffer_t *buffer; if (fragments == NULL && nfragments > 0) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } if ((buffer = buffer_new(fragments, nfragments, freep, error)) == NULL) { - return NULL; + return NULL; } if ((ctx = (struct read_data *)malloc(sizeof(*ctx))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - buffer_free(buffer); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + buffer_free(buffer); + return NULL; } ctx->in = buffer; ctx->out = NULL; ctx->mtime = time(NULL); if (attributes) { - memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes)); + memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes)); } else { - zip_file_attributes_init(&ctx->attributes); + zip_file_attributes_init(&ctx->attributes); } zip_error_init(&ctx->error); if ((zs = zip_source_function_create(read_data, ctx, error)) == NULL) { - buffer_free(ctx->in); - free(ctx); - return NULL; + buffer_free(ctx->in); + free(ctx); + return NULL; } return zs; @@ -187,133 +187,133 @@ read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { switch (cmd) { case ZIP_SOURCE_BEGIN_WRITE: - if ((ctx->out = buffer_new(NULL, 0, 0, &ctx->error)) == NULL) { - return -1; - } - ctx->out->offset = 0; - ctx->out->current_fragment = 0; - return 0; + if ((ctx->out = buffer_new(NULL, 0, 0, &ctx->error)) == NULL) { + return -1; + } + ctx->out->offset = 0; + ctx->out->current_fragment = 0; + return 0; case ZIP_SOURCE_BEGIN_WRITE_CLONING: - if ((ctx->out = buffer_clone(ctx->in, len, &ctx->error)) == NULL) { - return -1; - } - ctx->out->offset = len; - ctx->out->current_fragment = ctx->out->nfragments; - return 0; + if ((ctx->out = buffer_clone(ctx->in, len, &ctx->error)) == NULL) { + return -1; + } + ctx->out->offset = len; + ctx->out->current_fragment = ctx->out->nfragments; + return 0; case ZIP_SOURCE_CLOSE: - return 0; + return 0; case ZIP_SOURCE_COMMIT_WRITE: - buffer_free(ctx->in); - ctx->in = ctx->out; - ctx->out = NULL; - return 0; + buffer_free(ctx->in); + ctx->in = ctx->out; + ctx->out = NULL; + return 0; case ZIP_SOURCE_ERROR: - return zip_error_to_data(&ctx->error, data, len); + return zip_error_to_data(&ctx->error, data, len); case ZIP_SOURCE_FREE: - buffer_free(ctx->in); - buffer_free(ctx->out); - free(ctx); - return 0; + buffer_free(ctx->in); + buffer_free(ctx->out); + free(ctx); + return 0; case ZIP_SOURCE_GET_FILE_ATTRIBUTES: { - if (len < sizeof(ctx->attributes)) { - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; - } + if (len < sizeof(ctx->attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } - memcpy(data, &ctx->attributes, sizeof(ctx->attributes)); + memcpy(data, &ctx->attributes, sizeof(ctx->attributes)); - return sizeof(ctx->attributes); + return sizeof(ctx->attributes); } case ZIP_SOURCE_OPEN: - ctx->in->offset = 0; - ctx->in->current_fragment = 0; - return 0; + ctx->in->offset = 0; + ctx->in->current_fragment = 0; + return 0; case ZIP_SOURCE_READ: - if (len > ZIP_INT64_MAX) { - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; - } - return buffer_read(ctx->in, data, len); + if (len > ZIP_INT64_MAX) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + return buffer_read(ctx->in, data, len); case ZIP_SOURCE_REMOVE: { - buffer_t *empty = buffer_new(NULL, 0, 0, &ctx->error); - if (empty == NULL) { - return -1; - } + buffer_t *empty = buffer_new(NULL, 0, 0, &ctx->error); + if (empty == NULL) { + return -1; + } - buffer_free(ctx->in); - ctx->in = empty; - return 0; + buffer_free(ctx->in); + ctx->in = empty; + return 0; } case ZIP_SOURCE_ROLLBACK_WRITE: - buffer_free(ctx->out); - ctx->out = NULL; - return 0; + buffer_free(ctx->out); + ctx->out = NULL; + return 0; case ZIP_SOURCE_SEEK: - return buffer_seek(ctx->in, data, len, &ctx->error); + return buffer_seek(ctx->in, data, len, &ctx->error); case ZIP_SOURCE_SEEK_WRITE: - return buffer_seek(ctx->out, data, len, &ctx->error); + return buffer_seek(ctx->out, data, len, &ctx->error); case ZIP_SOURCE_STAT: { - zip_stat_t *st; + zip_stat_t *st; - if (len < sizeof(*st)) { - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; - } + if (len < sizeof(*st)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } - st = (zip_stat_t *)data; + st = (zip_stat_t *)data; - zip_stat_init(st); - st->mtime = ctx->mtime; - st->size = ctx->in->size; - st->comp_size = st->size; - st->comp_method = ZIP_CM_STORE; - st->encryption_method = ZIP_EM_NONE; - st->valid = ZIP_STAT_MTIME | ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD; + zip_stat_init(st); + st->mtime = ctx->mtime; + st->size = ctx->in->size; + st->comp_size = st->size; + st->comp_method = ZIP_CM_STORE; + st->encryption_method = ZIP_EM_NONE; + st->valid = ZIP_STAT_MTIME | ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD; - return sizeof(*st); + return sizeof(*st); } case ZIP_SOURCE_SUPPORTS: - return zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_BEGIN_WRITE_CLONING, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, -1); + return zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_BEGIN_WRITE_CLONING, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, -1); case ZIP_SOURCE_TELL: - if (ctx->in->offset > ZIP_INT64_MAX) { - zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW); - return -1; - } - return (zip_int64_t)ctx->in->offset; + if (ctx->in->offset > ZIP_INT64_MAX) { + zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW); + return -1; + } + return (zip_int64_t)ctx->in->offset; case ZIP_SOURCE_TELL_WRITE: - if (ctx->out->offset > ZIP_INT64_MAX) { - zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW); - return -1; - } - return (zip_int64_t)ctx->out->offset; + if (ctx->out->offset > ZIP_INT64_MAX) { + zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW); + return -1; + } + return (zip_int64_t)ctx->out->offset; case ZIP_SOURCE_WRITE: - if (len > ZIP_INT64_MAX) { - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; - } - return buffer_write(ctx->out, data, len, &ctx->error); + if (len > ZIP_INT64_MAX) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + return buffer_write(ctx->out, data, len, &ctx->error); default: - zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); - return -1; + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; } } @@ -324,34 +324,34 @@ buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) { buffer_t *clone; if (offset == 0) { - return buffer_new(NULL, 0, 1, error); + return buffer_new(NULL, 0, 1, error); } if (offset > buffer->size) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } if (buffer->shared_buffer != NULL) { - zip_error_set(error, ZIP_ER_INUSE, 0); - return NULL; + zip_error_set(error, ZIP_ER_INUSE, 0); + return NULL; } fragment = buffer_find_fragment(buffer, offset); fragment_offset = offset - buffer->fragment_offsets[fragment]; if (fragment_offset == 0) { - fragment--; - fragment_offset = buffer->fragments[fragment].length; + fragment--; + fragment_offset = buffer->fragments[fragment].length; } waste = buffer->fragments[fragment].length - fragment_offset; if (waste > offset) { - zip_error_set(error, ZIP_ER_OPNOTSUPP, 0); - return NULL; + zip_error_set(error, ZIP_ER_OPNOTSUPP, 0); + return NULL; } if ((clone = buffer_new(buffer->fragments, fragment + 1, 0, error)) == NULL) { - return NULL; + return NULL; } #ifndef __clang_analyzer__ @@ -380,16 +380,16 @@ buffer_find_fragment(const buffer_t *buffer, zip_uint64_t offset) { high = buffer->nfragments - 1; while (low < high) { - mid = (high - low) / 2 + low; - if (buffer->fragment_offsets[mid] > offset) { - high = mid - 1; - } - else if (mid == buffer->nfragments || buffer->fragment_offsets[mid + 1] > offset) { - return mid; - } - else { - low = mid + 1; - } + mid = (high - low) / 2 + low; + if (buffer->fragment_offsets[mid] > offset) { + high = mid - 1; + } + else if (mid == buffer->nfragments || buffer->fragment_offsets[mid + 1] > offset) { + return mid; + } + else { + low = mid + 1; + } } return low; @@ -401,18 +401,18 @@ buffer_free(buffer_t *buffer) { zip_uint64_t i; if (buffer == NULL) { - return; + return; } if (buffer->shared_buffer != NULL) { - buffer->shared_buffer->shared_buffer = NULL; - buffer->shared_buffer->shared_fragments = 0; + buffer->shared_buffer->shared_buffer = NULL; + buffer->shared_buffer->shared_fragments = 0; - buffer->first_owned_fragment = ZIP_MAX(buffer->first_owned_fragment, buffer->shared_fragments); + buffer->first_owned_fragment = ZIP_MAX(buffer->first_owned_fragment, buffer->shared_fragments); } for (i = buffer->first_owned_fragment; i < buffer->nfragments; i++) { - free(buffer->fragments[i].data); + free(buffer->fragments[i].data); } free(buffer->fragments); free(buffer->fragment_offsets); @@ -426,17 +426,17 @@ buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *erro zip_uint64_t *offsets; if (capacity < buffer->fragments_capacity) { - return true; + return true; } if ((fragments = realloc(buffer->fragments, sizeof(buffer->fragments[0]) * capacity)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return false; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; } buffer->fragments = fragments; if ((offsets = realloc(buffer->fragment_offsets, sizeof(buffer->fragment_offsets[0]) * (capacity + 1))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return false; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; } buffer->fragment_offsets = offsets; buffer->fragments_capacity = capacity; @@ -450,7 +450,7 @@ buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int buffer_t *buffer; if ((buffer = malloc(sizeof(*buffer))) == NULL) { - return NULL; + return NULL; } buffer->offset = 0; @@ -464,42 +464,42 @@ buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int buffer->shared_fragments = 0; if (nfragments == 0) { - if ((buffer->fragment_offsets = malloc(sizeof(buffer->fragment_offsets[0]))) == NULL) { - free(buffer); - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; - } - buffer->fragment_offsets[0] = 0; + if ((buffer->fragment_offsets = malloc(sizeof(buffer->fragment_offsets[0]))) == NULL) { + free(buffer); + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + buffer->fragment_offsets[0] = 0; } else { - zip_uint64_t i, j, offset; + zip_uint64_t i, j, offset; - if (!buffer_grow_fragments(buffer, nfragments, NULL)) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - buffer_free(buffer); - return NULL; - } + if (!buffer_grow_fragments(buffer, nfragments, NULL)) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + buffer_free(buffer); + return NULL; + } - offset = 0; - for (i = 0, j = 0; i < nfragments; i++) { - if (fragments[i].length == 0) { - continue; - } - if (fragments[i].data == NULL) { - zip_error_set(error, ZIP_ER_INVAL, 0); - buffer_free(buffer); - return NULL; - } - buffer->fragments[j].data = fragments[i].data; - buffer->fragments[j].length = fragments[i].length; - buffer->fragment_offsets[i] = offset; - offset += fragments[i].length; - j++; - } - buffer->nfragments = j; - buffer->first_owned_fragment = free_data ? 0 : buffer->nfragments; - buffer->fragment_offsets[buffer->nfragments] = offset; - buffer->size = offset; + offset = 0; + for (i = 0, j = 0; i < nfragments; i++) { + if (fragments[i].length == 0) { + continue; + } + if (fragments[i].data == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + buffer_free(buffer); + return NULL; + } + buffer->fragments[j].data = fragments[i].data; + buffer->fragments[j].length = fragments[i].length; + buffer->fragment_offsets[i] = offset; + offset += fragments[i].length; + j++; + } + buffer->nfragments = j; + buffer->first_owned_fragment = free_data ? 0 : buffer->nfragments; + buffer->fragment_offsets[buffer->nfragments] = offset; + buffer->size = offset; } return buffer; @@ -512,25 +512,25 @@ buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) { length = ZIP_MIN(length, buffer->size - buffer->offset); if (length == 0) { - return 0; + return 0; } if (length > ZIP_INT64_MAX) { - return -1; + return -1; } i = buffer->current_fragment; fragment_offset = buffer->offset - buffer->fragment_offsets[i]; n = 0; while (n < length) { - zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset); + zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset); - memcpy(data + n, buffer->fragments[i].data + fragment_offset, left); + memcpy(data + n, buffer->fragments[i].data + fragment_offset, left); - if (left == buffer->fragments[i].length - fragment_offset) { - i++; - } - n += left; - fragment_offset = 0; + if (left == buffer->fragments[i].length - fragment_offset) { + i++; + } + n += left; + fragment_offset = 0; } buffer->offset += n; @@ -544,7 +544,7 @@ buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error) zip_int64_t new_offset = zip_source_seek_compute_offset(buffer->offset, buffer->size, data, len, error); if (new_offset < 0) { - return -1; + return -1; } buffer->offset = (zip_uint64_t)new_offset; @@ -558,62 +558,62 @@ buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip zip_uint64_t n, i, fragment_offset, capacity; if (buffer->offset + length + WRITE_FRAGMENT_SIZE - 1 < length) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; } /* grow buffer if needed */ capacity = buffer_capacity(buffer); if (buffer->offset + length > capacity) { - zip_uint64_t needed_fragments = buffer->nfragments + (length - (capacity - buffer->offset) + WRITE_FRAGMENT_SIZE - 1) / WRITE_FRAGMENT_SIZE; + zip_uint64_t needed_fragments = buffer->nfragments + (length - (capacity - buffer->offset) + WRITE_FRAGMENT_SIZE - 1) / WRITE_FRAGMENT_SIZE; - if (needed_fragments > buffer->fragments_capacity) { - zip_uint64_t new_capacity = buffer->fragments_capacity; + if (needed_fragments > buffer->fragments_capacity) { + zip_uint64_t new_capacity = buffer->fragments_capacity; - if (new_capacity == 0) { - new_capacity = 16; - } - while (new_capacity < needed_fragments) { - new_capacity *= 2; - } + if (new_capacity == 0) { + new_capacity = 16; + } + while (new_capacity < needed_fragments) { + new_capacity *= 2; + } - if (!buffer_grow_fragments(buffer, new_capacity, error)) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return -1; - } - } + if (!buffer_grow_fragments(buffer, new_capacity, error)) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return -1; + } + } - while (buffer->nfragments < needed_fragments) { - if ((buffer->fragments[buffer->nfragments].data = malloc(WRITE_FRAGMENT_SIZE)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return -1; - } - buffer->fragments[buffer->nfragments].length = WRITE_FRAGMENT_SIZE; - buffer->nfragments++; - capacity += WRITE_FRAGMENT_SIZE; - buffer->fragment_offsets[buffer->nfragments] = capacity; - } + while (buffer->nfragments < needed_fragments) { + if ((buffer->fragments[buffer->nfragments].data = malloc(WRITE_FRAGMENT_SIZE)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return -1; + } + buffer->fragments[buffer->nfragments].length = WRITE_FRAGMENT_SIZE; + buffer->nfragments++; + capacity += WRITE_FRAGMENT_SIZE; + buffer->fragment_offsets[buffer->nfragments] = capacity; + } } i = buffer->current_fragment; fragment_offset = buffer->offset - buffer->fragment_offsets[i]; n = 0; while (n < length) { - zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset); + zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset); - memcpy(buffer->fragments[i].data + fragment_offset, data + n, left); + memcpy(buffer->fragments[i].data + fragment_offset, data + n, left); - if (left == buffer->fragments[i].length - fragment_offset) { - i++; - } - n += left; - fragment_offset = 0; + if (left == buffer->fragments[i].length - fragment_offset) { + i++; + } + n += left; + fragment_offset = 0; } buffer->offset += n; buffer->current_fragment = i; if (buffer->offset > buffer->size) { - buffer->size = buffer->offset; + buffer->size = buffer->offset; } return (zip_int64_t)n; diff --git a/zip_source_call.c b/zip_source_call.c index e7c2954..41b5c0f 100644 --- a/zip_source_call.c +++ b/zip_source_call.c @@ -1,6 +1,6 @@ /* zip_source_call.c -- invoke callback command on zip_source - Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,28 +40,28 @@ _zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_ zip_int64_t ret; if ((src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(command)) == 0) { - zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0); - return -1; + zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0); + return -1; } if (src->src == NULL) { - ret = src->cb.f(src->ud, data, length, command); + ret = src->cb.f(src->ud, data, length, command); } else { - ret = src->cb.l(src->src, src->ud, data, length, command); + ret = src->cb.l(src->src, src->ud, data, length, command); } if (ret < 0) { - if (command != ZIP_SOURCE_ERROR && command != ZIP_SOURCE_SUPPORTS) { - int e[2]; + if (command != ZIP_SOURCE_ERROR && command != ZIP_SOURCE_SUPPORTS) { + int e[2]; - if (_zip_source_call(src, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) { - zip_error_set(&src->error, ZIP_ER_INTERNAL, 0); - } - else { - zip_error_set(&src->error, e[0], e[1]); - } - } + if (_zip_source_call(src, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) { + zip_error_set(&src->error, ZIP_ER_INTERNAL, 0); + } + else { + zip_error_set(&src->error, e[0], e[1]); + } + } } return ret; diff --git a/zip_source_close.c b/zip_source_close.c index ab7898c..48efe8a 100644 --- a/zip_source_close.c +++ b/zip_source_close.c @@ -1,6 +1,6 @@ /* zip_source_close.c -- close zip_source (stop reading) - Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -38,19 +38,19 @@ int zip_source_close(zip_source_t *src) { if (!ZIP_SOURCE_IS_OPEN_READING(src)) { - zip_error_set(&src->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; } src->open_count--; if (src->open_count == 0) { - _zip_source_call(src, NULL, 0, ZIP_SOURCE_CLOSE); + _zip_source_call(src, NULL, 0, ZIP_SOURCE_CLOSE); - if (ZIP_SOURCE_IS_LAYERED(src)) { - if (zip_source_close(src->src) < 0) { - zip_error_set(&src->error, ZIP_ER_INTERNAL, 0); - } - } + if (ZIP_SOURCE_IS_LAYERED(src)) { + if (zip_source_close(src->src) < 0) { + zip_error_set(&src->error, ZIP_ER_INTERNAL, 0); + } + } } return 0; diff --git a/zip_source_commit_write.c b/zip_source_commit_write.c index d1254bf..30243d5 100644 --- a/zip_source_commit_write.c +++ b/zip_source_commit_write.c @@ -1,6 +1,6 @@ /* zip_source_commit_write.c -- commit changes to file - Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -38,23 +38,23 @@ ZIP_EXTERN int zip_source_commit_write(zip_source_t *src) { if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) { - zip_error_set(&src->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; } if (src->open_count > 1) { - zip_error_set(&src->error, ZIP_ER_INUSE, 0); - return -1; + zip_error_set(&src->error, ZIP_ER_INUSE, 0); + return -1; } else if (ZIP_SOURCE_IS_OPEN_READING(src)) { - if (zip_source_close(src) < 0) { - return -1; - } + if (zip_source_close(src) < 0) { + return -1; + } } if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_COMMIT_WRITE) < 0) { - src->write_state = ZIP_SOURCE_WRITE_FAILED; - return -1; + src->write_state = ZIP_SOURCE_WRITE_FAILED; + return -1; } src->write_state = ZIP_SOURCE_WRITE_CLOSED; diff --git a/zip_source_compress.c b/zip_source_compress.c index e49929f..9776065 100644 --- a/zip_source_compress.c +++ b/zip_source_compress.c @@ -1,6 +1,6 @@ /* zip_source_compress.c -- (de)compression routines - Copyright (C) 2017-2019 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 @@ -67,14 +67,17 @@ static struct implementation implementations[] = { {ZIP_CM_BZIP2, &zip_algorithm_bzip2_compress, &zip_algorithm_bzip2_decompress}, #endif #if defined(HAVE_LIBLZMA) - /* Disabled - because 7z isn't able to unpack ZIP+LZMA ZIP+LZMA2 - archives made this way - and vice versa. + {ZIP_CM_LZMA, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress}, + /* Disabled - because 7z isn't able to unpack ZIP+LZMA2 + archives made this way - and vice versa. - {ZIP_CM_LZMA, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress}, - {ZIP_CM_LZMA2, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress}, + {ZIP_CM_LZMA2, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress}, */ {ZIP_CM_XZ, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress}, #endif +#if defined(HAVE_LIBZSTD) + {ZIP_CM_ZSTD, &zip_algorithm_zstd_compress, &zip_algorithm_zstd_decompress}, +#endif }; @@ -86,20 +89,20 @@ static void context_free(struct context *ctx); static struct context *context_new(zip_int32_t method, bool compress, int compression_flags, zip_compression_algorithm_t *algorithm); static zip_int64_t compress_read(zip_source_t *, struct context *, void *, zip_uint64_t); -static zip_compression_algorithm_t * -get_algorithm(zip_int32_t method, bool compress) { +zip_compression_algorithm_t * +_zip_get_compression_algorithm(zip_int32_t method, bool compress) { size_t i; zip_uint16_t real_method = ZIP_CM_ACTUAL(method); for (i = 0; i < implementations_size; i++) { - if (implementations[i].method == real_method) { - if (compress) { - return implementations[i].compress; - } - else { - return implementations[i].decompress; - } - } + if (implementations[i].method == real_method) { + if (compress) { + return implementations[i].compress; + } + else { + return implementations[i].decompress; + } + } } return NULL; @@ -108,9 +111,9 @@ get_algorithm(zip_int32_t method, bool compress) { ZIP_EXTERN int zip_compression_method_supported(zip_int32_t method, int compress) { if (method == ZIP_CM_STORE) { - return 1; + return 1; } - return get_algorithm(method, compress) != NULL; + return _zip_get_compression_algorithm(method, compress) != NULL; } zip_source_t * @@ -131,23 +134,23 @@ compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool co zip_compression_algorithm_t *algorithm = NULL; if (src == NULL) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; } - if ((algorithm = get_algorithm(method, compress)) == NULL) { - zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); - return NULL; + if ((algorithm = _zip_get_compression_algorithm(method, compress)) == NULL) { + zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + return NULL; } if ((ctx = context_new(method, compress, compression_flags, algorithm)) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; } if ((s2 = zip_source_layered(za, src, compress_callback, ctx)) == NULL) { - context_free(ctx); - return NULL; + context_free(ctx); + return NULL; } return s2; @@ -159,7 +162,7 @@ context_new(zip_int32_t method, bool compress, int compression_flags, zip_compre struct context *ctx; if ((ctx = (struct context *)malloc(sizeof(*ctx))) == NULL) { - return NULL; + return NULL; } zip_error_init(&ctx->error); ctx->can_store = compress ? ZIP_CM_IS_DEFAULT(method) : false; @@ -171,9 +174,9 @@ context_new(zip_int32_t method, bool compress, int compression_flags, zip_compre ctx->is_stored = false; if ((ctx->ud = ctx->algorithm->allocate(ZIP_CM_ACTUAL(method), compression_flags, &ctx->error)) == NULL) { - zip_error_fini(&ctx->error); - free(ctx); - return NULL; + zip_error_fini(&ctx->error); + free(ctx); + return NULL; } return ctx; @@ -183,7 +186,7 @@ context_new(zip_int32_t method, bool compress, int compression_flags, zip_compre static void context_free(struct context *ctx) { if (ctx == NULL) { - return; + return; } ctx->algorithm->deallocate(ctx->ud); @@ -202,96 +205,96 @@ compress_read(zip_source_t *src, struct context *ctx, void *data, zip_uint64_t l zip_uint64_t out_len; if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK) { - return -1; + return -1; } if (len == 0 || ctx->end_of_stream) { - return 0; + return 0; } out_offset = 0; end = false; while (!end && out_offset < len) { - out_len = len - out_offset; - ret = ctx->algorithm->process(ctx->ud, (zip_uint8_t *)data + out_offset, &out_len); + out_len = len - out_offset; + ret = ctx->algorithm->process(ctx->ud, (zip_uint8_t *)data + out_offset, &out_len); - if (ret != ZIP_COMPRESSION_ERROR) { - out_offset += out_len; - } + if (ret != ZIP_COMPRESSION_ERROR) { + out_offset += out_len; + } - switch (ret) { - case ZIP_COMPRESSION_END: - ctx->end_of_stream = true; + switch (ret) { + case ZIP_COMPRESSION_END: + ctx->end_of_stream = true; - if (!ctx->end_of_input) { - /* TODO: garbage after stream, or compression ended before all data read */ - } + if (!ctx->end_of_input) { + /* TODO: garbage after stream, or compression ended before all data read */ + } - if (ctx->first_read < 0) { - /* we got end of processed stream before reading any input data */ - zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); - end = true; - break; - } - if (ctx->can_store && (zip_uint64_t)ctx->first_read <= out_offset) { - ctx->is_stored = true; - ctx->size = (zip_uint64_t)ctx->first_read; - memcpy(data, ctx->buffer, ctx->size); - return (zip_int64_t)ctx->size; - } - end = true; - break; + if (ctx->first_read < 0) { + /* we got end of processed stream before reading any input data */ + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + end = true; + break; + } + if (ctx->can_store && (zip_uint64_t)ctx->first_read <= out_offset) { + ctx->is_stored = true; + ctx->size = (zip_uint64_t)ctx->first_read; + memcpy(data, ctx->buffer, ctx->size); + return (zip_int64_t)ctx->size; + } + end = true; + break; - case ZIP_COMPRESSION_OK: - break; + case ZIP_COMPRESSION_OK: + break; - case ZIP_COMPRESSION_NEED_DATA: - if (ctx->end_of_input) { - /* TODO: error: stream not ended, but no more input */ - end = true; - break; - } + case ZIP_COMPRESSION_NEED_DATA: + if (ctx->end_of_input) { + /* TODO: error: stream not ended, but no more input */ + end = true; + break; + } - if ((n = zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) { - _zip_error_set_from_source(&ctx->error, src); - end = true; - break; - } - else if (n == 0) { - ctx->end_of_input = true; - ctx->algorithm->end_of_input(ctx->ud); - if (ctx->first_read < 0) { - ctx->first_read = 0; - } - } - else { - if (ctx->first_read >= 0) { - /* we overwrote a previously filled ctx->buffer */ - ctx->can_store = false; - } - else { - ctx->first_read = n; - } + if ((n = zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) { + _zip_error_set_from_source(&ctx->error, src); + end = true; + break; + } + else if (n == 0) { + ctx->end_of_input = true; + ctx->algorithm->end_of_input(ctx->ud); + if (ctx->first_read < 0) { + ctx->first_read = 0; + } + } + else { + if (ctx->first_read >= 0) { + /* we overwrote a previously filled ctx->buffer */ + ctx->can_store = false; + } + else { + ctx->first_read = n; + } - ctx->algorithm->input(ctx->ud, ctx->buffer, (zip_uint64_t)n); - } - break; + ctx->algorithm->input(ctx->ud, ctx->buffer, (zip_uint64_t)n); + } + break; - case ZIP_COMPRESSION_ERROR: - /* error set by algorithm */ - if (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) { - zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); - } - end = true; - break; - } + case ZIP_COMPRESSION_ERROR: + /* error set by algorithm */ + if (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + } + end = true; + break; + } } if (out_offset > 0) { - ctx->can_store = false; - ctx->size += out_offset; - return (zip_int64_t)out_offset; + ctx->can_store = false; + ctx->size += out_offset; + return (zip_int64_t)out_offset; } return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1; @@ -305,85 +308,91 @@ compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip ctx = (struct context *)ud; switch (cmd) { - case ZIP_SOURCE_OPEN: - ctx->size = 0; - ctx->end_of_input = false; - ctx->end_of_stream = false; - ctx->is_stored = false; - ctx->first_read = -1; + case ZIP_SOURCE_OPEN: { + zip_stat_t st; + zip_file_attributes_t attributes; + + ctx->size = 0; + ctx->end_of_input = false; + ctx->end_of_stream = false; + ctx->is_stored = false; + ctx->first_read = -1; + + if (zip_source_stat(src, &st) < 0 || zip_source_get_file_attributes(src, &attributes) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } - if (!ctx->algorithm->start(ctx->ud)) { - return -1; - } + if (!ctx->algorithm->start(ctx->ud, &st, &attributes)) { + return -1; + } - return 0; + return 0; + } case ZIP_SOURCE_READ: - return compress_read(src, ctx, data, len); + return compress_read(src, ctx, data, len); case ZIP_SOURCE_CLOSE: - if (!ctx->algorithm->end(ctx->ud)) { - return -1; - } - return 0; + if (!ctx->algorithm->end(ctx->ud)) { + return -1; + } + return 0; case ZIP_SOURCE_STAT: { - zip_stat_t *st; + zip_stat_t *st; - st = (zip_stat_t *)data; + st = (zip_stat_t *)data; - if (ctx->compress) { - if (ctx->end_of_stream) { - st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_ACTUAL(ctx->method); - st->comp_size = ctx->size; - st->valid |= ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD; - } - else { - st->valid &= ~(ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD); - } - } - else { - st->comp_method = ZIP_CM_STORE; - st->valid |= ZIP_STAT_COMP_METHOD; - if (ctx->end_of_stream) { - st->size = ctx->size; - st->valid |= ZIP_STAT_SIZE; - } - else { - st->valid &= ~ZIP_STAT_SIZE; - } - } + if (ctx->compress) { + if (ctx->end_of_stream) { + st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_ACTUAL(ctx->method); + st->comp_size = ctx->size; + st->valid |= ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD; + } + else { + st->valid &= ~(ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD); + } + } + else { + st->comp_method = ZIP_CM_STORE; + st->valid |= ZIP_STAT_COMP_METHOD; + if (ctx->end_of_stream) { + st->size = ctx->size; + st->valid |= ZIP_STAT_SIZE; + } + } } - return 0; + return 0; case ZIP_SOURCE_ERROR: - return zip_error_to_data(&ctx->error, data, len); + return zip_error_to_data(&ctx->error, data, len); case ZIP_SOURCE_FREE: - context_free(ctx); - return 0; + context_free(ctx); + return 0; case ZIP_SOURCE_GET_FILE_ATTRIBUTES: { - zip_file_attributes_t *attributes = (zip_file_attributes_t *)data; + zip_file_attributes_t *attributes = (zip_file_attributes_t *)data; - if (len < sizeof(*attributes)) { - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; - } + if (len < sizeof(*attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } - attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED | ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS; - attributes->version_needed = ctx->algorithm->version_needed; - attributes->general_purpose_bit_mask = ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK; - attributes->general_purpose_bit_flags = (ctx->is_stored ? 0 : ctx->algorithm->general_purpose_bit_flags(ctx->ud)); + attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED | ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS; + attributes->version_needed = ctx->algorithm->version_needed; + attributes->general_purpose_bit_mask = ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK; + attributes->general_purpose_bit_flags = (ctx->is_stored ? 0 : ctx->algorithm->general_purpose_bit_flags(ctx->ud)); - return sizeof(*attributes); + return sizeof(*attributes); } case ZIP_SOURCE_SUPPORTS: - return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1); + return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1); default: - zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); - return -1; + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + return -1; } } diff --git a/zip_source_crc.c b/zip_source_crc.c index 4f3f223..ebbeaa7 100644 --- a/zip_source_crc.c +++ b/zip_source_crc.c @@ -1,6 +1,6 @@ /* zip_source_crc.c -- pass-through source that calculates CRC32 and size - Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -52,17 +52,17 @@ static zip_int64_t crc_read(zip_source_t *, void *, void *, zip_uint64_t, zip_so zip_source_t * -zip_source_crc(zip_t *za, zip_source_t *src, int validate) { +zip_source_crc_create(zip_source_t *src, int validate, zip_error_t *error) { struct crc_context *ctx; if (src == NULL) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } if ((ctx = (struct crc_context *)malloc(sizeof(*ctx))) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } zip_error_init(&ctx->error); @@ -72,7 +72,7 @@ zip_source_crc(zip_t *za, zip_source_t *src, int validate) { ctx->crc = (zip_uint32_t)crc32(0, NULL, 0); ctx->size = 0; - return zip_source_layered(za, src, crc_read, ctx); + return zip_source_layered_create(src, crc_read, ctx, error); } @@ -85,113 +85,114 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source switch (cmd) { case ZIP_SOURCE_OPEN: - ctx->position = 0; - return 0; + ctx->position = 0; + return 0; case ZIP_SOURCE_READ: - if ((n = zip_source_read(src, data, len)) < 0) { - _zip_error_set_from_source(&ctx->error, src); - return -1; - } + if ((n = zip_source_read(src, data, len)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } - if (n == 0) { - if (ctx->crc_position == ctx->position) { - ctx->crc_complete = 1; - ctx->size = ctx->position; + if (n == 0) { + if (ctx->crc_position == ctx->position) { + ctx->crc_complete = 1; + ctx->size = ctx->position; - if (ctx->validate) { - struct zip_stat st; + if (ctx->validate) { + struct zip_stat st; - if (zip_source_stat(src, &st) < 0) { - _zip_error_set_from_source(&ctx->error, src); - return -1; - } + if (zip_source_stat(src, &st) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } - if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) { - zip_error_set(&ctx->error, ZIP_ER_CRC, 0); - return -1; - } - if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) { - zip_error_set(&ctx->error, ZIP_ER_INCONS, 0); - return -1; - } - } - } - } - else if (!ctx->crc_complete && ctx->position <= ctx->crc_position) { - zip_uint64_t i, nn; + if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) { + zip_error_set(&ctx->error, ZIP_ER_CRC, 0); + return -1; + } + if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) { + /* We don't have the index here, but the caller should know which file they are reading from. */ + zip_error_set(&ctx->error, ZIP_ER_INCONS, MAKE_DETAIL_WITH_INDEX(ZIP_ER_DETAIL_INVALID_FILE_LENGTH, MAX_DETAIL_INDEX)); + return -1; + } + } + } + } + else if (!ctx->crc_complete && ctx->position <= ctx->crc_position) { + zip_uint64_t i, nn; - for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) { - nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n - i); + for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) { + nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n - i); - ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data + i, (uInt)nn); - ctx->crc_position += nn; - } - } - ctx->position += (zip_uint64_t)n; - return n; + ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data + i, (uInt)nn); + ctx->crc_position += nn; + } + } + ctx->position += (zip_uint64_t)n; + return n; case ZIP_SOURCE_CLOSE: - return 0; + return 0; case ZIP_SOURCE_STAT: { - zip_stat_t *st; + zip_stat_t *st; - st = (zip_stat_t *)data; + st = (zip_stat_t *)data; - if (ctx->crc_complete) { - /* TODO: Set comp_size, comp_method, encryption_method? - After all, this only works for uncompressed data. */ - st->size = ctx->size; - st->crc = ctx->crc; - st->comp_size = ctx->size; - st->comp_method = ZIP_CM_STORE; - st->encryption_method = ZIP_EM_NONE; - st->valid |= ZIP_STAT_SIZE | ZIP_STAT_CRC | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD; - } - return 0; + if (ctx->crc_complete) { + /* TODO: Set comp_size, comp_method, encryption_method? + After all, this only works for uncompressed data. */ + st->size = ctx->size; + st->crc = ctx->crc; + st->comp_size = ctx->size; + st->comp_method = ZIP_CM_STORE; + st->encryption_method = ZIP_EM_NONE; + st->valid |= ZIP_STAT_SIZE | ZIP_STAT_CRC | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD; + } + return 0; } case ZIP_SOURCE_ERROR: - return zip_error_to_data(&ctx->error, data, len); + return zip_error_to_data(&ctx->error, data, len); case ZIP_SOURCE_FREE: - free(ctx); - return 0; + free(ctx); + return 0; case ZIP_SOURCE_SUPPORTS: { - zip_int64_t mask = zip_source_supports(src); + zip_int64_t mask = zip_source_supports(src); - if (mask < 0) { - _zip_error_set_from_source(&ctx->error, src); - return -1; - } + if (mask < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } - return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1); + return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1); } case ZIP_SOURCE_SEEK: { - zip_int64_t new_position; - zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); + zip_int64_t new_position; + zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); - if (args == NULL) { - return -1; - } - if (zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = zip_source_tell(src)) < 0) { - _zip_error_set_from_source(&ctx->error, src); - return -1; - } + if (args == NULL) { + return -1; + } + if (zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = zip_source_tell(src)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } - ctx->position = (zip_uint64_t)new_position; + ctx->position = (zip_uint64_t)new_position; - return 0; + return 0; } case ZIP_SOURCE_TELL: - return (zip_int64_t)ctx->position; + return (zip_int64_t)ctx->position; default: - zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); - return -1; + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; } } diff --git a/zip_source_error.c b/zip_source_error.c index 2257f71..042901f 100644 --- a/zip_source_error.c +++ b/zip_source_error.c @@ -1,6 +1,6 @@ /* zip_source_error.c -- get last error from zip_source - Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at diff --git a/zip_source_file_common.c b/zip_source_file_common.c index 74e2100..0012395 100644 --- a/zip_source_file_common.c +++ b/zip_source_file_common.c @@ -1,6 +1,6 @@ /* zip_source_file_common.c -- create data source from file - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -56,70 +56,70 @@ zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zi zip_source_file_stat_t sb; if (ops == NULL) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } if (ops->close == NULL || ops->read == NULL || ops->seek == NULL || ops->stat == NULL) { - zip_error_set(error, ZIP_ER_INTERNAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; } if (ops->write != NULL && (ops->commit_write == NULL || ops->create_temp_output == NULL || ops->remove == NULL || ops->rollback_write == NULL || ops->tell == NULL)) { - zip_error_set(error, ZIP_ER_INTERNAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; } if (fname != NULL) { - if (ops->open == NULL || ops->string_duplicate == NULL) { - zip_error_set(error, ZIP_ER_INTERNAL, 0); - return NULL; - } + if (ops->open == NULL || ops->string_duplicate == NULL) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; + } } else if (file == NULL) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } if (len < 0) { - len = 0; + len = 0; } if (start > ZIP_INT64_MAX || start + (zip_uint64_t)len < start) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } if ((ctx = (zip_source_file_context_t *)malloc(sizeof(zip_source_file_context_t))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } ctx->ops = ops; ctx->ops_userdata = ops_userdata; ctx->fname = NULL; if (fname) { - if ((ctx->fname = ops->string_duplicate(ctx, fname)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - free(ctx); - return NULL; - } + if ((ctx->fname = ops->string_duplicate(ctx, fname)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(ctx); + return NULL; + } } ctx->f = file; ctx->start = start; ctx->len = (zip_uint64_t)len; if (st) { - memcpy(&ctx->st, st, sizeof(ctx->st)); - ctx->st.name = NULL; - ctx->st.valid &= ~ZIP_STAT_NAME; + memcpy(&ctx->st, st, sizeof(ctx->st)); + ctx->st.name = NULL; + ctx->st.valid &= ~ZIP_STAT_NAME; } else { - zip_stat_init(&ctx->st); + zip_stat_init(&ctx->st); } if (ctx->len > 0) { - ctx->st.size = ctx->len; - ctx->st.valid |= ZIP_STAT_SIZE; + ctx->st.size = ctx->len; + ctx->st.valid |= ZIP_STAT_SIZE; } zip_error_init(&ctx->stat_error); @@ -154,46 +154,46 @@ zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zi } } else { - if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) { - ctx->st.mtime = sb.mtime; - ctx->st.valid |= ZIP_STAT_MTIME; - } - if (sb.regular_file) { - ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE; + if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) { + ctx->st.mtime = sb.mtime; + ctx->st.valid |= ZIP_STAT_MTIME; + } + if (sb.regular_file) { + ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE; - if (ctx->start + ctx->len > sb.size) { - zip_error_set(error, ZIP_ER_INVAL, 0); - free(ctx->fname); - free(ctx); - return NULL; - } + if (ctx->start + ctx->len > sb.size) { + zip_error_set(error, ZIP_ER_INVAL, 0); + free(ctx->fname); + free(ctx); + return NULL; + } - if (ctx->len == 0) { - ctx->len = sb.size - ctx->start; - ctx->st.size = ctx->len; - ctx->st.valid |= ZIP_STAT_SIZE; + if (ctx->len == 0) { + ctx->len = sb.size - ctx->start; + ctx->st.size = ctx->len; + ctx->st.valid |= ZIP_STAT_SIZE; - /* when using a partial file, don't allow writing */ - if (ctx->fname && start == 0 && ops->write != NULL) { - ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; - } - } - } + /* when using a partial file, don't allow writing */ + if (ctx->fname && start == 0 && ops->write != NULL) { + ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; + } + } + } - ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_FILE_ATTRIBUTES); + ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_FILE_ATTRIBUTES); } ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY); if (ops->create_temp_output_cloning != NULL) { - if (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE)) { - ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING); - } + if (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE)) { + ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING); + } } if ((zs = zip_source_function_create(read_file, ctx, error)) == NULL) { - free(ctx->fname); - free(ctx); - return NULL; + free(ctx->fname); + free(ctx); + return NULL; } return zs; @@ -210,169 +210,169 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { switch (cmd) { case ZIP_SOURCE_ACCEPT_EMPTY: - return 0; + return 0; case ZIP_SOURCE_BEGIN_WRITE: - /* write support should not be set if fname is NULL */ - if (ctx->fname == NULL) { - zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); - return -1; - } - return ctx->ops->create_temp_output(ctx); + /* write support should not be set if fname is NULL */ + if (ctx->fname == NULL) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + return -1; + } + return ctx->ops->create_temp_output(ctx); case ZIP_SOURCE_BEGIN_WRITE_CLONING: - /* write support should not be set if fname is NULL */ - if (ctx->fname == NULL) { - zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); - return -1; - } - return ctx->ops->create_temp_output_cloning(ctx, len); + /* write support should not be set if fname is NULL */ + if (ctx->fname == NULL) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + return -1; + } + return ctx->ops->create_temp_output_cloning(ctx, len); case ZIP_SOURCE_CLOSE: - if (ctx->fname) { - ctx->ops->close(ctx); - ctx->f = NULL; - } - return 0; + if (ctx->fname) { + ctx->ops->close(ctx); + ctx->f = NULL; + } + return 0; case ZIP_SOURCE_COMMIT_WRITE: { - zip_int64_t ret = ctx->ops->commit_write(ctx); - ctx->fout = NULL; - if (ret == 0) { - free(ctx->tmpname); - ctx->tmpname = NULL; - } - return ret; + zip_int64_t ret = ctx->ops->commit_write(ctx); + ctx->fout = NULL; + if (ret == 0) { + free(ctx->tmpname); + ctx->tmpname = NULL; + } + return ret; } case ZIP_SOURCE_ERROR: - return zip_error_to_data(&ctx->error, data, len); + return zip_error_to_data(&ctx->error, data, len); case ZIP_SOURCE_FREE: - free(ctx->fname); - free(ctx->tmpname); - if (ctx->f) { - ctx->ops->close(ctx); - } - free(ctx); - return 0; + free(ctx->fname); + free(ctx->tmpname); + if (ctx->f) { + ctx->ops->close(ctx); + } + free(ctx); + return 0; case ZIP_SOURCE_GET_FILE_ATTRIBUTES: - if (len < sizeof(ctx->attributes)) { - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; - } - memcpy(data, &ctx->attributes, sizeof(ctx->attributes)); - return sizeof(ctx->attributes); + if (len < sizeof(ctx->attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + memcpy(data, &ctx->attributes, sizeof(ctx->attributes)); + return sizeof(ctx->attributes); case ZIP_SOURCE_OPEN: - if (ctx->fname) { - if (ctx->ops->open(ctx) == false) { - return -1; - } - } + if (ctx->fname) { + if (ctx->ops->open(ctx) == false) { + return -1; + } + } - if (ctx->start > 0) { // TODO: rewind on re-open - if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)ctx->start, SEEK_SET) == false) { - /* TODO: skip by reading */ - return -1; - } - } - ctx->offset = 0; - return 0; + if (ctx->start > 0) { // TODO: rewind on re-open + if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)ctx->start, SEEK_SET) == false) { + /* TODO: skip by reading */ + return -1; + } + } + ctx->offset = 0; + return 0; case ZIP_SOURCE_READ: { - zip_int64_t i; - zip_uint64_t n; + zip_int64_t i; + zip_uint64_t n; - if (ctx->len > 0) { - n = ZIP_MIN(ctx->len - ctx->offset, len); - } - else { - n = len; - } + if (ctx->len > 0) { + n = ZIP_MIN(ctx->len - ctx->offset, len); + } + else { + n = len; + } - if ((i = ctx->ops->read(ctx, buf, n)) < 0) { - zip_error_set(&ctx->error, ZIP_ER_READ, errno); - return -1; - } - ctx->offset += (zip_uint64_t)i; + if ((i = ctx->ops->read(ctx, buf, n)) < 0) { + zip_error_set(&ctx->error, ZIP_ER_READ, errno); + return -1; + } + ctx->offset += (zip_uint64_t)i; - return i; + return i; } case ZIP_SOURCE_REMOVE: - return ctx->ops->remove(ctx); + return ctx->ops->remove(ctx); case ZIP_SOURCE_ROLLBACK_WRITE: - ctx->ops->rollback_write(ctx); - ctx->fout = NULL; - free(ctx->tmpname); - ctx->tmpname = NULL; - return 0; + ctx->ops->rollback_write(ctx); + ctx->fout = NULL; + free(ctx->tmpname); + ctx->tmpname = NULL; + return 0; case ZIP_SOURCE_SEEK: { - zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset, ctx->len, data, len, &ctx->error); + zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset, ctx->len, data, len, &ctx->error); - if (new_offset < 0) { - return -1; - } + if (new_offset < 0) { + return -1; + } - /* The actual offset inside the file must be representable as zip_int64_t. */ - if (new_offset > ZIP_INT64_MAX - (zip_int64_t)ctx->start) { - zip_error_set(&ctx->error, ZIP_ER_SEEK, EOVERFLOW); - return -1; - } + /* The actual offset inside the file must be representable as zip_int64_t. */ + if (new_offset > ZIP_INT64_MAX - (zip_int64_t)ctx->start) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, EOVERFLOW); + return -1; + } - ctx->offset = (zip_uint64_t)new_offset; + ctx->offset = (zip_uint64_t)new_offset; - if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)(ctx->offset + ctx->start), SEEK_SET) == false) { - return -1; - } - return 0; + if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)(ctx->offset + ctx->start), SEEK_SET) == false) { + return -1; + } + return 0; } case ZIP_SOURCE_SEEK_WRITE: { - zip_source_args_seek_t *args; + zip_source_args_seek_t *args; - args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); - if (args == NULL) { - return -1; - } + args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); + if (args == NULL) { + return -1; + } - if (ctx->ops->seek(ctx, ctx->fout, args->offset, args->whence) == false) { - return -1; - } - return 0; + if (ctx->ops->seek(ctx, ctx->fout, args->offset, args->whence) == false) { + return -1; + } + return 0; } case ZIP_SOURCE_STAT: { - if (len < sizeof(ctx->st)) - return -1; + if (len < sizeof(ctx->st)) + return -1; - if (zip_error_code_zip(&ctx->stat_error) != 0) { - zip_error_set(&ctx->error, zip_error_code_zip(&ctx->stat_error), zip_error_code_system(&ctx->stat_error)); - return -1; - } + if (zip_error_code_zip(&ctx->stat_error) != 0) { + zip_error_set(&ctx->error, zip_error_code_zip(&ctx->stat_error), zip_error_code_system(&ctx->stat_error)); + return -1; + } - memcpy(data, &ctx->st, sizeof(ctx->st)); - return sizeof(ctx->st); + memcpy(data, &ctx->st, sizeof(ctx->st)); + return sizeof(ctx->st); } case ZIP_SOURCE_SUPPORTS: - return ctx->supports; + return ctx->supports; case ZIP_SOURCE_TELL: - return (zip_int64_t)ctx->offset; + return (zip_int64_t)ctx->offset; case ZIP_SOURCE_TELL_WRITE: - return ctx->ops->tell(ctx, ctx->fout); + return ctx->ops->tell(ctx, ctx->fout); case ZIP_SOURCE_WRITE: - return ctx->ops->write(ctx, data, len); + return ctx->ops->write(ctx, data, len); default: - zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); - return -1; + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; } } diff --git a/zip_source_file_stdio.c b/zip_source_file_stdio.c index 4a22f78..1581771 100644 --- a/zip_source_file_stdio.c +++ b/zip_source_file_stdio.c @@ -69,7 +69,7 @@ static zip_source_file_operations_t ops_stdio_read = { ZIP_EXTERN zip_source_t * zip_source_filep(zip_t *za, FILE *file, zip_uint64_t start, zip_int64_t len) { if (za == NULL) { - return NULL; + return NULL; } return zip_source_filep_create(file, start, len, &za->error); @@ -79,8 +79,8 @@ zip_source_filep(zip_t *za, FILE *file, zip_uint64_t start, zip_int64_t len) { ZIP_EXTERN zip_source_t * zip_source_filep_create(FILE *file, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { if (file == NULL || length < -1) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } return zip_source_file_common_new(NULL, file, start, length, NULL, &ops_stdio_read, NULL, error); @@ -97,14 +97,14 @@ zip_int64_t _zip_stdio_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len) { size_t i; if (len > SIZE_MAX) { - len = SIZE_MAX; + len = SIZE_MAX; } if ((i = fread(buf, 1, (size_t)len, ctx->f)) == 0) { - if (ferror((FILE *)ctx->f)) { - zip_error_set(&ctx->error, ZIP_ER_READ, errno); - return -1; - } + if (ferror((FILE *)ctx->f)) { + zip_error_set(&ctx->error, ZIP_ER_READ, errno); + return -1; + } } return (zip_int64_t)i; @@ -115,14 +115,14 @@ bool _zip_stdio_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence) { #if ZIP_FSEEK_MAX > ZIP_INT64_MAX if (offset > ZIP_FSEEK_MAX || offset < ZIP_FSEEK_MIN) { - zip_error_set(&ctx->error, ZIP_ER_SEEK, EOVERFLOW); - return false; + zip_error_set(&ctx->error, ZIP_ER_SEEK, EOVERFLOW); + return false; } #endif if (fseeko((FILE *)f, (off_t)offset, whence) < 0) { - zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); - return false; + zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); + return false; } return true; } @@ -135,10 +135,10 @@ _zip_stdio_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) { int ret; if (ctx->fname) { - ret = stat(ctx->fname, &sb); + ret = stat(ctx->fname, &sb); } else { - ret = fstat(fileno((FILE *)ctx->f), &sb); + ret = fstat(fileno((FILE *)ctx->f), &sb); } if (ret < 0) { @@ -146,8 +146,8 @@ _zip_stdio_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) { st->exists = false; return true; } - zip_error_set(&ctx->error, ZIP_ER_READ, errno); - return false; + zip_error_set(&ctx->error, ZIP_ER_READ, errno); + return false; } st->size = (zip_uint64_t)sb.st_size; @@ -171,7 +171,7 @@ _zip_stdio_op_tell(zip_source_file_context_t *ctx, void *f) { off_t offset = ftello((FILE *)f); if (offset < 0) { - zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); + zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); } return offset; @@ -191,18 +191,18 @@ _zip_fopen_close_on_exec(const char *name, bool writeable) { flags = O_CLOEXEC; if (writeable) { - flags |= O_RDWR; + flags |= O_RDWR; } else { - flags |= O_RDONLY; + flags |= O_RDONLY; } /* mode argument needed on Windows */ if ((fd = open(name, flags, 0666)) < 0) { - return NULL; + return NULL; } if ((fp = fdopen(fd, writeable ? "r+b" : "rb")) == NULL) { - return NULL; + return NULL; } return fp; } diff --git a/zip_source_file_win32.c b/zip_source_file_win32.c index 2fe838f..6547fc2 100644 --- a/zip_source_file_win32.c +++ b/zip_source_file_win32.c @@ -37,6 +37,8 @@ static bool _zip_win32_op_stat(zip_source_file_context_t *ctx, zip_source_file_s static bool _zip_stat_win32(zip_source_file_context_t *ctx, zip_source_file_stat_t *st, HANDLE h); +/* clang-format off */ + static zip_source_file_operations_t ops_win32_read = { _zip_win32_op_close, NULL, @@ -53,13 +55,14 @@ static zip_source_file_operations_t ops_win32_read = { NULL }; +/* clang-format on */ ZIP_EXTERN zip_source_t * zip_source_win32handle(zip_t *za, HANDLE h, zip_uint64_t start, zip_int64_t len) { if (za == NULL) { return NULL; } - + return zip_source_win32handle_create(h, start, len, &za->error); } @@ -90,7 +93,7 @@ _zip_win32_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len) zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError())); return -1; } - + return (zip_int64_t)i; } @@ -135,13 +138,13 @@ zip_int64_t _zip_win32_op_tell(zip_source_file_context_t *ctx, void *f) { LARGE_INTEGER zero; LARGE_INTEGER new_offset; - + zero.QuadPart = 0; if (!SetFilePointerEx((HANDLE)f, zero, &new_offset, FILE_CURRENT)) { zip_error_set(&ctx->error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError())); return -1; } - + return (zip_int64_t)new_offset.QuadPart; } @@ -153,6 +156,7 @@ _zip_win32_error_to_errno(DWORD win32err) { case ERROR_INVALID_PARAMETER: return EINVAL; case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: return ENOENT; case ERROR_INVALID_HANDLE: return EBADF; @@ -184,7 +188,7 @@ _zip_stat_win32(zip_source_file_context_t *ctx, zip_source_file_stat_t *st, HAND zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE); return false; } - + st->exists = true; st->mtime = mtime; @@ -198,7 +202,7 @@ _zip_stat_win32(zip_source_file_context_t *ctx, zip_source_file_stat_t *st, HAND st->size = (zip_uint64_t)size.QuadPart; } - + /* TODO: fill in ctx->attributes */ return true; diff --git a/zip_source_file_win32.h b/zip_source_file_win32.h index 5092e63..88e45b1 100644 --- a/zip_source_file_win32.h +++ b/zip_source_file_win32.h @@ -43,19 +43,21 @@ #include +#include + #include "zipint.h" #include "zip_source_file.h" struct zip_win32_file_operations { char *(*allocate_tempname)(const char *name, size_t extra_chars, size_t *lengthp); - HANDLE (__stdcall *create_file)(const void *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file); - BOOL (__stdcall *delete_file)(const void *name); - DWORD (__stdcall *get_file_attributes)(const void *name); - BOOL (__stdcall *get_file_attributes_ex)(const void *name, GET_FILEEX_INFO_LEVELS info_level, void *information); + HANDLE(__stdcall *create_file)(const void *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file); + BOOL(__stdcall *delete_file)(const void *name); + DWORD(__stdcall *get_file_attributes)(const void *name); + BOOL(__stdcall *get_file_attributes_ex)(const void *name, GET_FILEEX_INFO_LEVELS info_level, void *information); void (*make_tempname)(char *buf, size_t len, const char *name, zip_uint32_t i); - BOOL (__stdcall *move_file)(const void *from, const void *to, DWORD flags); - BOOL (__stdcall *set_file_attributes)(const void *name, DWORD attributes); + BOOL(__stdcall *move_file)(const void *from, const void *to, DWORD flags); + BOOL(__stdcall *set_file_attributes)(const void *name, DWORD attributes); char *(*string_duplicate)(const char *string); }; diff --git a/zip_source_file_win32_ansi.c b/zip_source_file_win32_ansi.c index 573b74e..f299692 100644 --- a/zip_source_file_win32_ansi.c +++ b/zip_source_file_win32_ansi.c @@ -36,6 +36,8 @@ static char *ansi_allocate_tempname(const char *name, size_t extra_chars, size_t *lengthp); static void ansi_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i); +/* clang-format off */ + zip_win32_file_operations_t ops_ansi = { ansi_allocate_tempname, CreateFileA, @@ -48,10 +50,12 @@ zip_win32_file_operations_t ops_ansi = { strdup }; +/* clang-format on */ + ZIP_EXTERN zip_source_t * zip_source_win32a(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len) { if (za == NULL) - return NULL; + return NULL; return zip_source_win32a_create(fname, start, len, &za->error); } @@ -60,8 +64,8 @@ zip_source_win32a(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t ZIP_EXTERN zip_source_t * zip_source_win32a_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { if (fname == NULL || length < -1) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } return zip_source_file_common_new(fname, NULL, start, length, NULL, &_zip_source_file_win32_named_ops, &ops_ansi, error); diff --git a/zip_source_file_win32_named.c b/zip_source_file_win32_named.c index 9591b26..1fe5591 100644 --- a/zip_source_file_win32_named.c +++ b/zip_source_file_win32_named.c @@ -65,13 +65,14 @@ zip_source_file_operations_t _zip_source_file_win32_named_ops = { static zip_int64_t _zip_win32_named_op_commit_write(zip_source_file_context_t *ctx) { zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata; - + DWORD attributes; + if (!CloseHandle((HANDLE)ctx->fout)) { zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError())); return -1; } - - DWORD attributes = file_ops->get_file_attributes(ctx->tmpname); + + attributes = file_ops->get_file_attributes(ctx->tmpname); if (attributes == INVALID_FILE_ATTRIBUTES) { zip_error_set(&ctx->error, ZIP_ER_RENAME, _zip_win32_error_to_errno(GetLastError())); return -1; @@ -108,47 +109,47 @@ _zip_win32_named_op_create_temp_output(zip_source_file_context_t *ctx) { char *tempname = NULL; size_t tempname_size = 0; - if ((HANDLE)ctx->f != INVALID_HANDLE_VALUE && GetFileType((HANDLE)ctx->f) == FILE_TYPE_DISK) { - si = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION; - success = GetSecurityInfo((HANDLE)ctx->f, SE_FILE_OBJECT, si, NULL, NULL, &dacl, NULL, &psd); - if (success == ERROR_SUCCESS) { - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.bInheritHandle = FALSE; - sa.lpSecurityDescriptor = psd; - psa = &sa; - } - } + if ((HANDLE)ctx->f != INVALID_HANDLE_VALUE && GetFileType((HANDLE)ctx->f) == FILE_TYPE_DISK) { + si = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION; + success = GetSecurityInfo((HANDLE)ctx->f, SE_FILE_OBJECT, si, NULL, NULL, &dacl, NULL, &psd); + if (success == ERROR_SUCCESS) { + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = FALSE; + sa.lpSecurityDescriptor = psd; + psa = &sa; + } + } - #ifndef MS_UWP +#ifndef MS_UWP value = GetTickCount(); #else value = (zip_uint32_t)(GetTickCount64() & 0xffffffff); #endif - + if ((tempname = file_ops->allocate_tempname(ctx->fname, 10, &tempname_size)) == NULL) { zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); return -1; } - + for (i = 0; i < 1024 && th == INVALID_HANDLE_VALUE; i++) { file_ops->make_tempname(tempname, tempname_size, ctx->fname, value + i); - + th = win32_named_open(ctx, tempname, true, psa); if (th == INVALID_HANDLE_VALUE && GetLastError() != ERROR_FILE_EXISTS) break; } - + if (th == INVALID_HANDLE_VALUE) { free(tempname); LocalFree(psd); zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, _zip_win32_error_to_errno(GetLastError())); return -1; } - + LocalFree(psd); ctx->fout = th; ctx->tmpname = tempname; - + return 0; } @@ -156,11 +157,11 @@ _zip_win32_named_op_create_temp_output(zip_source_file_context_t *ctx) { static bool _zip_win32_named_op_open(zip_source_file_context_t *ctx) { HANDLE h = win32_named_open(ctx, ctx->fname, false, NULL); - + if (h == INVALID_HANDLE_VALUE) { return false; } - + ctx->f = h; return true; } @@ -193,7 +194,7 @@ _zip_win32_named_op_rollback_write(zip_source_file_context_t *ctx) { static bool _zip_win32_named_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) { zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata; - + WIN32_FILE_ATTRIBUTE_DATA file_attributes; if (!file_ops->get_file_attributes_ex(ctx->fname, GetFileExInfoStandard, &file_attributes)) { @@ -205,9 +206,16 @@ _zip_win32_named_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(error)); return false; } - + st->exists = true; - st->regular_file = true; /* TODO: Is this always right? How to determine without a HANDLE? */ + st->regular_file = false; + + if (file_attributes.dwFileAttributes != INVALID_FILE_ATTRIBUTES) { + if ((file_attributes.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)) == 0) { + st->regular_file = true; + } + } + if (!_zip_filetime_to_time_t(file_attributes.ftLastWriteTime, &st->mtime)) { zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE); return false; @@ -235,7 +243,7 @@ _zip_win32_named_op_write(zip_source_file_context_t *ctx, const void *data, zip_ zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError())); return -1; } - + return (zip_int64_t)ret; } @@ -248,7 +256,8 @@ win32_named_open(zip_source_file_context_t *ctx, const char *name, bool temporar DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE; DWORD creation_disposition = OPEN_EXISTING; DWORD file_attributes = FILE_ATTRIBUTE_NORMAL; - + HANDLE h; + if (temporary) { access = GENERIC_READ | GENERIC_WRITE; share_mode = FILE_SHARE_READ; @@ -256,8 +265,8 @@ win32_named_open(zip_source_file_context_t *ctx, const char *name, bool temporar file_attributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY; } - HANDLE h = file_ops->create_file(name, access, share_mode, security_attributes, creation_disposition, file_attributes, NULL); - + h = file_ops->create_file(name, access, share_mode, security_attributes, creation_disposition, file_attributes, NULL); + if (h == INVALID_HANDLE_VALUE) { zip_error_set(&ctx->error, ZIP_ER_OPEN, _zip_win32_error_to_errno(GetLastError())); } diff --git a/zip_source_file_win32_utf16.c b/zip_source_file_win32_utf16.c index 3fa0aa1..6aef2bb 100644 --- a/zip_source_file_win32_utf16.c +++ b/zip_source_file_win32_utf16.c @@ -38,6 +38,8 @@ static HANDLE __stdcall utf16_create_file(const char *name, DWORD access, DWORD static void utf16_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i); static char *utf16_strdup(const char *string); +/* clang-format off */ + zip_win32_file_operations_t ops_utf16 = { utf16_allocate_tempname, utf16_create_file, @@ -50,10 +52,12 @@ zip_win32_file_operations_t ops_utf16 = { utf16_strdup }; +/* clang-format on */ + ZIP_EXTERN zip_source_t * zip_source_win32w(zip_t *za, const wchar_t *fname, zip_uint64_t start, zip_int64_t len) { if (za == NULL) - return NULL; + return NULL; return zip_source_win32w_create(fname, start, len, &za->error); } @@ -62,8 +66,8 @@ zip_source_win32w(zip_t *za, const wchar_t *fname, zip_uint64_t start, zip_int64 ZIP_EXTERN zip_source_t * zip_source_win32w_create(const wchar_t *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { if (fname == NULL || length < -1) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } @@ -78,8 +82,7 @@ utf16_allocate_tempname(const char *name, size_t extra_chars, size_t *lengthp) { } -static HANDLE __stdcall -utf16_create_file(const char *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file) { +static HANDLE __stdcall utf16_create_file(const char *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file) { #ifdef MS_UWP CREATEFILE2_EXTENDED_PARAMETERS extParams = {0}; extParams.dwFileAttributes = file_attributes; @@ -88,7 +91,7 @@ utf16_create_file(const char *name, DWORD access, DWORD share_mode, PSECURITY_AT extParams.dwSize = sizeof(extParams); extParams.hTemplateFile = template_file; extParams.lpSecurityAttributes = security_attributes; - + return CreateFile2((const wchar_t *)name, access, share_mode, creation_disposition, &extParams); #else return CreateFileW((const wchar_t *)name, access, share_mode, security_attributes, creation_disposition, file_attributes, template_file); diff --git a/zip_source_file_win32_utf8.c b/zip_source_file_win32_utf8.c index 4f258bc..d6728e3 100644 --- a/zip_source_file_win32_utf8.c +++ b/zip_source_file_win32_utf8.c @@ -38,7 +38,7 @@ zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t le if (za == NULL) { return NULL; } - + return zip_source_file_create(fname, start, len, &za->error); } @@ -67,7 +67,7 @@ zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fname, -1, wfname, size); source = zip_source_win32w_create(wfname, start, length, error); - + free(wfname); return source; } diff --git a/zip_source_free.c b/zip_source_free.c index 2f10ef8..2e6944e 100644 --- a/zip_source_free.c +++ b/zip_source_free.c @@ -1,6 +1,6 @@ /* zip_source_free.c -- free zip data source - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,31 +40,31 @@ ZIP_EXTERN void zip_source_free(zip_source_t *src) { if (src == NULL) - return; + return; if (src->refcount > 0) { - src->refcount--; + src->refcount--; } if (src->refcount > 0) { - return; + return; } if (ZIP_SOURCE_IS_OPEN_READING(src)) { - src->open_count = 1; /* force close */ - zip_source_close(src); + src->open_count = 1; /* force close */ + zip_source_close(src); } if (ZIP_SOURCE_IS_OPEN_WRITING(src)) { - zip_source_rollback_write(src); + zip_source_rollback_write(src); } if (src->source_archive && !src->source_closed) { - _zip_deregister_source(src->source_archive, src); + _zip_deregister_source(src->source_archive, src); } (void)_zip_source_call(src, NULL, 0, ZIP_SOURCE_FREE); if (src->src) { - zip_source_free(src->src); + zip_source_free(src->src); } free(src); diff --git a/zip_source_function.c b/zip_source_function.c index d5c1b5b..44db947 100644 --- a/zip_source_function.c +++ b/zip_source_function.c @@ -1,6 +1,6 @@ /* zip_source_function.c -- create zip data source from callback function - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,7 +40,7 @@ ZIP_EXTERN zip_source_t * zip_source_function(zip_t *za, zip_source_callback zcb, void *ud) { if (za == NULL) { - return NULL; + return NULL; } return zip_source_function_create(zcb, ud, &za->error); @@ -52,14 +52,14 @@ zip_source_function_create(zip_source_callback zcb, void *ud, zip_error_t *error zip_source_t *zs; if ((zs = _zip_source_new(error)) == NULL) - return NULL; + return NULL; zs->cb.f = zcb; zs->ud = ud; zs->supports = zcb(ud, NULL, 0, ZIP_SOURCE_SUPPORTS); if (zs->supports < 0) { - zs->supports = ZIP_SOURCE_SUPPORTS_READABLE; + zs->supports = ZIP_SOURCE_SUPPORTS_READABLE; } return zs; @@ -77,8 +77,8 @@ _zip_source_new(zip_error_t *error) { zip_source_t *src; if ((src = (zip_source_t *)malloc(sizeof(*src))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } src->src = NULL; @@ -92,6 +92,7 @@ _zip_source_new(zip_error_t *error) { zip_error_init(&src->error); src->eof = false; src->had_read_error = false; + src->bytes_read = 0; return src; } diff --git a/zip_source_get_file_attributes.c b/zip_source_get_file_attributes.c index acbede1..734767a 100644 --- a/zip_source_get_file_attributes.c +++ b/zip_source_get_file_attributes.c @@ -42,62 +42,64 @@ zip_file_attributes_init(zip_file_attributes_t *attributes) { int zip_source_get_file_attributes(zip_source_t *src, zip_file_attributes_t *attributes) { if (src->source_closed) { - return -1; + return -1; } if (attributes == NULL) { - zip_error_set(&src->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; } zip_file_attributes_init(attributes); if (src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_FILE_ATTRIBUTES)) { - if (_zip_source_call(src, attributes, sizeof(*attributes), ZIP_SOURCE_GET_FILE_ATTRIBUTES) < 0) { - return -1; - } + if (_zip_source_call(src, attributes, sizeof(*attributes), ZIP_SOURCE_GET_FILE_ATTRIBUTES) < 0) { + return -1; + } } if (ZIP_SOURCE_IS_LAYERED(src)) { - zip_file_attributes_t lower_attributes; + zip_file_attributes_t lower_attributes; - if (zip_source_get_file_attributes(src->src, &lower_attributes) < 0) { - _zip_error_set_from_source(&src->error, src->src); - return -1; - } + if (zip_source_get_file_attributes(src->src, &lower_attributes) < 0) { + _zip_error_set_from_source(&src->error, src->src); + return -1; + } - if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM) && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM) == 0) { - attributes->host_system = lower_attributes.host_system; - attributes->valid |= ZIP_FILE_ATTRIBUTES_HOST_SYSTEM; - } - if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_ASCII) && (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) == 0) { - attributes->ascii = lower_attributes.ascii; - attributes->valid |= ZIP_FILE_ATTRIBUTES_ASCII; - } - if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED)) { - if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) { - attributes->version_needed = ZIP_MAX(lower_attributes.version_needed, attributes->version_needed); - } - else { - attributes->version_needed = lower_attributes.version_needed; - attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED; - } - } - if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES) && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES) == 0) { - attributes->external_file_attributes = lower_attributes.external_file_attributes; - attributes->valid |= ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES; - } - if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS)) { - if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) { - attributes->general_purpose_bit_flags &= ~lower_attributes.general_purpose_bit_mask; - attributes->general_purpose_bit_flags |= lower_attributes.general_purpose_bit_flags & lower_attributes.general_purpose_bit_mask; - attributes->general_purpose_bit_mask |= lower_attributes.general_purpose_bit_mask; - } - else { - attributes->valid |= ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS; - attributes->general_purpose_bit_flags = lower_attributes.general_purpose_bit_flags; - attributes->general_purpose_bit_mask = lower_attributes.general_purpose_bit_mask; - } - } + if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM) && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM) == 0) { + attributes->host_system = lower_attributes.host_system; + attributes->valid |= ZIP_FILE_ATTRIBUTES_HOST_SYSTEM; + } + if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_ASCII) && (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) == 0) { + attributes->ascii = lower_attributes.ascii; + attributes->valid |= ZIP_FILE_ATTRIBUTES_ASCII; + } + if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED)) { + if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) { + attributes->version_needed = ZIP_MAX(lower_attributes.version_needed, attributes->version_needed); + } + else { + attributes->version_needed = lower_attributes.version_needed; + attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED; + } + } + if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES) && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES) == 0) { + attributes->external_file_attributes = lower_attributes.external_file_attributes; + attributes->valid |= ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES; + } + if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS)) { + if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) { + /* only take from lower level what is not defined at current level */ + lower_attributes.general_purpose_bit_mask &= ~attributes->general_purpose_bit_mask; + + attributes->general_purpose_bit_flags |= lower_attributes.general_purpose_bit_flags & lower_attributes.general_purpose_bit_mask; + attributes->general_purpose_bit_mask |= lower_attributes.general_purpose_bit_mask; + } + else { + attributes->valid |= ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS; + attributes->general_purpose_bit_flags = lower_attributes.general_purpose_bit_flags; + attributes->general_purpose_bit_mask = lower_attributes.general_purpose_bit_mask; + } + } } return 0; diff --git a/zip_source_is_deleted.c b/zip_source_is_deleted.c index edd10ca..c2c7eb5 100644 --- a/zip_source_is_deleted.c +++ b/zip_source_is_deleted.c @@ -1,6 +1,6 @@ /* zip_source_is_deleted.c -- was archive was removed? - Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at diff --git a/zip_source_layered.c b/zip_source_layered.c index d02bc85..f6db2a7 100644 --- a/zip_source_layered.c +++ b/zip_source_layered.c @@ -1,6 +1,6 @@ /* zip_source_layered.c -- create layered source - Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,7 +40,7 @@ zip_source_t * zip_source_layered(zip_t *za, zip_source_t *src, zip_source_layered_callback cb, void *ud) { if (za == NULL) - return NULL; + return NULL; return zip_source_layered_create(src, cb, ud, &za->error); } @@ -51,7 +51,7 @@ zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, voi zip_source_t *zs; if ((zs = _zip_source_new(error)) == NULL) - return NULL; + return NULL; zip_source_keep(src); zs->src = src; @@ -60,7 +60,7 @@ zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, voi zs->supports = cb(src, ud, NULL, 0, ZIP_SOURCE_SUPPORTS); if (zs->supports < 0) { - zs->supports = ZIP_SOURCE_SUPPORTS_READABLE; + zs->supports = ZIP_SOURCE_SUPPORTS_READABLE; } return zs; diff --git a/zip_source_open.c b/zip_source_open.c index 414c677..b12a4c2 100644 --- a/zip_source_open.c +++ b/zip_source_open.c @@ -1,6 +1,6 @@ /* zip_source_open.c -- open zip_source (prepare for reading) - Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -37,38 +37,39 @@ ZIP_EXTERN int zip_source_open(zip_source_t *src) { if (src->source_closed) { - return -1; + return -1; } if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) { - zip_error_set(&src->error, ZIP_ER_DELETED, 0); - return -1; + zip_error_set(&src->error, ZIP_ER_DELETED, 0); + return -1; } if (ZIP_SOURCE_IS_OPEN_READING(src)) { - if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) == 0) { - zip_error_set(&src->error, ZIP_ER_INUSE, 0); - return -1; - } + if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) == 0) { + zip_error_set(&src->error, ZIP_ER_INUSE, 0); + return -1; + } } else { - if (ZIP_SOURCE_IS_LAYERED(src)) { - if (zip_source_open(src->src) < 0) { - _zip_error_set_from_source(&src->error, src->src); - return -1; - } - } + if (ZIP_SOURCE_IS_LAYERED(src)) { + if (zip_source_open(src->src) < 0) { + _zip_error_set_from_source(&src->error, src->src); + return -1; + } + } - if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_OPEN) < 0) { - if (ZIP_SOURCE_IS_LAYERED(src)) { - zip_source_close(src->src); - } - return -1; - } + if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_OPEN) < 0) { + if (ZIP_SOURCE_IS_LAYERED(src)) { + zip_source_close(src->src); + } + return -1; + } } src->eof = false; src->had_read_error = false; _zip_error_clear(&src->error); + src->bytes_read = 0; src->open_count++; return 0; diff --git a/zip_source_pkware_decode.c b/zip_source_pkware_decode.c index d5489a5..a1c9e3a 100644 --- a/zip_source_pkware_decode.c +++ b/zip_source_pkware_decode.c @@ -56,21 +56,21 @@ zip_source_pkware_decode(zip_t *za, zip_source_t *src, zip_uint16_t em, int flag zip_source_t *s2; if (password == NULL || src == NULL || em != ZIP_EM_TRAD_PKWARE) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; } if (flags & ZIP_CODEC_ENCODE) { - zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); - return NULL; + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + return NULL; } if ((ctx = trad_pkware_new(password, &za->error)) == NULL) { - return NULL; + return NULL; } if ((s2 = zip_source_layered(za, src, pkware_decrypt, ctx)) == NULL) { - trad_pkware_free(ctx); - return NULL; + trad_pkware_free(ctx); + return NULL; } return s2; @@ -82,22 +82,23 @@ decrypt_header(zip_source_t *src, struct trad_pkware *ctx) { zip_uint8_t header[ZIP_CRYPTO_PKWARE_HEADERLEN]; struct zip_stat st; zip_int64_t n; + bool ok = false; if ((n = zip_source_read(src, header, ZIP_CRYPTO_PKWARE_HEADERLEN)) < 0) { - _zip_error_set_from_source(&ctx->error, src); - return -1; + _zip_error_set_from_source(&ctx->error, src); + return -1; } if (n != ZIP_CRYPTO_PKWARE_HEADERLEN) { - zip_error_set(&ctx->error, ZIP_ER_EOF, 0); - return -1; + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); + return -1; } _zip_pkware_decrypt(&ctx->keys, header, header, ZIP_CRYPTO_PKWARE_HEADERLEN); if (zip_source_stat(src, &st)) { - /* stat failed, skip password validation */ - return 0; + /* stat failed, skip password validation */ + return 0; } /* password verification - two ways: @@ -105,25 +106,23 @@ decrypt_header(zip_source_t *src, struct trad_pkware *ctx) { * CRC - old PKWare way */ - bool ok = false; - if (st.valid & ZIP_STAT_MTIME) { - unsigned short dostime, dosdate; - _zip_u2d_time(st.mtime, &dostime, &dosdate); - if (header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] == dostime >> 8) { - ok = true; - } + unsigned short dostime, dosdate; + _zip_u2d_time(st.mtime, &dostime, &dosdate); + if (header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] == dostime >> 8) { + ok = true; + } } if (st.valid & ZIP_STAT_CRC) { - if (header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] == st.crc >> 24) { - ok = true; - } + if (header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] == st.crc >> 24) { + ok = true; + } } if (!ok && ((st.valid & (ZIP_STAT_MTIME | ZIP_STAT_CRC)) != 0)) { - zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0); - return -1; + zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0); + return -1; } return 0; @@ -139,52 +138,52 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_so switch (cmd) { case ZIP_SOURCE_OPEN: - _zip_pkware_keys_reset(&ctx->keys); - _zip_pkware_decrypt(&ctx->keys, NULL, (const zip_uint8_t *)ctx->password, strlen(ctx->password)); - if (decrypt_header(src, ctx) < 0) { - return -1; - } - return 0; + _zip_pkware_keys_reset(&ctx->keys); + _zip_pkware_decrypt(&ctx->keys, NULL, (const zip_uint8_t *)ctx->password, strlen(ctx->password)); + if (decrypt_header(src, ctx) < 0) { + return -1; + } + return 0; case ZIP_SOURCE_READ: - if ((n = zip_source_read(src, data, len)) < 0) { - _zip_error_set_from_source(&ctx->error, src); - return -1; - } + if ((n = zip_source_read(src, data, len)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } - _zip_pkware_decrypt(&ctx->keys, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n); - return n; + _zip_pkware_decrypt(&ctx->keys, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n); + return n; case ZIP_SOURCE_CLOSE: - return 0; + return 0; case ZIP_SOURCE_STAT: { - zip_stat_t *st; + zip_stat_t *st; - st = (zip_stat_t *)data; + st = (zip_stat_t *)data; - st->encryption_method = ZIP_EM_NONE; - st->valid |= ZIP_STAT_ENCRYPTION_METHOD; - if (st->valid & ZIP_STAT_COMP_SIZE) { - st->comp_size -= ZIP_CRYPTO_PKWARE_HEADERLEN; - } + st->encryption_method = ZIP_EM_NONE; + st->valid |= ZIP_STAT_ENCRYPTION_METHOD; + if (st->valid & ZIP_STAT_COMP_SIZE) { + st->comp_size -= ZIP_CRYPTO_PKWARE_HEADERLEN; + } - return 0; + return 0; } case ZIP_SOURCE_SUPPORTS: - return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1); + return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1); case ZIP_SOURCE_ERROR: - return zip_error_to_data(&ctx->error, data, len); + return zip_error_to_data(&ctx->error, data, len); case ZIP_SOURCE_FREE: - trad_pkware_free(ctx); - return 0; + trad_pkware_free(ctx); + return 0; default: - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; } } @@ -194,14 +193,14 @@ trad_pkware_new(const char *password, zip_error_t *error) { struct trad_pkware *ctx; if ((ctx = (struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } if ((ctx->password = strdup(password)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - free(ctx); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(ctx); + return NULL; } zip_error_init(&ctx->error); @@ -213,7 +212,7 @@ trad_pkware_new(const char *password, zip_error_t *error) { static void trad_pkware_free(struct trad_pkware *ctx) { if (ctx == NULL) { - return; + return; } free(ctx->password); diff --git a/zip_source_pkware_encode.c b/zip_source_pkware_encode.c index 1e8f42c..7c77e1e 100644 --- a/zip_source_pkware_encode.c +++ b/zip_source_pkware_encode.c @@ -58,21 +58,21 @@ zip_source_pkware_encode(zip_t *za, zip_source_t *src, zip_uint16_t em, int flag zip_source_t *s2; if (password == NULL || src == NULL || em != ZIP_EM_TRAD_PKWARE) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; } if (!(flags & ZIP_CODEC_ENCODE)) { - zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); - return NULL; + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + return NULL; } if ((ctx = trad_pkware_new(password, &za->error)) == NULL) { - return NULL; + return NULL; } if ((s2 = zip_source_layered(za, src, pkware_encrypt, ctx)) == NULL) { - trad_pkware_free(ctx); - return NULL; + trad_pkware_free(ctx); + return NULL; } return s2; @@ -86,15 +86,15 @@ encrypt_header(zip_source_t *src, struct trad_pkware *ctx) { zip_uint8_t *header; if (zip_source_stat(src, &st) != 0) { - _zip_error_set_from_source(&ctx->error, src); - return -1; + _zip_error_set_from_source(&ctx->error, src); + return -1; } _zip_u2d_time(st.mtime, &dostime, &dosdate); if ((ctx->buffer = _zip_buffer_new(NULL, ZIP_CRYPTO_PKWARE_HEADERLEN)) == NULL) { - zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); - return -1; + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; } header = _zip_buffer_data(ctx->buffer); @@ -102,10 +102,10 @@ encrypt_header(zip_source_t *src, struct trad_pkware *ctx) { /* generate header from random bytes and mtime see appnote.iz, XIII. Decryption, Step 2, last paragraph */ if (!zip_secure_random(header, ZIP_CRYPTO_PKWARE_HEADERLEN - 1)) { - zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); - _zip_buffer_free(ctx->buffer); - ctx->buffer = NULL; - return -1; + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(ctx->buffer); + ctx->buffer = NULL; + return -1; } header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] = (zip_uint8_t)((dostime >> 8) & 0xff); @@ -125,92 +125,92 @@ pkware_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length, zip switch (cmd) { case ZIP_SOURCE_OPEN: - ctx->eof = false; + ctx->eof = false; - /* initialize keys */ - _zip_pkware_keys_reset(&ctx->keys); - _zip_pkware_encrypt(&ctx->keys, NULL, (const zip_uint8_t *)ctx->password, strlen(ctx->password)); + /* initialize keys */ + _zip_pkware_keys_reset(&ctx->keys); + _zip_pkware_encrypt(&ctx->keys, NULL, (const zip_uint8_t *)ctx->password, strlen(ctx->password)); - if (encrypt_header(src, ctx) < 0) { - return -1; - } - return 0; + if (encrypt_header(src, ctx) < 0) { + return -1; + } + return 0; case ZIP_SOURCE_READ: - buffer_n = 0; + buffer_n = 0; - if (ctx->buffer) { - /* write header values to data */ - buffer_n = _zip_buffer_read(ctx->buffer, data, length); - data = (zip_uint8_t *)data + buffer_n; - length -= buffer_n; + if (ctx->buffer) { + /* write header values to data */ + buffer_n = _zip_buffer_read(ctx->buffer, data, length); + data = (zip_uint8_t *)data + buffer_n; + length -= buffer_n; - if (_zip_buffer_eof(ctx->buffer)) { - _zip_buffer_free(ctx->buffer); - ctx->buffer = NULL; - } - } + if (_zip_buffer_eof(ctx->buffer)) { + _zip_buffer_free(ctx->buffer); + ctx->buffer = NULL; + } + } - if (ctx->eof) { - return (zip_int64_t)buffer_n; - } + if (ctx->eof) { + return (zip_int64_t)buffer_n; + } - if ((n = zip_source_read(src, data, length)) < 0) { - _zip_error_set_from_source(&ctx->error, src); - return -1; - } + if ((n = zip_source_read(src, data, length)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } - _zip_pkware_encrypt(&ctx->keys, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n); + _zip_pkware_encrypt(&ctx->keys, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n); - if ((zip_uint64_t)n < length) { - ctx->eof = true; - } + if ((zip_uint64_t)n < length) { + ctx->eof = true; + } - return (zip_int64_t)buffer_n + n; + return (zip_int64_t)buffer_n + n; case ZIP_SOURCE_CLOSE: - _zip_buffer_free(ctx->buffer); - ctx->buffer = NULL; - return 0; + _zip_buffer_free(ctx->buffer); + ctx->buffer = NULL; + return 0; case ZIP_SOURCE_STAT: { - zip_stat_t *st; + zip_stat_t *st; - st = (zip_stat_t *)data; - st->encryption_method = ZIP_EM_TRAD_PKWARE; - st->valid |= ZIP_STAT_ENCRYPTION_METHOD; - if (st->valid & ZIP_STAT_COMP_SIZE) { - st->comp_size += ZIP_CRYPTO_PKWARE_HEADERLEN; - } + st = (zip_stat_t *)data; + st->encryption_method = ZIP_EM_TRAD_PKWARE; + st->valid |= ZIP_STAT_ENCRYPTION_METHOD; + if (st->valid & ZIP_STAT_COMP_SIZE) { + st->comp_size += ZIP_CRYPTO_PKWARE_HEADERLEN; + } - return 0; + return 0; } case ZIP_SOURCE_GET_FILE_ATTRIBUTES: { - zip_file_attributes_t *attributes = (zip_file_attributes_t *)data; - if (length < sizeof(*attributes)) { - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; - } - attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED; - attributes->version_needed = 20; + zip_file_attributes_t *attributes = (zip_file_attributes_t *)data; + if (length < sizeof(*attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED; + attributes->version_needed = 20; - return 0; + return 0; } case ZIP_SOURCE_SUPPORTS: - return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1); + return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1); case ZIP_SOURCE_ERROR: - return zip_error_to_data(&ctx->error, data, length); + return zip_error_to_data(&ctx->error, data, length); case ZIP_SOURCE_FREE: - trad_pkware_free(ctx); - return 0; + trad_pkware_free(ctx); + return 0; default: - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; } } @@ -220,14 +220,14 @@ trad_pkware_new(const char *password, zip_error_t *error) { struct trad_pkware *ctx; if ((ctx = (struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } if ((ctx->password = strdup(password)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - free(ctx); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(ctx); + return NULL; } ctx->buffer = NULL; zip_error_init(&ctx->error); @@ -239,7 +239,7 @@ trad_pkware_new(const char *password, zip_error_t *error) { static void trad_pkware_free(struct trad_pkware *ctx) { if (ctx == NULL) { - return; + return; } free(ctx->password); diff --git a/zip_source_read.c b/zip_source_read.c index 33088cb..ee7686a 100644 --- a/zip_source_read.c +++ b/zip_source_read.c @@ -1,6 +1,6 @@ /* zip_source_read.c -- read data from zip_source - Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -41,45 +41,51 @@ zip_source_read(zip_source_t *src, void *data, zip_uint64_t len) { zip_int64_t n; if (src->source_closed) { - return -1; + return -1; } if (!ZIP_SOURCE_IS_OPEN_READING(src) || len > ZIP_INT64_MAX || (len > 0 && data == NULL)) { - zip_error_set(&src->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; } if (src->had_read_error) { - return -1; + return -1; } if (_zip_source_eof(src)) { - return 0; + return 0; } if (len == 0) { - return 0; + return 0; } bytes_read = 0; while (bytes_read < len) { - if ((n = _zip_source_call(src, (zip_uint8_t *)data + bytes_read, len - bytes_read, ZIP_SOURCE_READ)) < 0) { - src->had_read_error = true; - if (bytes_read == 0) { - return -1; - } - else { - return (zip_int64_t)bytes_read; - } - } + if ((n = _zip_source_call(src, (zip_uint8_t *)data + bytes_read, len - bytes_read, ZIP_SOURCE_READ)) < 0) { + src->had_read_error = true; + if (bytes_read == 0) { + return -1; + } + else { + return (zip_int64_t)bytes_read; + } + } - if (n == 0) { - src->eof = 1; - break; - } + if (n == 0) { + src->eof = 1; + break; + } - bytes_read += (zip_uint64_t)n; + bytes_read += (zip_uint64_t)n; } + if (src->bytes_read + bytes_read < src->bytes_read) { + src->bytes_read = ZIP_UINT64_MAX; + } + else { + src->bytes_read += bytes_read; + } return (zip_int64_t)bytes_read; } diff --git a/zip_source_remove.c b/zip_source_remove.c index 14eddb8..46230cd 100644 --- a/zip_source_remove.c +++ b/zip_source_remove.c @@ -1,6 +1,6 @@ /* zip_source_remove.c -- remove empty archive - Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -38,20 +38,20 @@ int zip_source_remove(zip_source_t *src) { if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) { - return 0; + return 0; } if (ZIP_SOURCE_IS_OPEN_READING(src)) { - if (zip_source_close(src) < 0) { - return -1; - } + if (zip_source_close(src) < 0) { + return -1; + } } if (src->write_state != ZIP_SOURCE_WRITE_CLOSED) { - zip_source_rollback_write(src); + zip_source_rollback_write(src); } if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_REMOVE) < 0) { - return -1; + return -1; } src->write_state = ZIP_SOURCE_WRITE_REMOVED; diff --git a/zip_source_rollback_write.c b/zip_source_rollback_write.c index e8259bf..6f98c39 100644 --- a/zip_source_rollback_write.c +++ b/zip_source_rollback_write.c @@ -1,6 +1,6 @@ /* zip_source_rollback_write.c -- discard changes - Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -38,7 +38,7 @@ ZIP_EXTERN void zip_source_rollback_write(zip_source_t *src) { if (src->write_state != ZIP_SOURCE_WRITE_OPEN && src->write_state != ZIP_SOURCE_WRITE_FAILED) { - return; + return; } _zip_source_call(src, NULL, 0, ZIP_SOURCE_ROLLBACK_WRITE); diff --git a/zip_source_seek.c b/zip_source_seek.c index 163daf1..1acd6d8 100644 --- a/zip_source_seek.c +++ b/zip_source_seek.c @@ -1,6 +1,6 @@ /* zip_source_seek.c -- seek to offset - Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,18 +40,18 @@ zip_source_seek(zip_source_t *src, zip_int64_t offset, int whence) { zip_source_args_seek_t args; if (src->source_closed) { - return -1; + return -1; } if (!ZIP_SOURCE_IS_OPEN_READING(src) || (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END)) { - zip_error_set(&src->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; } args.offset = offset; args.whence = whence; if (_zip_source_call(src, &args, sizeof(args), ZIP_SOURCE_SEEK) < 0) { - return -1; + return -1; } src->eof = 0; @@ -65,30 +65,30 @@ zip_source_seek_compute_offset(zip_uint64_t offset, zip_uint64_t length, void *d zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, data_length, error); if (args == NULL) { - return -1; + return -1; } switch (args->whence) { case SEEK_CUR: - new_offset = (zip_int64_t)offset + args->offset; - break; + new_offset = (zip_int64_t)offset + args->offset; + break; case SEEK_END: - new_offset = (zip_int64_t)length + args->offset; - break; + new_offset = (zip_int64_t)length + args->offset; + break; case SEEK_SET: - new_offset = args->offset; - break; + new_offset = args->offset; + break; default: - zip_error_set(error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; } if (new_offset < 0 || (zip_uint64_t)new_offset > length) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; } return new_offset; diff --git a/zip_source_seek_write.c b/zip_source_seek_write.c index 6b0aa78..5599bcb 100644 --- a/zip_source_seek_write.c +++ b/zip_source_seek_write.c @@ -1,6 +1,6 @@ /* zip_source_seek_write.c -- seek to offset for writing - Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,8 +40,8 @@ zip_source_seek_write(zip_source_t *src, zip_int64_t offset, int whence) { zip_source_args_seek_t args; if (!ZIP_SOURCE_IS_OPEN_WRITING(src) || (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END)) { - zip_error_set(&src->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; } args.offset = offset; diff --git a/zip_source_stat.c b/zip_source_stat.c index 3421d2c..a9745e0 100644 --- a/zip_source_stat.c +++ b/zip_source_stat.c @@ -1,6 +1,6 @@ /* zip_source_stat.c -- get meta information from zip_source - Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -38,24 +38,24 @@ ZIP_EXTERN int zip_source_stat(zip_source_t *src, zip_stat_t *st) { if (src->source_closed) { - return -1; + return -1; } if (st == NULL) { - zip_error_set(&src->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; } zip_stat_init(st); if (ZIP_SOURCE_IS_LAYERED(src)) { - if (zip_source_stat(src->src, st) < 0) { - _zip_error_set_from_source(&src->error, src->src); - return -1; - } + if (zip_source_stat(src->src, st) < 0) { + _zip_error_set_from_source(&src->error, src->src); + return -1; + } } if (_zip_source_call(src, st, sizeof(*st), ZIP_SOURCE_STAT) < 0) { - return -1; + return -1; } return 0; diff --git a/zip_source_supports.c b/zip_source_supports.c index 8471559..66a5303 100644 --- a/zip_source_supports.c +++ b/zip_source_supports.c @@ -1,6 +1,6 @@ /* zip_source_supports.c -- check for supported functions - Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -53,11 +53,11 @@ zip_source_make_command_bitmap(zip_source_cmd_t cmd0, ...) { va_start(ap, cmd0); for (;;) { - int cmd = va_arg(ap, int); - if (cmd < 0) { - break; - } - bitmap |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd); + int cmd = va_arg(ap, int); + if (cmd < 0) { + break; + } + bitmap |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd); } va_end(ap); diff --git a/zip_source_tell.c b/zip_source_tell.c index 772e252..8518739 100644 --- a/zip_source_tell.c +++ b/zip_source_tell.c @@ -1,6 +1,6 @@ /* zip_source_tell.c -- report current offset - Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -38,11 +38,19 @@ ZIP_EXTERN zip_int64_t zip_source_tell(zip_source_t *src) { if (src->source_closed) { - return -1; + return -1; } if (!ZIP_SOURCE_IS_OPEN_READING(src)) { - zip_error_set(&src->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((src->supports & (ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL) | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK))) == 0) { + if (src->bytes_read > ZIP_INT64_MAX) { + zip_error_set(&src->error, ZIP_ER_TELL, EOVERFLOW); + return -1; + } + return (zip_int64_t)src->bytes_read; } return _zip_source_call(src, NULL, 0, ZIP_SOURCE_TELL); diff --git a/zip_source_tell_write.c b/zip_source_tell_write.c index 96ad7e2..8edee67 100644 --- a/zip_source_tell_write.c +++ b/zip_source_tell_write.c @@ -1,6 +1,6 @@ /* zip_source_tell_write.c -- report current offset for writing - Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -38,8 +38,8 @@ ZIP_EXTERN zip_int64_t zip_source_tell_write(zip_source_t *src) { if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) { - zip_error_set(&src->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; } return _zip_source_call(src, NULL, 0, ZIP_SOURCE_TELL_WRITE); diff --git a/zip_source_window.c b/zip_source_window.c index d996015..6f457b6 100644 --- a/zip_source_window.c +++ b/zip_source_window.c @@ -1,6 +1,6 @@ /* zip_source_window.c -- return part of lower source - Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,6 +40,7 @@ struct window { zip_uint64_t start; /* where in file we start reading */ zip_uint64_t end; /* where in file we stop reading */ + bool end_valid; /* whether end is set, otherwise read until EOF */ /* if not NULL, read file data for this file */ zip_t *source_archive; @@ -57,34 +58,47 @@ struct window { static zip_int64_t window_read(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t); -zip_source_t * -zip_source_window(zip_t *za, zip_source_t *src, zip_uint64_t start, zip_uint64_t len) { - return _zip_source_window_new(src, start, len, NULL, 0, NULL, 0, &za->error); +ZIP_EXTERN zip_source_t * +zip_source_window_create(zip_source_t *src, zip_uint64_t start, zip_int64_t len, zip_error_t *error) { + return _zip_source_window_new(src, start, len, NULL, 0, NULL, 0, error); } zip_source_t * -_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error) { +_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_int64_t length, zip_stat_t *st, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error) { struct window *ctx; - if (src == NULL || start + length < start || (source_archive == NULL && source_index != 0)) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; + if (src == NULL || length < -1 || (source_archive == NULL && source_index != 0)) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if (length >= 0) { + if (start + (zip_uint64_t)length < start) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } } if ((ctx = (struct window *)malloc(sizeof(*ctx))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } ctx->start = start; - ctx->end = start + length; - zip_stat_init(&ctx->stat); - if (attributes != NULL) { - memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes)); + if (length == -1) { + ctx->end_valid = false; } else { - zip_file_attributes_init(&ctx->attributes); + ctx->end = start + (zip_uint64_t)length; + ctx->end_valid = true; + } + zip_stat_init(&ctx->stat); + if (attributes != NULL) { + memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes)); + } + else { + zip_file_attributes_init(&ctx->attributes); } ctx->source_archive = source_archive; ctx->source_index = source_index; @@ -93,12 +107,12 @@ _zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t lengt ctx->needs_seek = (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) ? true : false; if (st) { - if (_zip_stat_merge(&ctx->stat, st, error) < 0) { - free(ctx); - return NULL; - } + if (_zip_stat_merge(&ctx->stat, st, error) < 0) { + free(ctx); + return NULL; + } } - + return zip_source_layered_create(src, window_read, ctx, error); } @@ -116,7 +130,7 @@ _zip_source_invalidate(zip_source_t *src) { src->source_closed = 1; if (zip_error_code_zip(&src->error) == ZIP_ER_OK) { - zip_error_set(&src->error, ZIP_ER_ZIPCLOSED, 0); + zip_error_set(&src->error, ZIP_ER_ZIPCLOSED, 0); } } @@ -131,129 +145,159 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou switch (cmd) { case ZIP_SOURCE_CLOSE: - return 0; + return 0; case ZIP_SOURCE_ERROR: - return zip_error_to_data(&ctx->error, data, len); + return zip_error_to_data(&ctx->error, data, len); case ZIP_SOURCE_FREE: - free(ctx); - return 0; + free(ctx); + return 0; case ZIP_SOURCE_OPEN: - if (ctx->source_archive) { - zip_uint64_t offset; + if (ctx->source_archive) { + zip_uint64_t offset; - if ((offset = _zip_file_get_offset(ctx->source_archive, ctx->source_index, &ctx->error)) == 0) { - return -1; - } - if (ctx->end + offset < ctx->end) { - /* zip archive data claims end of data past zip64 limits */ - zip_error_set(&ctx->error, ZIP_ER_INCONS, 0); - return -1; - } - ctx->start += offset; - ctx->end += offset; - ctx->source_archive = NULL; - } + if ((offset = _zip_file_get_offset(ctx->source_archive, ctx->source_index, &ctx->error)) == 0) { + return -1; + } + if (ctx->end + offset < ctx->end) { + /* zip archive data claims end of data past zip64 limits */ + zip_error_set(&ctx->error, ZIP_ER_INCONS, MAKE_DETAIL_WITH_INDEX(ZIP_ER_DETAIL_CDIR_ENTRY_INVALID, ctx->source_index)); + return -1; + } + ctx->start += offset; + ctx->end += offset; + ctx->source_archive = NULL; + } - if (!ctx->needs_seek) { - DEFINE_BYTE_ARRAY(b, BUFSIZE); + if (!ctx->needs_seek) { + DEFINE_BYTE_ARRAY(b, BUFSIZE); - if (!byte_array_init(b, BUFSIZE)) { - zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); - return -1; - } + if (!byte_array_init(b, BUFSIZE)) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; + } - for (n = 0; n < ctx->start; n += (zip_uint64_t)ret) { - i = (ctx->start - n > BUFSIZE ? BUFSIZE : ctx->start - n); - if ((ret = zip_source_read(src, b, i)) < 0) { - _zip_error_set_from_source(&ctx->error, src); - byte_array_fini(b); - return -1; - } - if (ret == 0) { - zip_error_set(&ctx->error, ZIP_ER_EOF, 0); - byte_array_fini(b); - return -1; - } - } + for (n = 0; n < ctx->start; n += (zip_uint64_t)ret) { + i = (ctx->start - n > BUFSIZE ? BUFSIZE : ctx->start - n); + if ((ret = zip_source_read(src, b, i)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + byte_array_fini(b); + return -1; + } + if (ret == 0) { + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); + byte_array_fini(b); + return -1; + } + } - byte_array_fini(b); - } + byte_array_fini(b); + } - ctx->offset = ctx->start; - return 0; + ctx->offset = ctx->start; + return 0; case ZIP_SOURCE_READ: - if (len > ctx->end - ctx->offset) - len = ctx->end - ctx->offset; + if (ctx->end_valid && len > ctx->end - ctx->offset) { + len = ctx->end - ctx->offset; + } - if (len == 0) - return 0; + if (len == 0) { + return 0; + } - if (ctx->needs_seek) { - if (zip_source_seek(src, (zip_int64_t)ctx->offset, SEEK_SET) < 0) { - _zip_error_set_from_source(&ctx->error, src); - return -1; - } - } + if (ctx->needs_seek) { + if (zip_source_seek(src, (zip_int64_t)ctx->offset, SEEK_SET) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + } - if ((ret = zip_source_read(src, data, len)) < 0) { - zip_error_set(&ctx->error, ZIP_ER_EOF, 0); - return -1; - } + if ((ret = zip_source_read(src, data, len)) < 0) { + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); + return -1; + } - ctx->offset += (zip_uint64_t)ret; + ctx->offset += (zip_uint64_t)ret; - if (ret == 0) { - if (ctx->offset < ctx->end) { - zip_error_set(&ctx->error, ZIP_ER_EOF, 0); - return -1; - } - } - return ret; + if (ret == 0) { + if (ctx->end_valid && ctx->offset < ctx->end) { + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); + return -1; + } + } + return ret; case ZIP_SOURCE_SEEK: { - zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset - ctx->start, ctx->end - ctx->start, data, len, &ctx->error); + zip_int64_t new_offset; + + if (!ctx->end_valid) { + zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); + + if (args == NULL) { + return -1; + } + if (args->whence == SEEK_END) { + if (zip_source_seek(src, args->offset, args->whence) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + new_offset = zip_source_tell(src); + if (new_offset < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + if ((zip_uint64_t)new_offset < ctx->start) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + (void)zip_source_seek(src, (zip_int64_t)ctx->offset, SEEK_SET); + return -1; + } + ctx->offset = (zip_uint64_t)new_offset; + return 0; + } + } - if (new_offset < 0) { - return -1; - } - - ctx->offset = (zip_uint64_t)new_offset + ctx->start; - return 0; + new_offset = zip_source_seek_compute_offset(ctx->offset - ctx->start, ctx->end - ctx->start, data, len, &ctx->error); + + if (new_offset < 0) { + return -1; + } + + ctx->offset = (zip_uint64_t)new_offset + ctx->start; + return 0; } case ZIP_SOURCE_STAT: { - zip_stat_t *st; + zip_stat_t *st; - st = (zip_stat_t *)data; + st = (zip_stat_t *)data; - if (_zip_stat_merge(st, &ctx->stat, &ctx->error) < 0) { - return -1; - } - return 0; + if (_zip_stat_merge(st, &ctx->stat, &ctx->error) < 0) { + return -1; + } + return 0; } case ZIP_SOURCE_GET_FILE_ATTRIBUTES: - if (len < sizeof(ctx->attributes)) { - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; - } + if (len < sizeof(ctx->attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } - memcpy(data, &ctx->attributes, sizeof(ctx->attributes)); - return sizeof(ctx->attributes); + memcpy(data, &ctx->attributes, sizeof(ctx->attributes)); + return sizeof(ctx->attributes); case ZIP_SOURCE_SUPPORTS: - return ctx->supports; + return ctx->supports; case ZIP_SOURCE_TELL: - return (zip_int64_t)(ctx->offset - ctx->start); + return (zip_int64_t)(ctx->offset - ctx->start); default: - zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); - return -1; + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; } } @@ -263,11 +307,11 @@ _zip_deregister_source(zip_t *za, zip_source_t *src) { unsigned int i; for (i = 0; i < za->nopen_source; i++) { - if (za->open_source[i] == src) { - za->open_source[i] = za->open_source[za->nopen_source - 1]; - za->nopen_source--; - break; - } + if (za->open_source[i] == src) { + za->open_source[i] = za->open_source[za->nopen_source - 1]; + za->nopen_source--; + break; + } } } @@ -277,15 +321,15 @@ _zip_register_source(zip_t *za, zip_source_t *src) { zip_source_t **open_source; if (za->nopen_source + 1 >= za->nopen_source_alloc) { - unsigned int n; - n = za->nopen_source_alloc + 10; - open_source = (zip_source_t **)realloc(za->open_source, n * sizeof(zip_source_t *)); - if (open_source == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; - } - za->nopen_source_alloc = n; - za->open_source = open_source; + unsigned int n; + n = za->nopen_source_alloc + 10; + open_source = (zip_source_t **)realloc(za->open_source, n * sizeof(zip_source_t *)); + if (open_source == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + za->nopen_source_alloc = n; + za->open_source = open_source; } za->open_source[za->nopen_source++] = src; diff --git a/zip_source_winzip_aes_decode.c b/zip_source_winzip_aes_decode.c index 2ee626a..2999654 100644 --- a/zip_source_winzip_aes_decode.c +++ b/zip_source_winzip_aes_decode.c @@ -1,6 +1,6 @@ /* zip_source_winzip_aes_decode.c -- Winzip AES decryption routines - Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -63,35 +63,35 @@ zip_source_winzip_aes_decode(zip_t *za, zip_source_t *src, zip_uint16_t encrypti struct winzip_aes *ctx; if ((encryption_method != ZIP_EM_AES_128 && encryption_method != ZIP_EM_AES_192 && encryption_method != ZIP_EM_AES_256) || password == NULL || src == NULL) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; } if (flags & ZIP_CODEC_ENCODE) { - zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); - return NULL; + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + return NULL; } if (zip_source_stat(src, &st) != 0) { - _zip_error_set_from_source(&za->error, src); - return NULL; + _zip_error_set_from_source(&za->error, src); + return NULL; } aux_length = WINZIP_AES_PASSWORD_VERIFY_LENGTH + SALT_LENGTH(encryption_method) + HMAC_LENGTH; if ((st.valid & ZIP_STAT_COMP_SIZE) == 0 || st.comp_size < aux_length) { - zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0); - return NULL; + zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0); + return NULL; } if ((ctx = winzip_aes_new(encryption_method, password, &za->error)) == NULL) { - return NULL; + return NULL; } ctx->data_length = st.comp_size - aux_length; if ((s2 = zip_source_layered(za, src, winzip_aes_decrypt, ctx)) == NULL) { - winzip_aes_free(ctx); - return NULL; + winzip_aes_free(ctx); + return NULL; } return s2; @@ -107,23 +107,23 @@ decrypt_header(zip_source_t *src, struct winzip_aes *ctx) { headerlen = WINZIP_AES_PASSWORD_VERIFY_LENGTH + SALT_LENGTH(ctx->encryption_method); if ((n = zip_source_read(src, header, headerlen)) < 0) { - _zip_error_set_from_source(&ctx->error, src); - return -1; + _zip_error_set_from_source(&ctx->error, src); + return -1; } if (n != headerlen) { - zip_error_set(&ctx->error, ZIP_ER_EOF, 0); - return -1; + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); + return -1; } if ((ctx->aes_ctx = _zip_winzip_aes_new((zip_uint8_t *)ctx->password, strlen(ctx->password), header, ctx->encryption_method, password_verification, &ctx->error)) == NULL) { - return -1; + return -1; } if (memcmp(password_verification, header + SALT_LENGTH(ctx->encryption_method), WINZIP_AES_PASSWORD_VERIFY_LENGTH) != 0) { - _zip_winzip_aes_free(ctx->aes_ctx); - ctx->aes_ctx = NULL; - zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0); - return -1; + _zip_winzip_aes_free(ctx->aes_ctx); + ctx->aes_ctx = NULL; + zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0); + return -1; } return 0; } @@ -133,20 +133,20 @@ static bool verify_hmac(zip_source_t *src, struct winzip_aes *ctx) { unsigned char computed[SHA1_LENGTH], from_file[HMAC_LENGTH]; if (zip_source_read(src, from_file, HMAC_LENGTH) < HMAC_LENGTH) { - _zip_error_set_from_source(&ctx->error, src); - return false; + _zip_error_set_from_source(&ctx->error, src); + return false; } if (!_zip_winzip_aes_finish(ctx->aes_ctx, computed)) { - zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); - return false; + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + return false; } _zip_winzip_aes_free(ctx->aes_ctx); ctx->aes_ctx = NULL; if (memcmp(from_file, computed, HMAC_LENGTH) != 0) { - zip_error_set(&ctx->error, ZIP_ER_CRC, 0); - return false; + zip_error_set(&ctx->error, ZIP_ER_CRC, 0); + return false; } return true; @@ -162,67 +162,67 @@ winzip_aes_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zi switch (cmd) { case ZIP_SOURCE_OPEN: - if (decrypt_header(src, ctx) < 0) { - return -1; - } - ctx->current_position = 0; - return 0; + if (decrypt_header(src, ctx) < 0) { + return -1; + } + ctx->current_position = 0; + return 0; case ZIP_SOURCE_READ: - if (len > ctx->data_length - ctx->current_position) { - len = ctx->data_length - ctx->current_position; - } + if (len > ctx->data_length - ctx->current_position) { + len = ctx->data_length - ctx->current_position; + } - if (len == 0) { - if (!verify_hmac(src, ctx)) { - return -1; - } - return 0; - } + if (len == 0) { + if (!verify_hmac(src, ctx)) { + return -1; + } + return 0; + } - if ((n = zip_source_read(src, data, len)) < 0) { - _zip_error_set_from_source(&ctx->error, src); - return -1; - } - ctx->current_position += (zip_uint64_t)n; + if ((n = zip_source_read(src, data, len)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + ctx->current_position += (zip_uint64_t)n; - if (!_zip_winzip_aes_decrypt(ctx->aes_ctx, (zip_uint8_t *)data, (zip_uint64_t)n)) { - zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); - return -1; - } + if (!_zip_winzip_aes_decrypt(ctx->aes_ctx, (zip_uint8_t *)data, (zip_uint64_t)n)) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + return -1; + } - return n; + return n; case ZIP_SOURCE_CLOSE: - return 0; + return 0; case ZIP_SOURCE_STAT: { - zip_stat_t *st; + zip_stat_t *st; - st = (zip_stat_t *)data; + st = (zip_stat_t *)data; - st->encryption_method = ZIP_EM_NONE; - st->valid |= ZIP_STAT_ENCRYPTION_METHOD; - if (st->valid & ZIP_STAT_COMP_SIZE) { - st->comp_size -= 12 + SALT_LENGTH(ctx->encryption_method); - } + st->encryption_method = ZIP_EM_NONE; + st->valid |= ZIP_STAT_ENCRYPTION_METHOD; + if (st->valid & ZIP_STAT_COMP_SIZE) { + st->comp_size -= 12 + SALT_LENGTH(ctx->encryption_method); + } - return 0; + return 0; } case ZIP_SOURCE_SUPPORTS: - return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1); + return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1); case ZIP_SOURCE_ERROR: - return zip_error_to_data(&ctx->error, data, len); + return zip_error_to_data(&ctx->error, data, len); case ZIP_SOURCE_FREE: - winzip_aes_free(ctx); - return 0; + winzip_aes_free(ctx); + return 0; default: - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; } } @@ -230,7 +230,7 @@ winzip_aes_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zi static void winzip_aes_free(struct winzip_aes *ctx) { if (ctx == NULL) { - return; + return; } _zip_crypto_clear(ctx->password, strlen(ctx->password)); @@ -246,14 +246,14 @@ winzip_aes_new(zip_uint16_t encryption_method, const char *password, zip_error_t struct winzip_aes *ctx; if ((ctx = (struct winzip_aes *)malloc(sizeof(*ctx))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } if ((ctx->password = strdup(password)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - free(ctx); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(ctx); + return NULL; } ctx->encryption_method = encryption_method; diff --git a/zip_source_winzip_aes_encode.c b/zip_source_winzip_aes_encode.c index f9ae555..44c4e4b 100644 --- a/zip_source_winzip_aes_encode.c +++ b/zip_source_winzip_aes_encode.c @@ -1,6 +1,6 @@ /* zip_source_winzip_aes_encode.c -- Winzip AES encryption routines - Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -63,17 +63,17 @@ zip_source_winzip_aes_encode(zip_t *za, zip_source_t *src, zip_uint16_t encrypti struct winzip_aes *ctx; if ((encryption_method != ZIP_EM_AES_128 && encryption_method != ZIP_EM_AES_192 && encryption_method != ZIP_EM_AES_256) || password == NULL || src == NULL) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; } if ((ctx = winzip_aes_new(encryption_method, password, &za->error)) == NULL) { - return NULL; + return NULL; } if ((s2 = zip_source_layered(za, src, winzip_aes_encrypt, ctx)) == NULL) { - winzip_aes_free(ctx); - return NULL; + winzip_aes_free(ctx); + return NULL; } return s2; @@ -84,19 +84,19 @@ static int encrypt_header(zip_source_t *src, struct winzip_aes *ctx) { zip_uint16_t salt_length = SALT_LENGTH(ctx->encryption_method); if (!zip_secure_random(ctx->data, salt_length)) { - zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); - return -1; + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + return -1; } if ((ctx->aes_ctx = _zip_winzip_aes_new((zip_uint8_t *)ctx->password, strlen(ctx->password), ctx->data, ctx->encryption_method, ctx->data + salt_length, &ctx->error)) == NULL) { - return -1; + return -1; } if ((ctx->buffer = _zip_buffer_new(ctx->data, salt_length + WINZIP_AES_PASSWORD_VERIFY_LENGTH)) == NULL) { - _zip_winzip_aes_free(ctx->aes_ctx); - ctx->aes_ctx = NULL; - zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); - return -1; + _zip_winzip_aes_free(ctx->aes_ctx); + ctx->aes_ctx = NULL; + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; } return 0; @@ -113,102 +113,102 @@ winzip_aes_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length, switch (cmd) { case ZIP_SOURCE_OPEN: - ctx->eof = false; - if (encrypt_header(src, ctx) < 0) { - return -1; - } - return 0; + ctx->eof = false; + if (encrypt_header(src, ctx) < 0) { + return -1; + } + return 0; case ZIP_SOURCE_READ: - buffer_n = 0; + buffer_n = 0; - if (ctx->buffer) { - buffer_n = _zip_buffer_read(ctx->buffer, data, length); + if (ctx->buffer) { + buffer_n = _zip_buffer_read(ctx->buffer, data, length); - data = (zip_uint8_t *)data + buffer_n; - length -= buffer_n; + data = (zip_uint8_t *)data + buffer_n; + length -= buffer_n; - if (_zip_buffer_eof(ctx->buffer)) { - _zip_buffer_free(ctx->buffer); - ctx->buffer = NULL; - } - } + if (_zip_buffer_eof(ctx->buffer)) { + _zip_buffer_free(ctx->buffer); + ctx->buffer = NULL; + } + } - if (ctx->eof) { - return (zip_int64_t)buffer_n; - } + if (ctx->eof) { + return (zip_int64_t)buffer_n; + } - if ((ret = zip_source_read(src, data, length)) < 0) { - _zip_error_set_from_source(&ctx->error, src); - return -1; - } + if ((ret = zip_source_read(src, data, length)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } - if (!_zip_winzip_aes_encrypt(ctx->aes_ctx, data, (zip_uint64_t)ret)) { - zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); - /* TODO: return partial read? */ - return -1; - } + if (!_zip_winzip_aes_encrypt(ctx->aes_ctx, data, (zip_uint64_t)ret)) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + /* TODO: return partial read? */ + return -1; + } - if ((zip_uint64_t)ret < length) { - ctx->eof = true; - if (!_zip_winzip_aes_finish(ctx->aes_ctx, ctx->data)) { - zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); - /* TODO: return partial read? */ - return -1; - } - _zip_winzip_aes_free(ctx->aes_ctx); - ctx->aes_ctx = NULL; - if ((ctx->buffer = _zip_buffer_new(ctx->data, HMAC_LENGTH)) == NULL) { - zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); - /* TODO: return partial read? */ - return -1; - } - buffer_n += _zip_buffer_read(ctx->buffer, (zip_uint8_t *)data + ret, length - (zip_uint64_t)ret); - } + if ((zip_uint64_t)ret < length) { + ctx->eof = true; + if (!_zip_winzip_aes_finish(ctx->aes_ctx, ctx->data)) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + /* TODO: return partial read? */ + return -1; + } + _zip_winzip_aes_free(ctx->aes_ctx); + ctx->aes_ctx = NULL; + if ((ctx->buffer = _zip_buffer_new(ctx->data, HMAC_LENGTH)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + /* TODO: return partial read? */ + return -1; + } + buffer_n += _zip_buffer_read(ctx->buffer, (zip_uint8_t *)data + ret, length - (zip_uint64_t)ret); + } - return (zip_int64_t)(buffer_n + (zip_uint64_t)ret); + return (zip_int64_t)(buffer_n + (zip_uint64_t)ret); case ZIP_SOURCE_CLOSE: - return 0; + return 0; case ZIP_SOURCE_STAT: { - zip_stat_t *st; + zip_stat_t *st; - st = (zip_stat_t *)data; - st->encryption_method = ctx->encryption_method; - st->valid |= ZIP_STAT_ENCRYPTION_METHOD; - if (st->valid & ZIP_STAT_COMP_SIZE) { - st->comp_size += 12 + SALT_LENGTH(ctx->encryption_method); - } + st = (zip_stat_t *)data; + st->encryption_method = ctx->encryption_method; + st->valid |= ZIP_STAT_ENCRYPTION_METHOD; + if (st->valid & ZIP_STAT_COMP_SIZE) { + st->comp_size += 12 + SALT_LENGTH(ctx->encryption_method); + } - return 0; + return 0; } case ZIP_SOURCE_GET_FILE_ATTRIBUTES: { - zip_file_attributes_t *attributes = (zip_file_attributes_t *)data; - if (length < sizeof(*attributes)) { - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; - } - attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED; - attributes->version_needed = 51; + zip_file_attributes_t *attributes = (zip_file_attributes_t *)data; + if (length < sizeof(*attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED; + attributes->version_needed = 51; - return 0; + return 0; } case ZIP_SOURCE_SUPPORTS: - return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1); + return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1); case ZIP_SOURCE_ERROR: - return zip_error_to_data(&ctx->error, data, length); + return zip_error_to_data(&ctx->error, data, length); case ZIP_SOURCE_FREE: - winzip_aes_free(ctx); - return 0; + winzip_aes_free(ctx); + return 0; default: - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; } } @@ -216,7 +216,7 @@ winzip_aes_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length, static void winzip_aes_free(struct winzip_aes *ctx) { if (ctx == NULL) { - return; + return; } _zip_crypto_clear(ctx->password, strlen(ctx->password)); @@ -233,14 +233,14 @@ winzip_aes_new(zip_uint16_t encryption_method, const char *password, zip_error_t struct winzip_aes *ctx; if ((ctx = (struct winzip_aes *)malloc(sizeof(*ctx))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } if ((ctx->password = strdup(password)) == NULL) { - free(ctx); - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + free(ctx); + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } ctx->encryption_method = encryption_method; diff --git a/zip_source_write.c b/zip_source_write.c index 73fc3a3..bb72b14 100644 --- a/zip_source_write.c +++ b/zip_source_write.c @@ -1,6 +1,6 @@ /* zip_source_write.c -- start a new file for writing - Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -38,8 +38,8 @@ ZIP_EXTERN zip_int64_t zip_source_write(zip_source_t *src, const void *data, zip_uint64_t length) { if (!ZIP_SOURCE_IS_OPEN_WRITING(src) || length > ZIP_INT64_MAX) { - zip_error_set(&src->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; } return _zip_source_call(src, (void *)data, length, ZIP_SOURCE_WRITE); diff --git a/zip_source_zip.c b/zip_source_zip.c index 8a7feaa..e6cedaf 100644 --- a/zip_source_zip.c +++ b/zip_source_zip.c @@ -1,6 +1,6 @@ /* zip_source_zip.c -- create data source from zip file - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -36,21 +36,24 @@ #include "zipint.h" - -ZIP_EXTERN zip_source_t * -zip_source_zip(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_int64_t len) { +ZIP_EXTERN zip_source_t *zip_source_zip_create(zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_int64_t len, zip_error_t *error) { if (len < -1) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } - + if (len == -1) - len = 0; - + len = 0; + if (start == 0 && len == 0) - flags |= ZIP_FL_COMPRESSED; + flags |= ZIP_FL_COMPRESSED; else - flags &= ~ZIP_FL_COMPRESSED; - - return _zip_source_zip_new(za, srcza, srcidx, flags, start, (zip_uint64_t)len, NULL); + flags &= ~ZIP_FL_COMPRESSED; + + return _zip_source_zip_new(srcza, srcidx, flags, start, (zip_uint64_t)len, NULL, error); +} + + +ZIP_EXTERN zip_source_t *zip_source_zip(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_int64_t len) { + return zip_source_zip_create(srcza, srcidx, flags, start, len, &za->error); } diff --git a/zip_source_zip_new.c b/zip_source_zip_new.c index 6d547f0..cf3d267 100644 --- a/zip_source_zip_new.c +++ b/zip_source_zip_new.c @@ -1,6 +1,6 @@ /* zip_source_zip_new.c -- prepare data structures for zip_fopen/zip_source_zip - Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -38,50 +38,45 @@ static void _zip_file_attributes_from_dirent(zip_file_attributes_t *attributes, zip_dirent_t *de); -zip_source_t * -_zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_uint64_t len, const char *password) { +zip_source_t *_zip_source_zip_new(zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_uint64_t len, const char *password, zip_error_t *error) { zip_source_t *src, *s2; zip_stat_t st; zip_file_attributes_t attributes; zip_dirent_t *de; bool partial_data, needs_crc, needs_decrypt, needs_decompress; - if (za == NULL) { - return NULL; - } - - if (srcza == NULL || srcidx >= srcza->nentry) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; + if (srcza == NULL || srcidx >= srcza->nentry || len > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } if ((flags & ZIP_FL_UNCHANGED) == 0 && (ZIP_ENTRY_DATA_CHANGED(srcza->entry + srcidx) || srcza->entry[srcidx].deleted)) { - zip_error_set(&za->error, ZIP_ER_CHANGED, 0); - return NULL; + zip_error_set(error, ZIP_ER_CHANGED, 0); + return NULL; } if (zip_stat_index(srcza, srcidx, flags | ZIP_FL_UNCHANGED, &st) < 0) { - zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; } if (flags & ZIP_FL_ENCRYPTED) { - flags |= ZIP_FL_COMPRESSED; + flags |= ZIP_FL_COMPRESSED; } if ((start > 0 || len > 0) && (flags & ZIP_FL_COMPRESSED)) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } /* overflow or past end of file */ if ((start > 0 || len > 0) && (start + len < start || start + len > st.size)) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } if (len == 0) { - len = st.size - start; + len = st.size - start; } partial_data = len < st.size; @@ -91,89 +86,93 @@ _zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t fl needs_crc = ((flags & ZIP_FL_COMPRESSED) == 0 || st.comp_method == ZIP_CM_STORE) && !partial_data; if (needs_decrypt) { - if (password == NULL) { - password = za->default_password; - } - if (password == NULL) { - zip_error_set(&za->error, ZIP_ER_NOPASSWD, 0); - return NULL; - } + if (password == NULL) { + password = srcza->default_password; + } + if (password == NULL) { + zip_error_set(error, ZIP_ER_NOPASSWD, 0); + return NULL; + } } - if ((de = _zip_get_dirent(srcza, srcidx, flags, &za->error)) == NULL) { - return NULL; + if ((de = _zip_get_dirent(srcza, srcidx, flags, error)) == NULL) { + return NULL; } _zip_file_attributes_from_dirent(&attributes, de); if (st.comp_size == 0) { - return zip_source_buffer_with_attributes(za, NULL, 0, 0, &attributes); + return zip_source_buffer_with_attributes_create(NULL, 0, 0, &attributes, error); } if (partial_data && !needs_decrypt && !needs_decompress) { - struct zip_stat st2; + struct zip_stat st2; - st2.size = len; - st2.comp_size = len; - st2.comp_method = ZIP_CM_STORE; - st2.mtime = st.mtime; - st2.valid = ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_MTIME; + st2.size = len; + st2.comp_size = len; + st2.comp_method = ZIP_CM_STORE; + st2.mtime = st.mtime; + st2.valid = ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_MTIME; - if ((src = _zip_source_window_new(srcza->src, start, len, &st2, &attributes, srcza, srcidx, &za->error)) == NULL) { - return NULL; - } + if ((src = _zip_source_window_new(srcza->src, start, (zip_int64_t)len, &st2, &attributes, srcza, srcidx, error)) == NULL) { + return NULL; + } } else { - if ((src = _zip_source_window_new(srcza->src, 0, st.comp_size, &st, &attributes, srcza, srcidx, &za->error)) == NULL) { - return NULL; - } + if (st.comp_size > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + if ((src = _zip_source_window_new(srcza->src, 0, (zip_int64_t)st.comp_size, &st, &attributes, srcza, srcidx, error)) == NULL) { + return NULL; + } } if (_zip_source_set_source_archive(src, srcza) < 0) { - zip_source_free(src); - return NULL; + zip_source_free(src); + return NULL; } /* creating a layered source calls zip_keep() on the lower layer, so we free it */ if (needs_decrypt) { - zip_encryption_implementation enc_impl; + zip_encryption_implementation enc_impl; - if ((enc_impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) { - zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); - return NULL; - } + if ((enc_impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) { + zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0); + return NULL; + } - s2 = enc_impl(za, src, st.encryption_method, 0, password); - zip_source_free(src); - if (s2 == NULL) { - return NULL; - } - src = s2; + s2 = enc_impl(srcza, src, st.encryption_method, 0, password); + zip_source_free(src); + if (s2 == NULL) { + return NULL; + } + src = s2; } if (needs_decompress) { - s2 = zip_source_decompress(za, src, st.comp_method); - zip_source_free(src); - if (s2 == NULL) { - return NULL; - } - src = s2; + s2 = zip_source_decompress(srcza, src, st.comp_method); + zip_source_free(src); + if (s2 == NULL) { + return NULL; + } + src = s2; } if (needs_crc) { - s2 = zip_source_crc(za, src, 1); - zip_source_free(src); - if (s2 == NULL) { - return NULL; - } - src = s2; + s2 = zip_source_crc_create(src, 1, error); + zip_source_free(src); + if (s2 == NULL) { + return NULL; + } + src = s2; } if (partial_data && (needs_decrypt || needs_decompress)) { - s2 = zip_source_window(za, src, start, len); - zip_source_free(src); - if (s2 == NULL) { - return NULL; - } - src = s2; + s2 = zip_source_window_create(src, start, (zip_int64_t)len, error); + zip_source_free(src); + if (s2 == NULL) { + return NULL; + } + src = s2; } return src; diff --git a/zip_stat.c b/zip_stat.c index 341c6f7..4b7c495 100644 --- a/zip_stat.c +++ b/zip_stat.c @@ -1,6 +1,6 @@ /* zip_stat.c -- get information about file by name - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,7 +40,7 @@ zip_stat(zip_t *za, const char *fname, zip_flags_t flags, zip_stat_t *st) { zip_int64_t idx; if ((idx = zip_name_locate(za, fname, flags)) < 0) - return -1; + return -1; return zip_stat_index(za, (zip_uint64_t)idx, flags, st); } diff --git a/zip_stat_index.c b/zip_stat_index.c index 7799325..62dc045 100644 --- a/zip_stat_index.c +++ b/zip_stat_index.c @@ -41,35 +41,35 @@ zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, zip_stat_t *st) zip_dirent_t *de; if ((de = _zip_get_dirent(za, index, flags, NULL)) == NULL) - return -1; + return -1; if ((name = zip_get_name(za, index, flags)) == NULL) - return -1; + return -1; if ((flags & ZIP_FL_UNCHANGED) == 0 && ZIP_ENTRY_DATA_CHANGED(za->entry + index)) { - zip_entry_t *entry = za->entry + index; + zip_entry_t *entry = za->entry + index; - if (zip_source_stat(entry->source, st) < 0) { - zip_error_set(&za->error, ZIP_ER_CHANGED, 0); - return -1; - } + if (zip_source_stat(entry->source, st) < 0) { + zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + return -1; + } - if (entry->changes->changed & ZIP_DIRENT_LAST_MOD) { - st->mtime = de->last_mod; - st->valid |= ZIP_STAT_MTIME; - } + if (entry->changes != NULL && entry->changes->changed & ZIP_DIRENT_LAST_MOD) { + st->mtime = de->last_mod; + st->valid |= ZIP_STAT_MTIME; + } } else { - zip_stat_init(st); + zip_stat_init(st); - st->crc = de->crc; - st->size = de->uncomp_size; - st->mtime = de->last_mod; - st->comp_size = de->comp_size; - st->comp_method = (zip_uint16_t)de->comp_method; - st->encryption_method = de->encryption_method; - st->valid = (de->crc_valid ? ZIP_STAT_CRC : 0) | ZIP_STAT_SIZE | ZIP_STAT_MTIME | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD; + st->crc = de->crc; + st->size = de->uncomp_size; + st->mtime = de->last_mod; + st->comp_size = de->comp_size; + st->comp_method = (zip_uint16_t)de->comp_method; + st->encryption_method = de->encryption_method; + st->valid = (de->crc_valid ? ZIP_STAT_CRC : 0) | ZIP_STAT_SIZE | ZIP_STAT_MTIME | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD; } st->index = index; diff --git a/zip_stat_init.c b/zip_stat_init.c index 6d0903d..f513bde 100644 --- a/zip_stat_init.c +++ b/zip_stat_init.c @@ -1,6 +1,6 @@ /* zip_stat_init.c -- initialize struct zip_stat. - Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -54,28 +54,28 @@ int _zip_stat_merge(zip_stat_t *dst, const zip_stat_t *src, zip_error_t *error) { /* name is not merged, since zip_stat_t doesn't own it, and src may not be valid as long as dst */ if (src->valid & ZIP_STAT_INDEX) { - dst->index = src->index; + dst->index = src->index; } if (src->valid & ZIP_STAT_SIZE) { - dst->size = src->size; + dst->size = src->size; } if (src->valid & ZIP_STAT_COMP_SIZE) { - dst->comp_size = src->comp_size; + dst->comp_size = src->comp_size; } if (src->valid & ZIP_STAT_MTIME) { - dst->mtime = src->mtime; + dst->mtime = src->mtime; } if (src->valid & ZIP_STAT_CRC) { - dst->crc = src->crc; + dst->crc = src->crc; } if (src->valid & ZIP_STAT_COMP_METHOD) { - dst->comp_method = src->comp_method; + dst->comp_method = src->comp_method; } if (src->valid & ZIP_STAT_ENCRYPTION_METHOD) { - dst->encryption_method = src->encryption_method; + dst->encryption_method = src->encryption_method; } if (src->valid & ZIP_STAT_FLAGS) { - dst->flags = src->flags; + dst->flags = src->flags; } dst->valid |= src->valid; diff --git a/zip_strerror.c b/zip_strerror.c index 906c7f7..e22db65 100644 --- a/zip_strerror.c +++ b/zip_strerror.c @@ -1,6 +1,6 @@ /* zip_sterror.c -- get string representation of zip error - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at diff --git a/zip_string.c b/zip_string.c index 122721d..7013315 100644 --- a/zip_string.c +++ b/zip_string.c @@ -1,6 +1,6 @@ /* zip_string.c -- string handling (with encoding) - Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -45,7 +45,7 @@ _zip_string_crc32(const zip_string_t *s) { crc = (zip_uint32_t)crc32(0L, Z_NULL, 0); if (s != NULL) - crc = (zip_uint32_t)crc32(crc, s->raw, s->length); + crc = (zip_uint32_t)crc32(crc, s->raw, s->length); return crc; } @@ -54,10 +54,10 @@ _zip_string_crc32(const zip_string_t *s) { int _zip_string_equal(const zip_string_t *a, const zip_string_t *b) { if (a == NULL || b == NULL) - return a == b; + return a == b; if (a->length != b->length) - return 0; + return 0; /* TODO: encoding */ @@ -68,7 +68,7 @@ _zip_string_equal(const zip_string_t *a, const zip_string_t *b) { void _zip_string_free(zip_string_t *s) { if (s == NULL) - return; + return; free(s->raw); free(s->converted); @@ -81,29 +81,29 @@ _zip_string_get(zip_string_t *string, zip_uint32_t *lenp, zip_flags_t flags, zip static const zip_uint8_t empty[1] = ""; if (string == NULL) { - if (lenp) - *lenp = 0; - return empty; + if (lenp) + *lenp = 0; + return empty; } if ((flags & ZIP_FL_ENC_RAW) == 0) { - /* start guessing */ - if (string->encoding == ZIP_ENCODING_UNKNOWN) - _zip_guess_encoding(string, ZIP_ENCODING_UNKNOWN); + /* start guessing */ + if (string->encoding == ZIP_ENCODING_UNKNOWN) + _zip_guess_encoding(string, ZIP_ENCODING_UNKNOWN); - if (((flags & ZIP_FL_ENC_STRICT) && string->encoding != ZIP_ENCODING_ASCII && string->encoding != ZIP_ENCODING_UTF8_KNOWN) || (string->encoding == ZIP_ENCODING_CP437)) { - if (string->converted == NULL) { - if ((string->converted = _zip_cp437_to_utf8(string->raw, string->length, &string->converted_length, error)) == NULL) - return NULL; - } - if (lenp) - *lenp = string->converted_length; - return string->converted; - } + if (((flags & ZIP_FL_ENC_STRICT) && string->encoding != ZIP_ENCODING_ASCII && string->encoding != ZIP_ENCODING_UTF8_KNOWN) || (string->encoding == ZIP_ENCODING_CP437)) { + if (string->converted == NULL) { + if ((string->converted = _zip_cp437_to_utf8(string->raw, string->length, &string->converted_length, error)) == NULL) + return NULL; + } + if (lenp) + *lenp = string->converted_length; + return string->converted; + } } if (lenp) - *lenp = string->length; + *lenp = string->length; return string->raw; } @@ -111,7 +111,7 @@ _zip_string_get(zip_string_t *string, zip_uint32_t *lenp, zip_flags_t flags, zip zip_uint16_t _zip_string_length(const zip_string_t *s) { if (s == NULL) - return 0; + return 0; return s->length; } @@ -123,31 +123,31 @@ _zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags, zip_encoding_type_t expected_encoding; if (length == 0) - return NULL; + return NULL; switch (flags & ZIP_FL_ENCODING_ALL) { case ZIP_FL_ENC_GUESS: - expected_encoding = ZIP_ENCODING_UNKNOWN; - break; + expected_encoding = ZIP_ENCODING_UNKNOWN; + break; case ZIP_FL_ENC_UTF_8: - expected_encoding = ZIP_ENCODING_UTF8_KNOWN; - break; + expected_encoding = ZIP_ENCODING_UTF8_KNOWN; + break; case ZIP_FL_ENC_CP437: - expected_encoding = ZIP_ENCODING_CP437; - break; + expected_encoding = ZIP_ENCODING_CP437; + break; default: - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } if ((s = (zip_string_t *)malloc(sizeof(*s))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } if ((s->raw = (zip_uint8_t *)malloc((size_t)length + 1)) == NULL) { - free(s); - return NULL; + free(s); + return NULL; } memcpy(s->raw, raw, length); @@ -158,11 +158,11 @@ _zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags, s->converted_length = 0; if (expected_encoding != ZIP_ENCODING_UNKNOWN) { - if (_zip_guess_encoding(s, expected_encoding) == ZIP_ENCODING_ERROR) { - _zip_string_free(s); - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; - } + if (_zip_guess_encoding(s, expected_encoding) == ZIP_ENCODING_ERROR) { + _zip_string_free(s); + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } } return s; @@ -172,7 +172,7 @@ _zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags, int _zip_string_write(zip_t *za, const zip_string_t *s) { if (s == NULL) - return 0; + return 0; return _zip_write(za, s->raw, s->length); } diff --git a/zip_unchange.c b/zip_unchange.c index 1a78e2c..d80a6ad 100644 --- a/zip_unchange.c +++ b/zip_unchange.c @@ -1,6 +1,6 @@ /* zip_unchange.c -- undo changes to file in zip archive - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -49,39 +49,39 @@ _zip_unchange(zip_t *za, zip_uint64_t idx, int allow_duplicates) { const char *orig_name, *changed_name; if (idx >= za->nentry) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } if (!allow_duplicates && za->entry[idx].changes && (za->entry[idx].changes->changed & ZIP_DIRENT_FILENAME)) { - if (za->entry[idx].orig != NULL) { - if ((orig_name = _zip_get_name(za, idx, ZIP_FL_UNCHANGED, &za->error)) == NULL) { - return -1; - } + if (za->entry[idx].orig != NULL) { + if ((orig_name = _zip_get_name(za, idx, ZIP_FL_UNCHANGED, &za->error)) == NULL) { + return -1; + } - i = _zip_name_locate(za, orig_name, 0, NULL); - if (i >= 0 && (zip_uint64_t)i != idx) { - zip_error_set(&za->error, ZIP_ER_EXISTS, 0); - return -1; - } - } - else { - orig_name = NULL; - } + i = _zip_name_locate(za, orig_name, 0, NULL); + if (i >= 0 && (zip_uint64_t)i != idx) { + zip_error_set(&za->error, ZIP_ER_EXISTS, 0); + return -1; + } + } + else { + orig_name = NULL; + } - if ((changed_name = _zip_get_name(za, idx, 0, &za->error)) == NULL) { - return -1; - } + if ((changed_name = _zip_get_name(za, idx, 0, &za->error)) == NULL) { + return -1; + } - if (orig_name) { - if (_zip_hash_add(za->names, (const zip_uint8_t *)orig_name, idx, 0, &za->error) == false) { - return -1; - } - } - if (_zip_hash_delete(za->names, (const zip_uint8_t *)changed_name, &za->error) == false) { - _zip_hash_delete(za->names, (const zip_uint8_t *)orig_name, NULL); - return -1; - } + if (orig_name) { + if (_zip_hash_add(za->names, (const zip_uint8_t *)orig_name, idx, 0, &za->error) == false) { + return -1; + } + } + if (_zip_hash_delete(za->names, (const zip_uint8_t *)changed_name, &za->error) == false) { + _zip_hash_delete(za->names, (const zip_uint8_t *)orig_name, NULL); + return -1; + } } _zip_dirent_free(za->entry[idx].changes); diff --git a/zip_unchange_all.c b/zip_unchange_all.c index 2ae742f..7b0a4c0 100644 --- a/zip_unchange_all.c +++ b/zip_unchange_all.c @@ -1,6 +1,6 @@ /* zip_unchange.c -- undo changes to all files in zip archive - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -41,12 +41,12 @@ zip_unchange_all(zip_t *za) { zip_uint64_t i; if (!_zip_hash_revert(za->names, &za->error)) { - return -1; + return -1; } ret = 0; for (i = 0; i < za->nentry; i++) - ret |= _zip_unchange(za, i, 1); + ret |= _zip_unchange(za, i, 1); ret |= zip_unchange_archive(za); diff --git a/zip_unchange_archive.c b/zip_unchange_archive.c index bd223ef..a0616cc 100644 --- a/zip_unchange_archive.c +++ b/zip_unchange_archive.c @@ -1,6 +1,6 @@ /* zip_unchange_archive.c -- undo global changes to ZIP archive - Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -40,9 +40,9 @@ ZIP_EXTERN int zip_unchange_archive(zip_t *za) { if (za->comment_changed) { - _zip_string_free(za->comment_changes); - za->comment_changes = NULL; - za->comment_changed = 0; + _zip_string_free(za->comment_changes); + za->comment_changes = NULL; + za->comment_changed = 0; } za->ch_flags = za->flags; diff --git a/zip_unchange_data.c b/zip_unchange_data.c index 74a429c..153c839 100644 --- a/zip_unchange_data.c +++ b/zip_unchange_data.c @@ -1,6 +1,6 @@ /* zip_unchange_data.c -- undo helper function - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -37,16 +37,16 @@ void _zip_unchange_data(zip_entry_t *ze) { if (ze->source) { - zip_source_free(ze->source); - ze->source = NULL; + zip_source_free(ze->source); + ze->source = NULL; } if (ze->changes != NULL && (ze->changes->changed & ZIP_DIRENT_COMP_METHOD) && ze->changes->comp_method == ZIP_CM_REPLACED_DEFAULT) { - ze->changes->changed &= ~ZIP_DIRENT_COMP_METHOD; - if (ze->changes->changed == 0) { - _zip_dirent_free(ze->changes); - ze->changes = NULL; - } + ze->changes->changed &= ~ZIP_DIRENT_COMP_METHOD; + if (ze->changes->changed == 0) { + _zip_dirent_free(ze->changes); + ze->changes = NULL; + } } ze->deleted = 0; diff --git a/zip_utf-8.c b/zip_utf-8.c index 099db9b..ebf67fa 100644 --- a/zip_utf-8.c +++ b/zip_utf-8.c @@ -1,6 +1,6 @@ /* zip_utf-8.c -- UTF-8 support functions for libzip - Copyright (C) 2011-2019 Dieter Baron and Thomas Klausner + Copyright (C) 2011-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -103,54 +103,54 @@ _zip_guess_encoding(zip_string_t *str, zip_encoding_type_t expected_encoding) { zip_uint32_t i, j, ulen; if (str == NULL) - return ZIP_ENCODING_ASCII; + return ZIP_ENCODING_ASCII; name = str->raw; if (str->encoding != ZIP_ENCODING_UNKNOWN) - enc = str->encoding; + enc = str->encoding; else { - enc = ZIP_ENCODING_ASCII; - for (i = 0; i < str->length; i++) { - if ((name[i] > 31 && name[i] < 128) || name[i] == '\r' || name[i] == '\n' || name[i] == '\t') - continue; + enc = ZIP_ENCODING_ASCII; + for (i = 0; i < str->length; i++) { + if ((name[i] > 31 && name[i] < 128) || name[i] == '\r' || name[i] == '\n' || name[i] == '\t') + continue; - enc = ZIP_ENCODING_UTF8_GUESSED; - if ((name[i] & UTF_8_LEN_2_MASK) == UTF_8_LEN_2_MATCH) - ulen = 1; - else if ((name[i] & UTF_8_LEN_3_MASK) == UTF_8_LEN_3_MATCH) - ulen = 2; - else if ((name[i] & UTF_8_LEN_4_MASK) == UTF_8_LEN_4_MATCH) - ulen = 3; - else { - enc = ZIP_ENCODING_CP437; - break; - } + enc = ZIP_ENCODING_UTF8_GUESSED; + if ((name[i] & UTF_8_LEN_2_MASK) == UTF_8_LEN_2_MATCH) + ulen = 1; + else if ((name[i] & UTF_8_LEN_3_MASK) == UTF_8_LEN_3_MATCH) + ulen = 2; + else if ((name[i] & UTF_8_LEN_4_MASK) == UTF_8_LEN_4_MATCH) + ulen = 3; + else { + enc = ZIP_ENCODING_CP437; + break; + } - if (i + ulen >= str->length) { - enc = ZIP_ENCODING_CP437; - break; - } + if (i + ulen >= str->length) { + enc = ZIP_ENCODING_CP437; + break; + } - for (j = 1; j <= ulen; j++) { - if ((name[i + j] & UTF_8_CONTINUE_MASK) != UTF_8_CONTINUE_MATCH) { - enc = ZIP_ENCODING_CP437; - goto done; - } - } - i += ulen; - } + for (j = 1; j <= ulen; j++) { + if ((name[i + j] & UTF_8_CONTINUE_MASK) != UTF_8_CONTINUE_MATCH) { + enc = ZIP_ENCODING_CP437; + goto done; + } + } + i += ulen; + } } done: str->encoding = enc; if (expected_encoding != ZIP_ENCODING_UNKNOWN) { - if (expected_encoding == ZIP_ENCODING_UTF8_KNOWN && enc == ZIP_ENCODING_UTF8_GUESSED) - str->encoding = enc = ZIP_ENCODING_UTF8_KNOWN; + if (expected_encoding == ZIP_ENCODING_UTF8_KNOWN && enc == ZIP_ENCODING_UTF8_GUESSED) + str->encoding = enc = ZIP_ENCODING_UTF8_KNOWN; - if (expected_encoding != enc && enc != ZIP_ENCODING_ASCII) - return ZIP_ENCODING_ERROR; + if (expected_encoding != enc && enc != ZIP_ENCODING_ASCII) + return ZIP_ENCODING_ERROR; } return enc; @@ -160,11 +160,11 @@ done: static zip_uint32_t _zip_unicode_to_utf8_len(zip_uint32_t codepoint) { if (codepoint < 0x0080) - return 1; + return 1; if (codepoint < 0x0800) - return 2; + return 2; if (codepoint < 0x10000) - return 3; + return 3; return 4; } @@ -172,19 +172,19 @@ _zip_unicode_to_utf8_len(zip_uint32_t codepoint) { static zip_uint32_t _zip_unicode_to_utf8(zip_uint32_t codepoint, zip_uint8_t *buf) { if (codepoint < 0x0080) { - buf[0] = codepoint & 0xff; - return 1; + buf[0] = codepoint & 0xff; + return 1; } if (codepoint < 0x0800) { - buf[0] = (zip_uint8_t)(UTF_8_LEN_2_MATCH | ((codepoint >> 6) & 0x1f)); - buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f)); - return 2; + buf[0] = (zip_uint8_t)(UTF_8_LEN_2_MATCH | ((codepoint >> 6) & 0x1f)); + buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f)); + return 2; } if (codepoint < 0x10000) { - buf[0] = (zip_uint8_t)(UTF_8_LEN_3_MATCH | ((codepoint >> 12) & 0x0f)); - buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | ((codepoint >> 6) & 0x3f)); - buf[2] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f)); - return 3; + buf[0] = (zip_uint8_t)(UTF_8_LEN_3_MATCH | ((codepoint >> 12) & 0x0f)); + buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | ((codepoint >> 6) & 0x3f)); + buf[2] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f)); + return 3; } buf[0] = (zip_uint8_t)(UTF_8_LEN_4_MATCH | ((codepoint >> 18) & 0x07)); buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | ((codepoint >> 12) & 0x3f)); @@ -201,26 +201,26 @@ _zip_cp437_to_utf8(const zip_uint8_t *const _cp437buf, zip_uint32_t len, zip_uin zip_uint32_t buflen, i, offset; if (len == 0) { - if (utf8_lenp) - *utf8_lenp = 0; - return NULL; + if (utf8_lenp) + *utf8_lenp = 0; + return NULL; } buflen = 1; for (i = 0; i < len; i++) - buflen += _zip_unicode_to_utf8_len(_cp437_to_unicode[cp437buf[i]]); + buflen += _zip_unicode_to_utf8_len(_cp437_to_unicode[cp437buf[i]]); if ((utf8buf = (zip_uint8_t *)malloc(buflen)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } offset = 0; for (i = 0; i < len; i++) - offset += _zip_unicode_to_utf8(_cp437_to_unicode[cp437buf[i]], utf8buf + offset); + offset += _zip_unicode_to_utf8(_cp437_to_unicode[cp437buf[i]], utf8buf + offset); utf8buf[buflen - 1] = 0; if (utf8_lenp) - *utf8_lenp = buflen - 1; + *utf8_lenp = buflen - 1; return utf8buf; } diff --git a/zip_winzip_aes.c b/zip_winzip_aes.c index c86ef88..b36e46c 100644 --- a/zip_winzip_aes.c +++ b/zip_winzip_aes.c @@ -1,6 +1,6 @@ /* zip_winzip_aes.c -- Winzip AES de/encryption backend routines - Copyright (C) 2017-2019 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 @@ -55,19 +55,19 @@ aes_crypt(zip_winzip_aes_t *ctx, zip_uint8_t *data, zip_uint64_t length) { zip_uint64_t i, j; for (i = 0; i < length; i++) { - if (ctx->pad_offset == AES_BLOCK_SIZE) { - for (j = 0; j < 8; j++) { - ctx->counter[j]++; - if (ctx->counter[j] != 0) { - break; - } - } - if (!_zip_crypto_aes_encrypt_block(ctx->aes, ctx->counter, ctx->pad)) { - return false; - } - ctx->pad_offset = 0; - } - data[i] ^= ctx->pad[ctx->pad_offset++]; + if (ctx->pad_offset == AES_BLOCK_SIZE) { + for (j = 0; j < 8; j++) { + ctx->counter[j]++; + if (ctx->counter[j] != 0) { + break; + } + } + if (!_zip_crypto_aes_encrypt_block(ctx->aes, ctx->counter, ctx->pad)) { + return false; + } + ctx->pad_offset = 0; + } + data[i] ^= ctx->pad[ctx->pad_offset++]; } return true; @@ -83,49 +83,49 @@ _zip_winzip_aes_new(const zip_uint8_t *password, zip_uint64_t password_length, c switch (encryption_method) { case ZIP_EM_AES_128: - key_size = 128; - break; + key_size = 128; + break; case ZIP_EM_AES_192: - key_size = 192; - break; + key_size = 192; + break; case ZIP_EM_AES_256: - key_size = 256; - break; + key_size = 256; + break; } if (key_size == 0 || salt == NULL || password == NULL || password_length == 0) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } key_length = key_size / 8; if ((ctx = (zip_winzip_aes_t *)malloc(sizeof(*ctx))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } memset(ctx->counter, 0, sizeof(ctx->counter)); ctx->pad_offset = ZIP_CRYPTO_AES_BLOCK_LENGTH; if (!_zip_crypto_pbkdf2(password, password_length, salt, key_length / 2, PBKDF2_ITERATIONS, buffer, 2 * key_length + WINZIP_AES_PASSWORD_VERIFY_LENGTH)) { - free(ctx); - return NULL; + free(ctx); + return NULL; } if ((ctx->aes = _zip_crypto_aes_new(buffer, key_size, error)) == NULL) { - _zip_crypto_clear(ctx, sizeof(*ctx)); - free(ctx); - return NULL; + _zip_crypto_clear(ctx, sizeof(*ctx)); + free(ctx); + return NULL; } if ((ctx->hmac = _zip_crypto_hmac_new(buffer + key_length, key_length, error)) == NULL) { - _zip_crypto_aes_free(ctx->aes); - free(ctx); - return NULL; + _zip_crypto_aes_free(ctx->aes); + free(ctx); + return NULL; } if (password_verify) { - memcpy(password_verify, buffer + (2 * key_size / 8), WINZIP_AES_PASSWORD_VERIFY_LENGTH); + memcpy(password_verify, buffer + (2 * key_size / 8), WINZIP_AES_PASSWORD_VERIFY_LENGTH); } return ctx; @@ -153,7 +153,7 @@ _zip_winzip_aes_finish(zip_winzip_aes_t *ctx, zip_uint8_t *hmac) { void _zip_winzip_aes_free(zip_winzip_aes_t *ctx) { if (ctx == NULL) { - return; + return; } _zip_crypto_aes_free(ctx->aes); diff --git a/zipint.h b/zipint.h index 99c1806..eab1e3a 100644 --- a/zipint.h +++ b/zipint.h @@ -3,7 +3,7 @@ /* zipint.h -- internal declarations. - Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -35,6 +35,7 @@ */ #include "config.h" + #include "compat.h" #ifdef ZIP_ALLOCATE_BUFFER @@ -121,6 +122,9 @@ enum zip_compression_status { typedef enum zip_compression_status zip_compression_status_t; struct zip_compression_algorithm { + /* Return maxiumum compressed size for uncompressed data of given size. */ + zip_uint64_t (*maximum_compressed_size)(zip_uint64_t uncompressed_size); + /* called once to create new context */ void *(*allocate)(zip_uint16_t method, int compression_flags, zip_error_t *error); /* called once to free context */ @@ -132,7 +136,7 @@ struct zip_compression_algorithm { zip_uint8_t version_needed; /* start processing */ - bool (*start)(void *ctx); + bool (*start)(void *ctx, zip_stat_t *st, zip_file_attributes_t *attributes); /* stop processing */ bool (*end)(void *ctx); @@ -153,7 +157,10 @@ extern zip_compression_algorithm_t zip_algorithm_deflate_compress; extern zip_compression_algorithm_t zip_algorithm_deflate_decompress; extern zip_compression_algorithm_t zip_algorithm_xz_compress; extern zip_compression_algorithm_t zip_algorithm_xz_decompress; +extern zip_compression_algorithm_t zip_algorithm_zstd_compress; +extern zip_compression_algorithm_t zip_algorithm_zstd_decompress; +zip_compression_algorithm_t *_zip_get_compression_algorithm(zip_int32_t method, bool compress); /* This API is not final yet, but we need it internally, so it's private for now. */ @@ -165,7 +172,7 @@ const zip_uint8_t *zip_get_extra_field_by_id(zip_t *, int, int, zip_uint16_t, in typedef zip_int64_t (*zip_source_layered_callback)(zip_source_t *, void *, void *, zip_uint64_t, enum zip_source_cmd); zip_source_t *zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t cm, int compression_flags); -zip_source_t *zip_source_crc(zip_t *, zip_source_t *, int); +zip_source_t *zip_source_crc_create(zip_source_t *, int, zip_error_t *error); zip_source_t *zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t cm); zip_source_t *zip_source_layered(zip_t *, zip_source_t *, zip_source_layered_callback, void *); zip_source_t *zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, void *ud, zip_error_t *error); @@ -173,15 +180,57 @@ zip_source_t *zip_source_pkware_decode(zip_t *, zip_source_t *, zip_uint16_t, in zip_source_t *zip_source_pkware_encode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); int zip_source_remove(zip_source_t *); zip_int64_t zip_source_supports(zip_source_t *src); -zip_source_t *zip_source_window(zip_t *, zip_source_t *, zip_uint64_t, zip_uint64_t); zip_source_t *zip_source_winzip_aes_decode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); zip_source_t *zip_source_winzip_aes_encode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); zip_source_t *zip_source_buffer_with_attributes(zip_t *za, const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes); +zip_source_t *zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes, zip_error_t *error); /* error source for layered sources */ enum zip_les { ZIP_LES_NONE, ZIP_LES_UPPER, ZIP_LES_LOWER, ZIP_LES_INVAL }; +#define ZIP_DETAIL_ET_GLOBAL 0 +#define ZIP_DETAIL_ET_ENTRY 1 + +struct _zip_err_info { + int type; + const char *description; +}; + +extern const struct _zip_err_info _zip_err_str[]; +extern const int _zip_err_str_count; +extern const struct _zip_err_info _zip_err_details[]; +extern const int _zip_err_details_count; + +/* macros for libzip-internal errors */ +#define MAX_DETAIL_INDEX 0x7fffff +#define MAKE_DETAIL_WITH_INDEX(error, index) ((((index) > MAX_DETAIL_INDEX) ? MAX_DETAIL_INDEX : (int)(index)) << 8 | (error)) +#define GET_INDEX_FROM_DETAIL(error) (((error) >> 8) & MAX_DETAIL_INDEX) +#define GET_ERROR_FROM_DETAIL(error) ((error) & 0xff) +#define ADD_INDEX_TO_DETAIL(error, index) MAKE_DETAIL_WITH_INDEX(GET_ERROR_FROM_DETAIL(error), (index)) + +/* error code for libzip-internal errors */ +#define ZIP_ER_DETAIL_NO_DETAIL 0 /* G no detail */ +#define ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD 1 /* G central directory overlaps EOCD, or there is space between them */ +#define ZIP_ER_DETAIL_COMMENT_LENGTH_INVALID 2 /* G archive comment length incorrect */ +#define ZIP_ER_DETAIL_CDIR_LENGTH_INVALID 3 /* G central directory length invalid */ +#define ZIP_ER_DETAIL_CDIR_ENTRY_INVALID 4 /* E central header invalid */ +#define ZIP_ER_DETAIL_CDIR_WRONG_ENTRIES_COUNT 5 /* G central directory count of entries is incorrect */ +#define ZIP_ER_DETAIL_ENTRY_HEADER_MISMATCH 6 /* E local and central headers do not match */ +#define ZIP_ER_DETAIL_EOCD_LENGTH_INVALID 7 /* G wrong EOCD length */ +#define ZIP_ER_DETAIL_EOCD64_OVERLAPS_EOCD 8 /* G EOCD64 overlaps EOCD, or there is space between them */ +#define ZIP_ER_DETAIL_EOCD64_WRONG_MAGIC 9 /* G EOCD64 magic incorrect */ +#define ZIP_ER_DETAIL_EOCD64_MISMATCH 10 /* G EOCD64 and EOCD do not match */ +#define ZIP_ER_DETAIL_CDIR_INVALID 11 /* G invalid value in central directory */ +#define ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW 12 /* E variable size fields overflow header */ +#define ZIP_ER_DETAIL_INVALID_UTF8_IN_FILENAME 13 /* E invalid UTF-8 in filename */ +#define ZIP_ER_DETAIL_INVALID_UTF8_IN_COMMENT 13 /* E invalid UTF-8 in comment */ +#define ZIP_ER_DETAIL_INVALID_ZIP64_EF 14 /* E invalid Zip64 extra field */ +#define ZIP_ER_DETAIL_INVALID_WINZIPAES_EF 14 /* E invalid WinZip AES extra field */ +#define ZIP_ER_DETAIL_EF_TRAILING_GARBAGE 15 /* E garbage at end of extra fields */ +#define ZIP_ER_DETAIL_INVALID_EF_LENGTH 16 /* E extra field length is invalid */ +#define ZIP_ER_DETAIL_INVALID_FILE_LENGTH 17 /* E file length in header doesn't match actual file length */ + /* directory entry: general purpose bit flags */ #define ZIP_GPBF_ENCRYPTED 0x0001u /* is encrypted */ @@ -334,8 +383,8 @@ typedef enum zip_source_write_state zip_source_write_state_t; struct zip_source { zip_source_t *src; union { - zip_source_callback f; - zip_source_layered_callback l; + zip_source_callback f; + zip_source_layered_callback l; } cb; void *ud; zip_error_t error; @@ -345,8 +394,9 @@ struct zip_source { bool source_closed; /* set if source archive is closed */ zip_t *source_archive; /* zip archive we're reading from, NULL if not from archive */ unsigned int refcount; - bool eof; /* EOF reached */ - bool had_read_error; /* a previous ZIP_SOURCE_READ reported an error */ + bool eof; /* EOF reached */ + bool had_read_error; /* a previous ZIP_SOURCE_READ reported an error */ + zip_uint64_t bytes_read; /* for sources that don't support ZIP_SOURCE_TELL. */ }; #define ZIP_SOURCE_IS_OPEN_READING(src) ((src)->open_count > 0) @@ -419,10 +469,6 @@ struct _zip_pkware_keys { }; typedef struct _zip_pkware_keys zip_pkware_keys_t; -extern const char *const _zip_err_str[]; -extern const int _zip_nerr_str; -extern const int _zip_err_type[]; - #define ZIP_MAX(a, b) ((a) > (b) ? (a) : (b)) #define ZIP_MIN(a, b) ((a) < (b) ? (a) : (b)) @@ -561,8 +607,8 @@ bool _zip_source_had_error(zip_source_t *); void _zip_source_invalidate(zip_source_t *src); zip_source_t *_zip_source_new(zip_error_t *error); int _zip_source_set_source_archive(zip_source_t *, zip_t *); -zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error); -zip_source_t *_zip_source_zip_new(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_uint64_t, const char *); +zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_int64_t length, zip_stat_t *st, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error); +zip_source_t *_zip_source_zip_new(zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_uint64_t, const char *, zip_error_t *error); int _zip_stat_merge(zip_stat_t *dst, const zip_stat_t *src, zip_error_t *error); int _zip_string_equal(const zip_string_t *, const zip_string_t *);