From 1fc4168b81f565feab409b92ccb61c57a1c550eb Mon Sep 17 00:00:00 2001 From: DLL125 <134442578+DLL125@users.noreply.github.com> Date: Thu, 25 May 2023 12:52:53 +0200 Subject: Update Libzip to latest 1.9.2 (#1071) * Libzip 1.9.2 Updated Libzip to latest version 1.9.2 and changed version number in the config.h from 1.7.3 to 1.9.2. Not sure if anything else needs to be tweaked :) * Modified Libzip to work with Visual studio * Update README.md Update libzip copyright. * Added the missing files. I've added the missing files zipconf.h and config.h, I've missed those sorry for that! --- README.md | 2 +- src/Common/libzip/LICENSE | 2 +- src/Common/libzip/NEWS.md | 32 + src/Common/libzip/compat.h | 22 +- src/Common/libzip/config.h | 70 +- src/Common/libzip/zip.h | 29 +- src/Common/libzip/zip_add.c | 10 +- src/Common/libzip/zip_add_dir.c | 4 +- src/Common/libzip/zip_add_entry.c | 52 +- src/Common/libzip/zip_algorithm_bzip2.c | 285 +++++++ src/Common/libzip/zip_algorithm_deflate.c | 75 +- src/Common/libzip/zip_algorithm_xz.c | 406 +++++++++ src/Common/libzip/zip_algorithm_zstd.c | 294 +++++++ src/Common/libzip/zip_buffer.c | 64 +- src/Common/libzip/zip_close.c | 743 ++++++++-------- src/Common/libzip/zip_crypto.h | 54 ++ src/Common/libzip/zip_crypto_commoncrypto.c | 110 +++ src/Common/libzip/zip_crypto_commoncrypto.h | 53 ++ src/Common/libzip/zip_crypto_gnutls.c | 134 +++ src/Common/libzip/zip_crypto_gnutls.h | 68 ++ src/Common/libzip/zip_crypto_mbedtls.c | 162 ++++ src/Common/libzip/zip_crypto_mbedtls.h | 56 ++ src/Common/libzip/zip_crypto_openssl.c | 184 ++++ src/Common/libzip/zip_crypto_openssl.h | 56 ++ src/Common/libzip/zip_crypto_win.c | 495 +++++++++++ src/Common/libzip/zip_crypto_win.h | 53 ++ src/Common/libzip/zip_delete.c | 18 +- src/Common/libzip/zip_dir_add.c | 40 +- src/Common/libzip/zip_dirent.c | 939 ++++++++++----------- src/Common/libzip/zip_discard.c | 18 +- src/Common/libzip/zip_entry.c | 4 +- src/Common/libzip/zip_error.c | 45 +- src/Common/libzip/zip_error_clear.c | 6 +- src/Common/libzip/zip_error_get.c | 4 +- src/Common/libzip/zip_error_get_sys_type.c | 11 +- src/Common/libzip/zip_error_strerror.c | 83 +- src/Common/libzip/zip_error_to_str.c | 33 +- src/Common/libzip/zip_extra_field.c | 374 ++++---- src/Common/libzip/zip_extra_field_api.c | 224 ++--- src/Common/libzip/zip_fclose.c | 8 +- src/Common/libzip/zip_fdopen.c | 34 +- src/Common/libzip/zip_file_add.c | 14 +- src/Common/libzip/zip_file_error_clear.c | 6 +- src/Common/libzip/zip_file_error_get.c | 4 +- src/Common/libzip/zip_file_get_comment.c | 10 +- .../libzip/zip_file_get_external_attributes.c | 10 +- src/Common/libzip/zip_file_get_offset.c | 64 +- src/Common/libzip/zip_file_rename.c | 18 +- src/Common/libzip/zip_file_replace.c | 60 +- src/Common/libzip/zip_file_set_comment.c | 62 +- src/Common/libzip/zip_file_set_encryption.c | 116 +++ .../libzip/zip_file_set_external_attributes.c | 46 +- src/Common/libzip/zip_file_set_mtime.c | 23 +- src/Common/libzip/zip_file_strerror.c | 4 +- src/Common/libzip/zip_filerange_crc.c | 84 -- src/Common/libzip/zip_fopen.c | 6 +- src/Common/libzip/zip_fopen_encrypted.c | 6 +- src/Common/libzip/zip_fopen_index.c | 4 +- src/Common/libzip/zip_fopen_index_encrypted.c | 26 +- src/Common/libzip/zip_fread.c | 18 +- src/Common/libzip/zip_fseek.c | 61 ++ src/Common/libzip/zip_ftell.c | 54 ++ src/Common/libzip/zip_get_archive_comment.c | 12 +- src/Common/libzip/zip_get_archive_flag.c | 4 +- .../libzip/zip_get_encryption_implementation.c | 12 +- src/Common/libzip/zip_get_file_comment.c | 8 +- src/Common/libzip/zip_get_name.c | 8 +- src/Common/libzip/zip_get_num_entries.c | 14 +- src/Common/libzip/zip_get_num_files.c | 10 +- src/Common/libzip/zip_hash.c | 294 +++---- src/Common/libzip/zip_io_util.c | 68 +- src/Common/libzip/zip_libzip_version.c | 41 + src/Common/libzip/zip_memdup.c | 10 +- src/Common/libzip/zip_name_locate.c | 75 +- src/Common/libzip/zip_new.c | 12 +- src/Common/libzip/zip_open.c | 743 ++++++++-------- src/Common/libzip/zip_pkware.c | 42 +- src/Common/libzip/zip_progress.c | 110 +-- src/Common/libzip/zip_random_unix.c | 104 +++ src/Common/libzip/zip_random_uwp.c | 81 ++ src/Common/libzip/zip_random_win32.c | 81 ++ src/Common/libzip/zip_rename.c | 4 +- src/Common/libzip/zip_replace.c | 4 +- src/Common/libzip/zip_set_archive_comment.c | 36 +- src/Common/libzip/zip_set_archive_flag.c | 22 +- src/Common/libzip/zip_set_default_password.c | 18 +- src/Common/libzip/zip_set_file_comment.c | 8 +- src/Common/libzip/zip_set_file_compression.c | 54 +- src/Common/libzip/zip_set_name.c | 114 +-- src/Common/libzip/zip_source_accept_empty.c | 12 +- src/Common/libzip/zip_source_begin_write.c | 10 +- src/Common/libzip/zip_source_begin_write_cloning.c | 10 +- src/Common/libzip/zip_source_buffer.c | 434 +++++----- src/Common/libzip/zip_source_call.c | 30 +- src/Common/libzip/zip_source_close.c | 20 +- src/Common/libzip/zip_source_commit_write.c | 22 +- src/Common/libzip/zip_source_compress.c | 347 ++++---- src/Common/libzip/zip_source_crc.c | 181 ++-- src/Common/libzip/zip_source_error.c | 4 +- src/Common/libzip/zip_source_file.h | 6 +- src/Common/libzip/zip_source_file_common.c | 352 ++++---- src/Common/libzip/zip_source_file_stdio.c | 44 +- src/Common/libzip/zip_source_file_stdio.h | 2 +- src/Common/libzip/zip_source_file_stdio_named.c | 361 ++++++++ src/Common/libzip/zip_source_file_win32.c | 24 +- src/Common/libzip/zip_source_file_win32.h | 16 +- src/Common/libzip/zip_source_file_win32_ansi.c | 85 ++ src/Common/libzip/zip_source_file_win32_named.c | 69 +- src/Common/libzip/zip_source_file_win32_utf16.c | 26 +- src/Common/libzip/zip_source_file_win32_utf8.c | 6 +- src/Common/libzip/zip_source_free.c | 20 +- src/Common/libzip/zip_source_function.c | 17 +- src/Common/libzip/zip_source_get_file_attributes.c | 92 +- src/Common/libzip/zip_source_is_deleted.c | 4 +- src/Common/libzip/zip_source_layered.c | 10 +- src/Common/libzip/zip_source_open.c | 43 +- src/Common/libzip/zip_source_pkware_decode.c | 118 ++- src/Common/libzip/zip_source_pkware_encode.c | 158 ++-- src/Common/libzip/zip_source_read.c | 54 +- src/Common/libzip/zip_source_remove.c | 16 +- src/Common/libzip/zip_source_rollback_write.c | 6 +- src/Common/libzip/zip_source_seek.c | 34 +- src/Common/libzip/zip_source_seek_write.c | 8 +- src/Common/libzip/zip_source_stat.c | 20 +- src/Common/libzip/zip_source_supports.c | 14 +- src/Common/libzip/zip_source_tell.c | 18 +- src/Common/libzip/zip_source_tell_write.c | 8 +- src/Common/libzip/zip_source_window.c | 308 ++++--- src/Common/libzip/zip_source_winzip_aes_decode.c | 265 ++++++ src/Common/libzip/zip_source_winzip_aes_encode.c | 254 ++++++ src/Common/libzip/zip_source_write.c | 8 +- src/Common/libzip/zip_source_zip.c | 29 +- src/Common/libzip/zip_source_zip_new.c | 147 ++-- src/Common/libzip/zip_stat.c | 6 +- src/Common/libzip/zip_stat_index.c | 42 +- src/Common/libzip/zip_stat_init.c | 20 +- src/Common/libzip/zip_strerror.c | 4 +- src/Common/libzip/zip_string.c | 86 +- src/Common/libzip/zip_unchange.c | 73 +- src/Common/libzip/zip_unchange_all.c | 8 +- src/Common/libzip/zip_unchange_archive.c | 10 +- src/Common/libzip/zip_unchange_data.c | 18 +- src/Common/libzip/zip_utf-8.c | 116 +-- src/Common/libzip/zip_winzip_aes.c | 162 ++++ src/Common/libzip/zipconf.h | 65 +- src/Common/libzip/zipint.h | 92 +- 146 files changed, 8350 insertions(+), 4105 deletions(-) create mode 100644 src/Common/libzip/zip_algorithm_bzip2.c create mode 100644 src/Common/libzip/zip_algorithm_xz.c create mode 100644 src/Common/libzip/zip_algorithm_zstd.c create mode 100644 src/Common/libzip/zip_crypto.h create mode 100644 src/Common/libzip/zip_crypto_commoncrypto.c create mode 100644 src/Common/libzip/zip_crypto_commoncrypto.h create mode 100644 src/Common/libzip/zip_crypto_gnutls.c create mode 100644 src/Common/libzip/zip_crypto_gnutls.h create mode 100644 src/Common/libzip/zip_crypto_mbedtls.c create mode 100644 src/Common/libzip/zip_crypto_mbedtls.h create mode 100644 src/Common/libzip/zip_crypto_openssl.c create mode 100644 src/Common/libzip/zip_crypto_openssl.h create mode 100644 src/Common/libzip/zip_crypto_win.c create mode 100644 src/Common/libzip/zip_crypto_win.h create mode 100644 src/Common/libzip/zip_file_set_encryption.c delete mode 100644 src/Common/libzip/zip_filerange_crc.c create mode 100644 src/Common/libzip/zip_fseek.c create mode 100644 src/Common/libzip/zip_ftell.c create mode 100644 src/Common/libzip/zip_libzip_version.c create mode 100644 src/Common/libzip/zip_random_unix.c create mode 100644 src/Common/libzip/zip_random_uwp.c create mode 100644 src/Common/libzip/zip_random_win32.c create mode 100644 src/Common/libzip/zip_source_file_stdio_named.c create mode 100644 src/Common/libzip/zip_source_file_win32_ansi.c create mode 100644 src/Common/libzip/zip_source_winzip_aes_decode.c create mode 100644 src/Common/libzip/zip_source_winzip_aes_encode.c create mode 100644 src/Common/libzip/zip_winzip_aes.c diff --git a/README.md b/README.md index 41fbaf61..0e8f7450 100644 --- a/README.md +++ b/README.md @@ -219,7 +219,7 @@ Copyright (c) 1998-2000 Paul Le Roux. All rights reserved. Copyright (c) 1998-2008 Brian Gladman, Worcester, UK. All rights reserved. Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler. Copyright (c) 2016 Disk Cryptography Services for EFI (DCS), Alex Kolotnikov -Copyright (c) 1999-2017 Dieter Baron and Thomas Klausner. +Copyright (c) 1999-2020 Dieter Baron and Thomas Klausner. Copyright (c) 2013, Alexey Degtyarev. All rights reserved. Copyright (c) 1999-2016 Jack Lloyd. All rights reserved. Copyright (c) 2013-2019 Stephan Mueller diff --git a/src/Common/libzip/LICENSE b/src/Common/libzip/LICENSE index 573d5d94..fa706096 100644 --- a/src/Common/libzip/LICENSE +++ b/src/Common/libzip/LICENSE @@ -1,6 +1,6 @@ Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner -The authors can be contacted at +The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/src/Common/libzip/NEWS.md b/src/Common/libzip/NEWS.md index d48b59ac..73bafe2e 100644 --- a/src/Common/libzip/NEWS.md +++ b/src/Common/libzip/NEWS.md @@ -1,3 +1,35 @@ +1.9.2 [2022-06-28] + +* Fix version number in header file. + +1.9.1 [2022-06-28] +=================== + +* Fix `zip_file_is_seekable()`. + +1.9.0 [2022-06-13] +================== + +* Add `zip_file_is_seekable()`. +* Improve compatibility with WinAES. +* Fix encoding handling in `zip_name_locate()`. +* Add option to `zipcmp` to output summary of changes. +* Various bug fixes and documentation improvements. + +1.8.0 [2021-06-18] +================== + +* Add support for zstd (Zstandard) compression. +* Add support for lzma (ID 14) compression. +* Add `zip_source_window_create()`. +* Add `zip_source_zip_create()` variant to `zip_source_zip()`. +* Allow method specific `comp_flags` in `zip_set_file_compression()`. +* Allow `zip_source_tell()` on sources that don't support seeking and `zip_ftell()` on compressed data. +* Provide more details for consistency check errors. +* Improve output of `zipcmp`. +* In `zipcmp`, don’t ignore empty directories when comparing directory listing. +* Treat empty string as no password given in `zip_file_set_encryption()`, `zip_fopen_encrypted()`, and `zip_set_default_password()`. + 1.7.3 [2020-07-15] ================== diff --git a/src/Common/libzip/compat.h b/src/Common/libzip/compat.h index fb2c56e1..82661792 100644 --- a/src/Common/libzip/compat.h +++ b/src/Common/libzip/compat.h @@ -3,10 +3,10 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -41,27 +41,26 @@ /* to have *_MAX definitions for all types when compiling with g++ */ #define __STDC_LIMIT_MACROS -#ifdef _WIN32 -#ifndef ZIP_EXTERN -#ifndef ZIP_STATIC +#if defined(_WIN32) && defined(ZIP_DLL) && !defined(ZIP_STATIC) +#ifdef BUILDING_LIBZIP #define ZIP_EXTERN __declspec(dllexport) #else -#define ZIP_EXTERN +#define ZIP_EXTERN __declspec(dllimport) #endif #endif + +#ifdef _WIN32 /* for dup(), close(), etc. */ #include #endif #ifdef HAVE_STDBOOL_H #include -#else -#ifndef __cplusplus +#elif !defined(__BOOL_DEFINED) typedef char bool; #define true 1 #define false 0 #endif -#endif #include @@ -85,9 +84,6 @@ typedef char bool; #endif #ifdef _WIN32 -#if defined(HAVE__CHMOD) -#define chmod _chmod -#endif #if defined(HAVE__CLOSE) #define close _close #endif @@ -101,7 +97,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/src/Common/libzip/config.h b/src/Common/libzip/config.h index 1edd29ba..cb76150c 100644 --- a/src/Common/libzip/config.h +++ b/src/Common/libzip/config.h @@ -5,68 +5,72 @@ #endif /* BEGIN DEFINES */ /* #undef HAVE___PROGNAME */ -#define HAVE__CHMOD #define HAVE__CLOSE #define HAVE__DUP #define HAVE__FDOPEN #define HAVE__FILENO -#define HAVE__OPEN #define HAVE__SETMODE +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define HAVE__SNPRINTF +#else /* #undef HAVE__SNPRINTF */ +#endif #define HAVE__STRDUP #define HAVE__STRICMP #define HAVE__STRTOI64 #define HAVE__STRTOUI64 -#define HAVE__UMASK +/* #undef HAVE__UMASK */ #define HAVE__UNLINK +/* #undef HAVE_ARC4RANDOM */ /* #undef HAVE_CLONEFILE */ /* #undef HAVE_COMMONCRYPTO */ -/* #undef HAVE_CRYPTO */ +#define HAVE_CRYPTO /* #undef HAVE_FICLONERANGE */ #define HAVE_FILENO +/* #undef HAVE_FCHMOD */ /* #undef HAVE_FSEEKO */ /* #undef HAVE_FTELLO */ /* #undef HAVE_GETPROGNAME */ /* #undef HAVE_GNUTLS */ /* #undef HAVE_LIBBZ2 */ -#define HAVE_OPEN -/* #undef HAVE_OPENSSL */ +/* #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 +#if defined(_MSC_VER) && _MSC_VER < 1900 /* #undef HAVE_SNPRINTF */ -/* #undef HAVE_SSIZE_T_LIBZIP */ +#else +#define HAVE_SNPRINTF +#endif /* #undef HAVE_STRCASECMP */ #define HAVE_STRDUP #define HAVE_STRICMP +#if defined(_MSC_VER) && _MSC_VER < 1800 /* #undef HAVE_STRTOLL */ /* #undef HAVE_STRTOULL */ +#else +#define HAVE_STRTOLL +#define HAVE_STRTOULL +#endif /* #undef HAVE_STRUCT_TM_TM_ZONE */ +#if defined(_MSC_VER) && _MSC_VER < 1800 /* #undef HAVE_STDBOOL_H */ +#else +#define HAVE_STDBOOL_H +#endif /* #undef HAVE_STRINGS_H */ /* #undef HAVE_UNISTD_H */ -#define __INT8_LIBZIP 1 -#define INT8_T_LIBZIP 1 -#define UINT8_T_LIBZIP 1 -#define __INT16_LIBZIP 2 -#define INT16_T_LIBZIP 2 -#define UINT16_T_LIBZIP 2 -#define __INT32_LIBZIP 4 -#define INT32_T_LIBZIP 4 -#define UINT32_T_LIBZIP 4 -#define __INT64_LIBZIP 8 -#define INT64_T_LIBZIP 8 -#define UINT64_T_LIBZIP 8 -#define SHORT_LIBZIP 2 -#define INT_LIBZIP 4 -#define LONG_LIBZIP 4 -#define LONG_LONG_LIBZIP 8 +#define HAVE_WINDOWS_CRYPTO #define SIZEOF_OFF_T 4 #ifdef _WIN64 -#define SIZE_T_LIBZIP 8 +#define SIZEOF_SIZE_T 8 #else -#define SIZE_T_LIBZIP 4 +#define SIZEOF_SIZE_T 4 #endif -/* #undef SSIZE_T_LIBZIP */ /* #undef HAVE_DIRENT_H */ /* #undef HAVE_FTS_H */ /* #undef HAVE_NDIR_H */ @@ -76,18 +80,6 @@ #define HAVE_SHARED /* END DEFINES */ #define PACKAGE "libzip" -#define VERSION "1.7.3" - -#ifndef HAVE_SSIZE_T_LIBZIP -# if SIZE_T_LIBZIP == INT_LIBZIP -typedef int ssize_t; -# elif SIZE_T_LIBZIP == LONG_LIBZIP -typedef long ssize_t; -# elif SIZE_T_LIBZIP == LONG_LONG_LIBZIP -typedef long long ssize_t; -# else -#error no suitable type for ssize_t found -# endif -#endif +#define VERSION "1.9.2" #endif /* HAD_CONFIG_H */ diff --git a/src/Common/libzip/zip.h b/src/Common/libzip/zip.h index ba0b6ba2..61003fd4 100644 --- a/src/Common/libzip/zip.h +++ b/src/Common/libzip/zip.h @@ -3,10 +3,10 @@ /* zip.h -- exported 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -45,9 +45,13 @@ extern "C" { #include #ifndef ZIP_EXTERN -#ifndef ZIP_STATIC +#if defined(ZIP_DLL) && !defined(ZIP_STATIC) #ifdef _WIN32 +#ifdef BUILDING_LIBZIP +#define ZIP_EXTERN __declspec(dllexport) +#else #define ZIP_EXTERN __declspec(dllimport) +#endif #elif defined(__GNUC__) && __GNUC__ >= 4 #define ZIP_EXTERN __attribute__((visibility("default"))) #else @@ -58,9 +62,6 @@ extern "C" { #endif #endif -#define _Nullable -#define _Nonnull - #include #include #include @@ -126,7 +127,7 @@ extern "C" { #define ZIP_ER_INVAL 18 /* N Invalid argument */ #define ZIP_ER_NOZIP 19 /* N Not a zip archive */ #define ZIP_ER_INTERNAL 20 /* N Internal error */ -#define ZIP_ER_INCONS 21 /* N Zip archive inconsistent */ +#define ZIP_ER_INCONS 21 /* L Zip archive inconsistent */ #define ZIP_ER_REMOVE 22 /* S Can't remove file */ #define ZIP_ER_DELETED 23 /* N Entry has been deleted */ #define ZIP_ER_ENCRNOTSUPP 24 /* N Encryption method not supported */ @@ -141,9 +142,10 @@ extern "C" { /* type of system error value */ -#define ZIP_ET_NONE 0 /* sys_err unused */ -#define ZIP_ET_SYS 1 /* sys_err is errno */ -#define ZIP_ET_ZLIB 2 /* sys_err is zlib error code */ +#define ZIP_ET_NONE 0 /* sys_err unused */ +#define ZIP_ET_SYS 1 /* sys_err is errno */ +#define ZIP_ET_ZLIB 2 /* sys_err is zlib error code */ +#define ZIP_ET_LIBZIP 3 /* sys_err is libzip error code */ /* compression methods */ @@ -166,7 +168,9 @@ extern "C" { /* 15-17 - Reserved by PKWARE */ #define ZIP_CM_TERSE 18 /* compressed using IBM TERSE (new) */ #define ZIP_CM_LZ77 19 /* IBM LZ77 z Architecture (PFS) */ +/* 20 - old value for Zstandard */ #define ZIP_CM_LZMA2 33 +#define ZIP_CM_ZSTD 93 /* Zstandard compressed data */ #define ZIP_CM_XZ 95 /* XZ compressed data */ #define ZIP_CM_JPEG 96 /* Compressed Jpeg data */ #define ZIP_CM_WAVPACK 97 /* WavPack compressed data */ @@ -242,6 +246,8 @@ typedef enum zip_source_cmd zip_source_cmd_t; #define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd) (((zip_int64_t)1) << (cmd)) +#define ZIP_SOURCE_CHECK_SUPPORTED(supported, cmd) (((supported) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd)) != 0) + /* clang-format off */ #define ZIP_SOURCE_SUPPORTS_READABLE (ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_OPEN) \ @@ -397,6 +403,7 @@ ZIP_EXTERN const zip_uint8_t *_Nullable zip_file_extra_field_get_by_id(zip_t *_N ZIP_EXTERN const char *_Nullable zip_file_get_comment(zip_t *_Nonnull, zip_uint64_t, zip_uint32_t *_Nullable, zip_flags_t); ZIP_EXTERN zip_error_t *_Nonnull zip_file_get_error(zip_file_t *_Nonnull); ZIP_EXTERN int zip_file_get_external_attributes(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint8_t *_Nullable, zip_uint32_t *_Nullable); +ZIP_EXTERN int zip_file_is_seekable(zip_file_t *_Nonnull); ZIP_EXTERN int zip_file_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull, zip_flags_t); ZIP_EXTERN int zip_file_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull, zip_flags_t); ZIP_EXTERN int zip_file_set_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, zip_uint16_t, zip_flags_t); @@ -463,8 +470,10 @@ ZIP_EXTERN zip_source_t *zip_source_win32handle_create(void *, zip_uint64_t, zip ZIP_EXTERN zip_source_t *zip_source_win32w(zip_t *, const wchar_t *, zip_uint64_t, zip_int64_t); ZIP_EXTERN zip_source_t *zip_source_win32w_create(const wchar_t *, zip_uint64_t, zip_int64_t, zip_error_t *); #endif +ZIP_EXTERN zip_source_t *_Nullable zip_source_window_create(zip_source_t *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable); ZIP_EXTERN zip_int64_t zip_source_write(zip_source_t *_Nonnull, const void *_Nullable, zip_uint64_t); ZIP_EXTERN zip_source_t *_Nullable zip_source_zip(zip_t *_Nonnull, zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t); +ZIP_EXTERN zip_source_t *_Nullable zip_source_zip_create(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable); ZIP_EXTERN int zip_stat(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t, zip_stat_t *_Nonnull); ZIP_EXTERN int zip_stat_index(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_stat_t *_Nonnull); ZIP_EXTERN void zip_stat_init(zip_stat_t *_Nonnull); diff --git a/src/Common/libzip/zip_add.c b/src/Common/libzip/zip_add.c index 19542357..9770139d 100644 --- a/src/Common/libzip/zip_add.c +++ b/src/Common/libzip/zip_add.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_add_dir.c b/src/Common/libzip/zip_add_dir.c index 88fcf53a..c31fea36 100644 --- a/src/Common/libzip/zip_add_dir.c +++ b/src/Common/libzip/zip_add_dir.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/src/Common/libzip/zip_add_entry.c b/src/Common/libzip/zip_add_entry.c index f52e0b5c..bf12dd54 100644 --- a/src/Common/libzip/zip_add_entry.c +++ b/src/Common/libzip/zip_add_entry.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_algorithm_bzip2.c b/src/Common/libzip/zip_algorithm_bzip2.c new file mode 100644 index 00000000..c79cb8aa --- /dev/null +++ b/src/Common/libzip/zip_algorithm_bzip2.c @@ -0,0 +1,285 @@ +/* + zip_algorithm_bzip2.c -- bzip2 (de)compression routines + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#include +#include +#include + +struct ctx { + zip_error_t *error; + bool compress; + int compression_flags; + bool end_of_input; + bz_stream zstr; +}; + + +static zip_uint64_t +maximum_compressed_size(zip_uint64_t uncompressed_size) { + zip_uint64_t compressed_size = (zip_uint64_t)((double)uncompressed_size * 1.006); + + 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) { + 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 = 9; + } + ctx->end_of_input = false; + + ctx->zstr.bzalloc = NULL; + ctx->zstr.bzfree = NULL; + ctx->zstr.opaque = NULL; + + return ctx; +} + + +static void * +compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) { + return allocate(true, compression_flags, error); +} + + +static void * +decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) { + return allocate(false, compression_flags, error); +} + + +static void +deallocate(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + free(ctx); +} + + +static zip_uint16_t +general_purpose_bit_flags(void *ud) { + return 0; +} + + +static int +map_error(int ret) { + switch (ret) { + case BZ_FINISH_OK: + case BZ_FLUSH_OK: + case BZ_OK: + case BZ_RUN_OK: + case BZ_STREAM_END: + return ZIP_ER_OK; + + case BZ_DATA_ERROR: + case BZ_DATA_ERROR_MAGIC: + case BZ_UNEXPECTED_EOF: + return ZIP_ER_COMPRESSED_DATA; + + case BZ_MEM_ERROR: + return ZIP_ER_MEMORY; + + case BZ_PARAM_ERROR: + return ZIP_ER_INVAL; + + case BZ_CONFIG_ERROR: /* actually, bzip2 miscompiled */ + case BZ_IO_ERROR: + case BZ_OUTBUFF_FULL: + case BZ_SEQUENCE_ERROR: + return ZIP_ER_INTERNAL; + + default: + return ZIP_ER_INTERNAL; + } +} + +static bool +start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) { + struct ctx *ctx = (struct ctx *)ud; + int ret; + + ctx->zstr.avail_in = 0; + ctx->zstr.next_in = NULL; + ctx->zstr.avail_out = 0; + ctx->zstr.next_out = NULL; + + if (ctx->compress) { + ret = BZ2_bzCompressInit(&ctx->zstr, ctx->compression_flags, 0, 30); + } + else { + ret = BZ2_bzDecompressInit(&ctx->zstr, 0, 0); + } + + if (ret != BZ_OK) { + zip_error_set(ctx->error, map_error(ret), 0); + return false; + } + + return true; +} + + +static bool +end(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + int err; + + if (ctx->compress) { + err = BZ2_bzCompressEnd(&ctx->zstr); + } + else { + err = BZ2_bzDecompressEnd(&ctx->zstr); + } + + if (err != BZ_OK) { + zip_error_set(ctx->error, map_error(err), 0); + return false; + } + + return true; +} + + +static bool +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; + } + + ctx->zstr.avail_in = (unsigned int)length; + ctx->zstr.next_in = (char *)data; + + return true; +} + + +static void +end_of_input(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + ctx->end_of_input = true; +} + + +static zip_compression_status_t +process(void *ud, zip_uint8_t *data, zip_uint64_t *length) { + struct ctx *ctx = (struct ctx *)ud; + + int ret; + + if (ctx->zstr.avail_in == 0 && !ctx->end_of_input) { + *length = 0; + return ZIP_COMPRESSION_NEED_DATA; + } + + ctx->zstr.avail_out = (unsigned int)ZIP_MIN(UINT_MAX, *length); + ctx->zstr.next_out = (char *)data; + + if (ctx->compress) { + ret = BZ2_bzCompress(&ctx->zstr, ctx->end_of_input ? BZ_FINISH : BZ_RUN); + } + else { + ret = BZ2_bzDecompress(&ctx->zstr); + } + + *length = *length - ctx->zstr.avail_out; + + switch (ret) { + case BZ_FINISH_OK: /* compression */ + return ZIP_COMPRESSION_OK; + + case BZ_OK: /* decompression */ + case BZ_RUN_OK: /* compression */ + if (ctx->zstr.avail_in == 0) { + return ZIP_COMPRESSION_NEED_DATA; + } + return ZIP_COMPRESSION_OK; + + case BZ_STREAM_END: + return ZIP_COMPRESSION_END; + + default: + zip_error_set(ctx->error, map_error(ret), 0); + return ZIP_COMPRESSION_ERROR; + } +} + +/* clang-format off */ + +zip_compression_algorithm_t zip_algorithm_bzip2_compress = { + maximum_compressed_size, + compress_allocate, + deallocate, + general_purpose_bit_flags, + 46, + start, + end, + input, + end_of_input, + process +}; + + +zip_compression_algorithm_t zip_algorithm_bzip2_decompress = { + maximum_compressed_size, + decompress_allocate, + deallocate, + general_purpose_bit_flags, + 46, + start, + end, + input, + end_of_input, + process +}; + +/* clang-format on */ diff --git a/src/Common/libzip/zip_algorithm_deflate.c b/src/Common/libzip/zip_algorithm_deflate.c index d28a1ac5..03250ef9 100644 --- a/src/Common/libzip/zip_algorithm_deflate.c +++ b/src/Common/libzip/zip_algorithm_deflate.c @@ -1,9 +1,9 @@ /* zip_algorithm_deflate.c -- deflate (de)compression routines - Copyright (C) 2017-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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_algorithm_xz.c b/src/Common/libzip/zip_algorithm_xz.c new file mode 100644 index 00000000..d8f4266a --- /dev/null +++ b/src/Common/libzip/zip_algorithm_xz.c @@ -0,0 +1,406 @@ +/* + zip_algorithm_xz.c -- LZMA/XZ (de)compression routines + Bazed on zip_algorithm_deflate.c -- deflate (de)compression routines + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#include +#include +#include +#include + +enum header_state { INCOMPLETE, OUTPUT, DONE }; + +#define HEADER_BYTES_ZIP 9 +#define HEADER_MAGIC_LENGTH 4 +#define HEADER_MAGIC1_OFFSET 0 +#define HEADER_MAGIC2_OFFSET 2 +#define HEADER_SIZE_OFFSET 9 +#define HEADER_SIZE_LENGTH 8 +#define HEADER_PARAMETERS_LENGTH 5 +#define HEADER_LZMA_ALONE_LENGTH (HEADER_PARAMETERS_LENGTH + HEADER_SIZE_LENGTH) + +struct ctx { + zip_error_t *error; + bool compress; + zip_uint32_t compression_flags; + bool end_of_input; + lzma_stream zstr; + zip_uint16_t method; + /* header member is used for converting from zip to "lzma alone" + * format + * + * "lzma alone" file format starts with: + * 5 bytes lzma parameters + * 8 bytes uncompressed size + * compressed data + * + * zip archive on-disk format starts with + * 4 bytes magic (first two bytes vary, e.g. 0x0914 or 0x1002, next bytes are 0x0500) + * 5 bytes lzma parameters + * compressed data + * + * we read the data into a header of the form + * 4 bytes magic + * 5 bytes lzma parameters + * 8 bytes uncompressed size + */ + zip_uint8_t header[HEADER_MAGIC_LENGTH + HEADER_LZMA_ALONE_LENGTH]; + zip_uint8_t header_bytes_offset; + enum header_state header_state; + zip_uint64_t uncompresssed_size; +}; + + +static zip_uint64_t +maximum_compressed_size(zip_uint64_t uncompressed_size) { + /* + According to https://sourceforge.net/p/sevenzip/discussion/45797/thread/b6bd62f8/ + + 1) you can use + outSize = 1.10 * originalSize + 64 KB. + in most cases outSize is less then 1.02 from originalSize. + 2) You can try LZMA2, where + outSize can be = 1.001 * originalSize + 1 KB. + */ + /* 13 bytes added for lzma alone header */ + zip_uint64_t compressed_size = (zip_uint64_t)((double)uncompressed_size * 1.1) + 64 * 1024 + 13; + + if (compressed_size < uncompressed_size) { + return ZIP_UINT64_MAX; + } + return compressed_size; +} + + +static void * +allocate(bool compress, int compression_flags, zip_error_t *error, zip_uint16_t method) { + struct ctx *ctx; + + if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + ctx->error = error; + ctx->compress = compress; + if (compression_flags < 0 || compression_flags > 9) { + ctx->compression_flags = 6; /* default value */ + } else { + ctx->compression_flags = (zip_uint32_t)compression_flags; + } + ctx->compression_flags |= LZMA_PRESET_EXTREME; + ctx->end_of_input = false; + memset(ctx->header, 0, sizeof(ctx->header)); + ctx->header_bytes_offset = 0; + if (ZIP_CM_LZMA) { + ctx->header_state = INCOMPLETE; + } + else { + ctx->header_state = DONE; + } + memset(&ctx->zstr, 0, sizeof(ctx->zstr)); + ctx->method = method; + return ctx; +} + + +static void * +compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) { + return allocate(true, compression_flags, error, method); +} + + +static void * +decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) { + return allocate(false, compression_flags, error, method); +} + + +static void +deallocate(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + free(ctx); +} + + +static zip_uint16_t +general_purpose_bit_flags(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + if (!ctx->compress) { + return 0; + } + + if (ctx->method == ZIP_CM_LZMA) { + /* liblzma always returns an EOS/EOPM marker, see + * https://sourceforge.net/p/lzmautils/discussion/708858/thread/84c5dbb9/#a5e4/3764 */ + return 1 << 1; + } + return 0; +} + +static int +map_error(lzma_ret ret) { + switch (ret) { + case LZMA_DATA_ERROR: + case LZMA_UNSUPPORTED_CHECK: + return ZIP_ER_COMPRESSED_DATA; + + case LZMA_MEM_ERROR: + return ZIP_ER_MEMORY; + + case LZMA_OPTIONS_ERROR: + return ZIP_ER_INVAL; + + default: + return ZIP_ER_INTERNAL; + } +} + + +static bool +start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) { + struct ctx *ctx = (struct ctx *)ud; + lzma_ret ret; + + lzma_options_lzma opt_lzma; + lzma_lzma_preset(&opt_lzma, ctx->compression_flags); + lzma_filter filters[] = { + {.id = (ctx->method == ZIP_CM_LZMA ? LZMA_FILTER_LZMA1 : LZMA_FILTER_LZMA2), .options = &opt_lzma}, + {.id = LZMA_VLI_UNKNOWN, .options = NULL}, + }; + + ctx->zstr.avail_in = 0; + ctx->zstr.next_in = NULL; + ctx->zstr.avail_out = 0; + ctx->zstr.next_out = NULL; + + if (ctx->compress) { + if (ctx->method == ZIP_CM_LZMA) + ret = lzma_alone_encoder(&ctx->zstr, filters[0].options); + else + ret = lzma_stream_encoder(&ctx->zstr, filters, LZMA_CHECK_CRC64); + } + else { + if (ctx->method == ZIP_CM_LZMA) + ret = lzma_alone_decoder(&ctx->zstr, UINT64_MAX); + else + ret = lzma_stream_decoder(&ctx->zstr, UINT64_MAX, LZMA_CONCATENATED); + } + + if (ret != LZMA_OK) { + zip_error_set(ctx->error, map_error(ret), 0); + return false; + } + + /* If general purpose bits 1 & 2 are both zero, write real uncompressed size in header. */ + if ((attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) && (attributes->general_purpose_bit_mask & 0x6) == 0x6 && (attributes->general_purpose_bit_flags & 0x06) == 0 && (st->valid & ZIP_STAT_SIZE)) { + ctx->uncompresssed_size = st->size; + } + else { + ctx->uncompresssed_size = ZIP_UINT64_MAX; + } + + return true; +} + + +static bool +end(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + lzma_end(&ctx->zstr); + return true; +} + + +static bool +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; + } + + /* For decompression of LZMA1: Have we read the full "lzma alone" header yet? */ + if (ctx->method == ZIP_CM_LZMA && !ctx->compress && ctx->header_state == INCOMPLETE) { + /* if not, get more of the data */ + zip_uint8_t got = (zip_uint8_t)ZIP_MIN(HEADER_BYTES_ZIP - ctx->header_bytes_offset, length); + memcpy(ctx->header + ctx->header_bytes_offset, data, got); + ctx->header_bytes_offset += got; + length -= got; + data += got; + /* Do we have a complete header now? */ + if (ctx->header_bytes_offset == HEADER_BYTES_ZIP) { + Bytef empty_buffer[1]; + zip_buffer_t *buffer; + /* check magic */ + if (ctx->header[HEADER_MAGIC2_OFFSET] != 0x05 || ctx->header[HEADER_MAGIC2_OFFSET + 1] != 0x00) { + /* magic does not match */ + zip_error_set(ctx->error, ZIP_ER_COMPRESSED_DATA, 0); + return false; + } + /* set size of uncompressed data in "lzma alone" header to "unknown" */ + if ((buffer = _zip_buffer_new(ctx->header + HEADER_SIZE_OFFSET, HEADER_SIZE_LENGTH)) == NULL) { + zip_error_set(ctx->error, ZIP_ER_MEMORY, 0); + return false; + } + _zip_buffer_put_64(buffer, ctx->uncompresssed_size); + _zip_buffer_free(buffer); + /* Feed header into "lzma alone" decoder, for + * initialization; this should not produce output. */ + ctx->zstr.next_in = (void *)(ctx->header + HEADER_MAGIC_LENGTH); + ctx->zstr.avail_in = HEADER_LZMA_ALONE_LENGTH; + ctx->zstr.total_in = 0; + ctx->zstr.next_out = empty_buffer; + ctx->zstr.avail_out = sizeof(*empty_buffer); + ctx->zstr.total_out = 0; + /* this just initializes the decoder and does not produce output, so it consumes the complete header */ + if (lzma_code(&ctx->zstr, LZMA_RUN) != LZMA_OK || ctx->zstr.total_out > 0) { + zip_error_set(ctx->error, ZIP_ER_COMPRESSED_DATA, 0); + return false; + } + ctx->header_state = DONE; + } + } + ctx->zstr.avail_in = (uInt)length; + ctx->zstr.next_in = (Bytef *)data; + + return true; +} + + +static void +end_of_input(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + ctx->end_of_input = true; +} + + +static zip_compression_status_t +process(void *ud, zip_uint8_t *data, zip_uint64_t *length) { + struct ctx *ctx = (struct ctx *)ud; + lzma_ret ret; + /* for compression of LZMA1 */ + if (ctx->method == ZIP_CM_LZMA && ctx->compress) { + if (ctx->header_state == INCOMPLETE) { + /* write magic to output buffer */ + ctx->header[0] = 0x09; + ctx->header[1] = 0x14; + ctx->header[2] = 0x05; + ctx->header[3] = 0x00; + /* generate lzma parameters into output buffer */ + ctx->zstr.avail_out = HEADER_LZMA_ALONE_LENGTH; + ctx->zstr.next_out = ctx->header + HEADER_MAGIC_LENGTH; + ret = lzma_code(&ctx->zstr, LZMA_RUN); + if (ret != LZMA_OK || ctx->zstr.avail_out != 0) { + /* assume that the whole header will be provided with the first call to lzma_code */ + return ZIP_COMPRESSION_ERROR; + } + ctx->header_state = OUTPUT; + } + if (ctx->header_state == OUTPUT) { + /* write header */ + zip_uint8_t write_len = (zip_uint8_t)ZIP_MIN(HEADER_BYTES_ZIP - ctx->header_bytes_offset, *length); + memcpy(data, ctx->header + ctx->header_bytes_offset, write_len); + ctx->header_bytes_offset += write_len; + *length = write_len; + if (ctx->header_bytes_offset == HEADER_BYTES_ZIP) { + ctx->header_state = DONE; + } + return ZIP_COMPRESSION_OK; + } + } + + ctx->zstr.avail_out = (uInt)ZIP_MIN(UINT_MAX, *length); + ctx->zstr.next_out = (Bytef *)data; + + ret = lzma_code(&ctx->zstr, ctx->end_of_input ? LZMA_FINISH : LZMA_RUN); + *length = *length - ctx->zstr.avail_out; + + switch (ret) { + case LZMA_OK: + return ZIP_COMPRESSION_OK; + + case LZMA_STREAM_END: + return ZIP_COMPRESSION_END; + + case LZMA_BUF_ERROR: + if (ctx->zstr.avail_in == 0) { + return ZIP_COMPRESSION_NEED_DATA; + } + + /* fallthrough */ + default: + zip_error_set(ctx->error, map_error(ret), 0); + return ZIP_COMPRESSION_ERROR; + } +} + +/* Version Required should be set to 63 (6.3) because this compression + method was only defined in appnote.txt version 6.3.8, but Winzip + does not unpack it if the value is not 20. */ + +/* clang-format off */ + +zip_compression_algorithm_t zip_algorithm_xz_compress = { + maximum_compressed_size, + compress_allocate, + deallocate, + general_purpose_bit_flags, + 20, + start, + end, + input, + end_of_input, + process +}; + + +zip_compression_algorithm_t zip_algorithm_xz_decompress = { + maximum_compressed_size, + decompress_allocate, + deallocate, + general_purpose_bit_flags, + 20, + start, + end, + input, + end_of_input, + process +}; + +/* clang-format on */ diff --git a/src/Common/libzip/zip_algorithm_zstd.c b/src/Common/libzip/zip_algorithm_zstd.c new file mode 100644 index 00000000..7a08fbbc --- /dev/null +++ b/src/Common/libzip/zip_algorithm_zstd.c @@ -0,0 +1,294 @@ +/* + zip_algorithm_zstd.c -- zstd (de)compression routines + Copyright (C) 2020-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#include +#include +#include +#include + +struct ctx { + zip_error_t *error; + bool compress; + int compression_flags; + bool end_of_input; + ZSTD_DStream *zdstream; + ZSTD_CStream *zcstream; + ZSTD_outBuffer out; + ZSTD_inBuffer in; +}; + +static zip_uint64_t +maximum_compressed_size(zip_uint64_t uncompressed_size) { + return ZSTD_compressBound(uncompressed_size); +} + + +static void * +allocate(bool compress, int compression_flags, zip_error_t *error) { + struct ctx *ctx; + + /* 0: let zstd choose */ + if (compression_flags < ZSTD_minCLevel() || compression_flags > ZSTD_maxCLevel()) { + compression_flags = 0; + } + + if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) { + return NULL; + } + + ctx->error = error; + ctx->compress = compress; + ctx->compression_flags = compression_flags; + ctx->end_of_input = false; + + ctx->zdstream = NULL; + ctx->zcstream = NULL; + ctx->in.src = NULL; + ctx->in.pos = 0; + ctx->in.size = 0; + ctx->out.dst = NULL; + ctx->out.pos = 0; + ctx->out.size = 0; + + return ctx; +} + + +static void * +compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) { + return allocate(true, compression_flags, error); +} + + +static void * +decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) { + return allocate(false, compression_flags, error); +} + + +static void +deallocate(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + free(ctx); +} + + +static zip_uint16_t +general_purpose_bit_flags(void *ud) { + /* struct ctx *ctx = (struct ctx *)ud; */ + return 0; +} + +static int +map_error(size_t ret) { + switch (ret) { + case ZSTD_error_no_error: + return ZIP_ER_OK; + + case ZSTD_error_corruption_detected: + case ZSTD_error_checksum_wrong: + case ZSTD_error_dictionary_corrupted: + case ZSTD_error_dictionary_wrong: + return ZIP_ER_COMPRESSED_DATA; + + case ZSTD_error_memory_allocation: + return ZIP_ER_MEMORY; + + case ZSTD_error_parameter_unsupported: + case ZSTD_error_parameter_outOfBound: + return ZIP_ER_INVAL; + + default: + return ZIP_ER_INTERNAL; + } +} + + +static bool +start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) { + struct ctx *ctx = (struct ctx *)ud; + ctx->in.src = NULL; + ctx->in.pos = 0; + ctx->in.size = 0; + ctx->out.dst = NULL; + ctx->out.pos = 0; + ctx->out.size = 0; + if (ctx->compress) { + size_t ret; + ctx->zcstream = ZSTD_createCStream(); + if (ctx->zcstream == NULL) { + zip_error_set(ctx->error, ZIP_ER_MEMORY, 0); + return false; + } + ret = ZSTD_initCStream(ctx->zcstream, ctx->compression_flags); + if (ZSTD_isError(ret)) { + zip_error_set(ctx->error, ZIP_ER_ZLIB, map_error(ret)); + return false; + } + } + else { + ctx->zdstream = ZSTD_createDStream(); + if (ctx->zdstream == NULL) { + zip_error_set(ctx->error, ZIP_ER_MEMORY, 0); + return false; + } + } + + return true; +} + + +static bool +end(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + size_t ret; + + if (ctx->compress) { + ret = ZSTD_freeCStream(ctx->zcstream); + ctx->zcstream = NULL; + } + else { + ret = ZSTD_freeDStream(ctx->zdstream); + ctx->zdstream = NULL; + } + + if (ZSTD_isError(ret)) { + zip_error_set(ctx->error, map_error(ret), 0); + return false; + } + + return true; +} + + +static bool +input(void *ud, zip_uint8_t *data, zip_uint64_t length) { + struct ctx *ctx = (struct ctx *)ud; + if (length > SIZE_MAX || ctx->in.pos != ctx->in.size) { + zip_error_set(ctx->error, ZIP_ER_INVAL, 0); + return false; + } + ctx->in.src = (const void *)data; + ctx->in.size = (size_t)length; + ctx->in.pos = 0; + return true; +} + + +static void +end_of_input(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + ctx->end_of_input = true; +} + + +static zip_compression_status_t +process(void *ud, zip_uint8_t *data, zip_uint64_t *length) { + struct ctx *ctx = (struct ctx *)ud; + + size_t ret; + + if (ctx->in.pos == ctx->in.size && !ctx->end_of_input) { + *length = 0; + return ZIP_COMPRESSION_NEED_DATA; + } + + ctx->out.dst = data; + ctx->out.pos = 0; + ctx->out.size = ZIP_MIN(SIZE_MAX, *length); + + if (ctx->compress) { + if (ctx->in.pos == ctx->in.size && ctx->end_of_input) { + ret = ZSTD_endStream(ctx->zcstream, &ctx->out); + if (ret == 0) { + *length = ctx->out.pos; + return ZIP_COMPRESSION_END; + } + } + else { + ret = ZSTD_compressStream(ctx->zcstream, &ctx->out, &ctx->in); + } + } + else { + ret = ZSTD_decompressStream(ctx->zdstream, &ctx->out, &ctx->in); + } + if (ZSTD_isError(ret)) { + zip_error_set(ctx->error, map_error(ret), 0); + return ZIP_COMPRESSION_ERROR; + } + + *length = ctx->out.pos; + if (ctx->in.pos == ctx->in.size) { + return ZIP_COMPRESSION_NEED_DATA; + } + + return ZIP_COMPRESSION_OK; +} + +/* Version Required should be set to 63 (6.3) because this compression + method was only defined in appnote.txt version 6.3.7, but Winzip + does not unpack it if the value is not 20. */ + +/* clang-format off */ + +zip_compression_algorithm_t zip_algorithm_zstd_compress = { + maximum_compressed_size, + compress_allocate, + deallocate, + general_purpose_bit_flags, + 20, + start, + end, + input, + end_of_input, + process +}; + + +zip_compression_algorithm_t zip_algorithm_zstd_decompress = { + maximum_compressed_size, + decompress_allocate, + deallocate, + general_purpose_bit_flags, + 20, + start, + end, + input, + end_of_input, + process +}; + +/* clang-format on */ diff --git a/src/Common/libzip/zip_buffer.c b/src/Common/libzip/zip_buffer.c index 8c24b27e..a353ce06 100644 --- a/src/Common/libzip/zip_buffer.c +++ b/src/Common/libzip/zip_buffer.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_close.c b/src/Common/libzip/zip_close.c index 816fcefa..8d1a2aa8 100644 --- a/src/Common/libzip/zip_close.c +++ b/src/Common/libzip/zip_close.c @@ -1,9 +1,9 @@ /* zip_close.c -- close zip archive and update changes - Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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 (j >= survivors) { - free(filelist); - zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); - return -1; - } - - filelist[j].idx = i; - j++; + 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; + } + + 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; - - 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 == 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; + } + } } 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; - - 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; - - 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)); - - /* 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) { + 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; + } + + i = filelist[j].idx; + entry = za->entry + i; + + 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)); + + /* 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); + 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 (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; - } - } - } + 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; - - if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) { - zip_uint64_t max_size; - - 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; - - 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; + 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_compressed_size; + zip_uint16_t compression_method = ZIP_CM_ACTUAL(de->comp_method); + + 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); + } + } + + 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,143 @@ 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; - - 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; - } - - zip_source_free(src_final); - src_final = src_tmp; + zip_encryption_implementation impl; + const char *password = NULL; + + 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 (de->encryption_method == ZIP_EM_TRAD_PKWARE) { + de->bitflags |= ZIP_GPBF_DATA_DESCRIPTOR; + + /* PKWare encryption uses last_mod, make sure it gets the right value. */ + if (de->changed & ZIP_DIRENT_LAST_MOD) { + zip_stat_t st_mtime; + zip_stat_init(&st_mtime); + st_mtime.valid = ZIP_STAT_MTIME; + st_mtime.mtime = de->last_mod; + if ((src_tmp = _zip_source_window_new(src_final, 0, -1, &st_mtime, NULL, NULL, 0, &za->error)) == NULL) { + zip_source_free(src_final); + return -1; + } + zip_source_free(src_final); + src_final = src_tmp; + } + } + + 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; + } + + 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 +529,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 +559,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 +595,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 +635,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 +660,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 +685,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/src/Common/libzip/zip_crypto.h b/src/Common/libzip/zip_crypto.h new file mode 100644 index 00000000..0d74d1a4 --- /dev/null +++ b/src/Common/libzip/zip_crypto.h @@ -0,0 +1,54 @@ +/* + zip_crypto.h -- crypto definitions + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HAD_ZIP_CRYPTO_H +#define HAD_ZIP_CRYPTO_H + +#define ZIP_CRYPTO_SHA1_LENGTH 20 +#define ZIP_CRYPTO_AES_BLOCK_LENGTH 16 + +#if defined(HAVE_WINDOWS_CRYPTO) +#include "zip_crypto_win.h" +#elif defined(HAVE_COMMONCRYPTO) +#include "zip_crypto_commoncrypto.h" +#elif defined(HAVE_GNUTLS) +#include "zip_crypto_gnutls.h" +#elif defined(HAVE_OPENSSL) +#include "zip_crypto_openssl.h" +#elif defined(HAVE_MBEDTLS) +#include "zip_crypto_mbedtls.h" +#else +#error "no crypto backend found" +#endif + +#endif /* HAD_ZIP_CRYPTO_H */ diff --git a/src/Common/libzip/zip_crypto_commoncrypto.c b/src/Common/libzip/zip_crypto_commoncrypto.c new file mode 100644 index 00000000..b198be56 --- /dev/null +++ b/src/Common/libzip/zip_crypto_commoncrypto.c @@ -0,0 +1,110 @@ +/* + zip_crypto_commoncrypto.c -- CommonCrypto wrapper. + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include "zipint.h" + +#include "zip_crypto.h" + +#include +#include + +void +_zip_crypto_aes_free(_zip_crypto_aes_t *aes) { + if (aes == NULL) { + return; + } + + CCCryptorRelease(aes); +} + + +bool +_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) { + size_t len; + CCCryptorUpdate(aes, in, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, ZIP_CRYPTO_AES_BLOCK_LENGTH, &len); + return true; +} + + +_zip_crypto_aes_t * +_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) { + _zip_crypto_aes_t *aes; + CCCryptorStatus ret; + + ret = CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES, kCCOptionECBMode, key, key_size / 8, NULL, &aes); + + switch (ret) { + case kCCSuccess: + return aes; + + case kCCMemoryFailure: + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + + case kCCParamError: + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + + default: + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; + } +} + + +void +_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) { + if (hmac == NULL) { + return; + } + + _zip_crypto_clear(hmac, sizeof(*hmac)); + free(hmac); +} + + +_zip_crypto_hmac_t * +_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) { + _zip_crypto_hmac_t *hmac; + + if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + CCHmacInit(hmac, kCCHmacAlgSHA1, secret, secret_length); + + return hmac; +} diff --git a/src/Common/libzip/zip_crypto_commoncrypto.h b/src/Common/libzip/zip_crypto_commoncrypto.h new file mode 100644 index 00000000..01828cc6 --- /dev/null +++ b/src/Common/libzip/zip_crypto_commoncrypto.h @@ -0,0 +1,53 @@ +/* + zip_crypto_commoncrypto.h -- definitions for CommonCrypto wrapper. + Copyright (C) 2018 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HAD_ZIP_CRYPTO_COMMONCRYPTO_H +#define HAD_ZIP_CRYPTO_COMMONCRYPTO_H + +#include + +#define _zip_crypto_aes_t struct _CCCryptor +#define _zip_crypto_hmac_t CCHmacContext + +void _zip_crypto_aes_free(_zip_crypto_aes_t *aes); +bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out); +_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error); + +#define _zip_crypto_hmac(hmac, data, length) (CCHmacUpdate((hmac), (data), (length)), true) +void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac); +_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error); +#define _zip_crypto_hmac_output(hmac, data) (CCHmacFinal((hmac), (data)), true) + +#define _zip_crypto_pbkdf2(key, key_length, salt, salt_length, iterations, output, output_length) (CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)(key), (key_length), (salt), (salt_length), kCCPRFHmacAlgSHA1, (iterations), (output), (output_length)) == kCCSuccess) + +#endif /* HAD_ZIP_CRYPTO_COMMONCRYPTO_H */ diff --git a/src/Common/libzip/zip_crypto_gnutls.c b/src/Common/libzip/zip_crypto_gnutls.c new file mode 100644 index 00000000..1a25aa12 --- /dev/null +++ b/src/Common/libzip/zip_crypto_gnutls.c @@ -0,0 +1,134 @@ +/* + zip_crypto_gnutls.c -- GnuTLS wrapper. + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include "zipint.h" + +#include "zip_crypto.h" + +_zip_crypto_aes_t * +_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) { + _zip_crypto_aes_t *aes; + + if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + aes->key_size = key_size; + + switch (aes->key_size) { + case 128: + nettle_aes128_set_encrypt_key(&aes->ctx.ctx_128, key); + break; + case 192: + nettle_aes192_set_encrypt_key(&aes->ctx.ctx_192, key); + break; + case 256: + nettle_aes256_set_encrypt_key(&aes->ctx.ctx_256, key); + break; + default: + zip_error_set(error, ZIP_ER_INVAL, 0); + free(aes); + return NULL; + } + + return aes; +} + +bool +_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) { + switch (aes->key_size) { + case 128: + nettle_aes128_encrypt(&aes->ctx.ctx_128, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in); + break; + case 192: + nettle_aes192_encrypt(&aes->ctx.ctx_192, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in); + break; + case 256: + nettle_aes256_encrypt(&aes->ctx.ctx_256, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in); + break; + } + + return true; +} + +void +_zip_crypto_aes_free(_zip_crypto_aes_t *aes) { + if (aes == NULL) { + return; + } + + _zip_crypto_clear(aes, sizeof(*aes)); + free(aes); +} + + +_zip_crypto_hmac_t * +_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) { + _zip_crypto_hmac_t *hmac; + + if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if (gnutls_hmac_init(hmac, GNUTLS_MAC_SHA1, secret, secret_length) < 0) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + free(hmac); + return NULL; + } + + return hmac; +} + + +void +_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) { + zip_uint8_t buf[ZIP_CRYPTO_SHA1_LENGTH]; + + if (hmac == NULL) { + return; + } + + gnutls_hmac_deinit(*hmac, buf); + _zip_crypto_clear(hmac, sizeof(*hmac)); + free(hmac); +} + + +ZIP_EXTERN bool +zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { + return gnutls_rnd(GNUTLS_RND_KEY, buffer, length) == 0; +} diff --git a/src/Common/libzip/zip_crypto_gnutls.h b/src/Common/libzip/zip_crypto_gnutls.h new file mode 100644 index 00000000..dc8b97a4 --- /dev/null +++ b/src/Common/libzip/zip_crypto_gnutls.h @@ -0,0 +1,68 @@ +/* + zip_crypto_gnutls.h -- definitions for GnuTLS wrapper. + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HAD_ZIP_CRYPTO_GNUTLS_H +#define HAD_ZIP_CRYPTO_GNUTLS_H + +#define HAVE_SECURE_RANDOM + +#include +#include + +#include + +#include + +typedef struct { + union { + 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; + +#define _zip_crypto_hmac_t gnutls_hmac_hd_t + +void _zip_crypto_aes_free(_zip_crypto_aes_t *aes); +bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out); +_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error); + +#define _zip_crypto_hmac(hmac, data, length) (gnutls_hmac(*(hmac), (data), (length)) == 0) +void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac); +_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error); +#define _zip_crypto_hmac_output(hmac, data) (gnutls_hmac_output(*(hmac), (data)), true) + +#define _zip_crypto_pbkdf2(key, key_length, salt, salt_length, iterations, output, output_length) (pbkdf2_hmac_sha1((key_length), (key), (iterations), (salt_length), (salt), (output_length), (output)), true) + +#endif /* HAD_ZIP_CRYPTO_GNUTLS_H */ diff --git a/src/Common/libzip/zip_crypto_mbedtls.c b/src/Common/libzip/zip_crypto_mbedtls.c new file mode 100644 index 00000000..95ac8990 --- /dev/null +++ b/src/Common/libzip/zip_crypto_mbedtls.c @@ -0,0 +1,162 @@ +/* + zip_crypto_mbedtls.c -- mbed TLS wrapper + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include "zipint.h" + +#include "zip_crypto.h" + +#include +#include +#include + +#include + +_zip_crypto_aes_t * +_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) { + _zip_crypto_aes_t *aes; + + if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + mbedtls_aes_init(aes); + mbedtls_aes_setkey_enc(aes, (const unsigned char *)key, (unsigned int)key_size); + + return aes; +} + +void +_zip_crypto_aes_free(_zip_crypto_aes_t *aes) { + if (aes == NULL) { + return; + } + + mbedtls_aes_free(aes); + free(aes); +} + + +_zip_crypto_hmac_t * +_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) { + _zip_crypto_hmac_t *hmac; + + if (secret_length > INT_MAX) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + mbedtls_md_init(hmac); + + if (mbedtls_md_setup(hmac, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1) != 0) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + free(hmac); + return NULL; + } + + if (mbedtls_md_hmac_starts(hmac, (const unsigned char *)secret, (size_t)secret_length) != 0) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + free(hmac); + return NULL; + } + + return hmac; +} + + +void +_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) { + if (hmac == NULL) { + return; + } + + mbedtls_md_free(hmac); + free(hmac); +} + + +bool +_zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, int iterations, zip_uint8_t *output, zip_uint64_t output_length) { + mbedtls_md_context_t sha1_ctx; + bool ok = true; + + mbedtls_md_init(&sha1_ctx); + + if (mbedtls_md_setup(&sha1_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1) != 0) { + ok = false; + } + + if (ok && mbedtls_pkcs5_pbkdf2_hmac(&sha1_ctx, (const unsigned char *)key, (size_t)key_length, (const unsigned char *)salt, (size_t)salt_length, (unsigned int)iterations, (uint32_t)output_length, (unsigned char *)output) != 0) { + ok = false; + } + + mbedtls_md_free(&sha1_ctx); + return ok; +} + + +typedef struct { + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; +} zip_random_context_t; + +ZIP_EXTERN bool +zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { + static zip_random_context_t *ctx = NULL; + const unsigned char *pers = "zip_crypto_mbedtls"; + + if (!ctx) { + ctx = (zip_random_context_t *)malloc(sizeof(zip_random_context_t)); + if (!ctx) { + return false; + } + mbedtls_entropy_init(&ctx->entropy); + mbedtls_ctr_drbg_init(&ctx->ctr_drbg); + if (mbedtls_ctr_drbg_seed(&ctx->ctr_drbg, mbedtls_entropy_func, &ctx->entropy, pers, strlen(pers)) != 0) { + mbedtls_ctr_drbg_free(&ctx->ctr_drbg); + mbedtls_entropy_free(&ctx->entropy); + free(ctx); + ctx = NULL; + return false; + } + } + + return mbedtls_ctr_drbg_random(&ctx->ctr_drbg, (unsigned char *)buffer, (size_t)length) == 0; +} diff --git a/src/Common/libzip/zip_crypto_mbedtls.h b/src/Common/libzip/zip_crypto_mbedtls.h new file mode 100644 index 00000000..1151fff7 --- /dev/null +++ b/src/Common/libzip/zip_crypto_mbedtls.h @@ -0,0 +1,56 @@ +/* + zip_crypto_mbedtls.h -- definitions for mbedtls wrapper + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HAD_ZIP_CRYPTO_MBEDTLS_H +#define HAD_ZIP_CRYPTO_MBEDTLS_H + +#define HAVE_SECURE_RANDOM + +#include +#include + +#define _zip_crypto_aes_t mbedtls_aes_context +#define _zip_crypto_hmac_t mbedtls_md_context_t + +_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error); +#define _zip_crypto_aes_encrypt_block(aes, in, out) (mbedtls_aes_crypt_ecb((aes), MBEDTLS_AES_ENCRYPT, (in), (out)) == 0) +void _zip_crypto_aes_free(_zip_crypto_aes_t *aes); + +_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error); +#define _zip_crypto_hmac(hmac, data, length) (mbedtls_md_hmac_update((hmac), (data), (length)) == 0) +#define _zip_crypto_hmac_output(hmac, data) (mbedtls_md_hmac_finish((hmac), (data)) == 0) +void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac); + +bool _zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, int iterations, zip_uint8_t *output, zip_uint64_t output_length); + +#endif /* HAD_ZIP_CRYPTO_MBEDTLS_H */ diff --git a/src/Common/libzip/zip_crypto_openssl.c b/src/Common/libzip/zip_crypto_openssl.c new file mode 100644 index 00000000..acbfe4bc --- /dev/null +++ b/src/Common/libzip/zip_crypto_openssl.c @@ -0,0 +1,184 @@ +/* + zip_crypto_openssl.c -- OpenSSL wrapper. + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include "zipint.h" + +#include "zip_crypto.h" + +#include +#include + +#if OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL) +#define USE_OPENSSL_1_0_API +#endif + + +_zip_crypto_aes_t * +_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) { + _zip_crypto_aes_t *aes; + const EVP_CIPHER* cipher_type; + + switch (key_size) { + case 128: + cipher_type = EVP_aes_128_ecb(); + break; + case 192: + cipher_type = EVP_aes_192_ecb(); + break; + case 256: + cipher_type = EVP_aes_256_ecb(); + break; + default: + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; + } + +#ifdef USE_OPENSSL_1_0_API + if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + memset(aes, 0, sizeof(*aes)); +#else + if ((aes = EVP_CIPHER_CTX_new()) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } +#endif + + if (EVP_EncryptInit_ex(aes, cipher_type, NULL, key, NULL) != 1) { +#ifdef USE_OPENSSL_1_0_API + free(aes); +#else + EVP_CIPHER_CTX_free(aes); +#endif + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; + } + + return aes; +} + +void +_zip_crypto_aes_free(_zip_crypto_aes_t *aes) { + if (aes == NULL) { + return; + } + +#ifdef USE_OPENSSL_1_0_API + EVP_CIPHER_CTX_cleanup(aes); + _zip_crypto_clear(aes, sizeof(*aes)); + free(aes); +#else + EVP_CIPHER_CTX_free(aes); +#endif +} + + +bool +_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) { + int len; + if (EVP_EncryptUpdate(aes, out, &len, in, ZIP_CRYPTO_AES_BLOCK_LENGTH) != 1) { + return false; + } + return true; +} + + +_zip_crypto_hmac_t * +_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) { + _zip_crypto_hmac_t *hmac; + + if (secret_length > INT_MAX) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + +#ifdef USE_OPENSSL_1_0_API + if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + HMAC_CTX_init(hmac); +#else + if ((hmac = HMAC_CTX_new()) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } +#endif + + if (HMAC_Init_ex(hmac, secret, (int)secret_length, EVP_sha1(), NULL) != 1) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); +#ifdef USE_OPENSSL_1_0_API + free(hmac); +#else + HMAC_CTX_free(hmac); +#endif + return NULL; + } + + return hmac; +} + + +void +_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) { + if (hmac == NULL) { + return; + } + +#ifdef USE_OPENSSL_1_0_API + HMAC_CTX_cleanup(hmac); + _zip_crypto_clear(hmac, sizeof(*hmac)); + free(hmac); +#else + HMAC_CTX_free(hmac); +#endif +} + + +bool +_zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data) { + unsigned int length; + + return HMAC_Final(hmac, data, &length) == 1; +} + + +ZIP_EXTERN bool +zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { + return RAND_bytes(buffer, length) == 1; +} diff --git a/src/Common/libzip/zip_crypto_openssl.h b/src/Common/libzip/zip_crypto_openssl.h new file mode 100644 index 00000000..030e67ed --- /dev/null +++ b/src/Common/libzip/zip_crypto_openssl.h @@ -0,0 +1,56 @@ +/* + zip_crypto_openssl.h -- definitions for OpenSSL wrapper. + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HAD_ZIP_CRYPTO_OPENSSL_H +#define HAD_ZIP_CRYPTO_OPENSSL_H + +#define HAVE_SECURE_RANDOM + +#include +#include + +#define _zip_crypto_aes_t EVP_CIPHER_CTX +#define _zip_crypto_hmac_t HMAC_CTX + +void _zip_crypto_aes_free(_zip_crypto_aes_t *aes); +bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out); +_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error); + +#define _zip_crypto_hmac(hmac, data, length) (HMAC_Update((hmac), (data), (length)) == 1) +void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac); +_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error); +bool _zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data); + +#define _zip_crypto_pbkdf2(key, key_length, salt, salt_length, iterations, output, output_length) (PKCS5_PBKDF2_HMAC_SHA1((const char *)(key), (key_length), (salt), (salt_length), (iterations), (output_length), (output))) + +#endif /* HAD_ZIP_CRYPTO_OPENSSL_H */ diff --git a/src/Common/libzip/zip_crypto_win.c b/src/Common/libzip/zip_crypto_win.c new file mode 100644 index 00000000..6dc1bb1d --- /dev/null +++ b/src/Common/libzip/zip_crypto_win.c @@ -0,0 +1,495 @@ +/* + zip_crypto_win.c -- Windows Crypto API wrapper. + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include + +#include "zipint.h" + +#include "zip_crypto.h" + +#define WIN32_LEAN_AND_MEAN +#define NOCRYPT + +#include + +#include + +#pragma comment(lib, "bcrypt.lib") + +/* + +This code is using the Cryptography API: Next Generation (CNG) +https://docs.microsoft.com/en-us/windows/desktop/seccng/cng-portal + +This API is supported on + - Windows Vista or later (client OS) + - Windows Server 2008 (server OS) + - Windows Embedded Compact 2013 (don't know about Windows Embedded Compact 7) + +The code was developed for Windows Embedded Compact 2013 (WEC2013), +but should be working for all of the above mentioned OSes. + +There are 2 restrictions for WEC2013, Windows Vista and Windows Server 2008: + +1.) The function "BCryptDeriveKeyPBKDF2" is not available + +I found some code which is implementing this function using the deprecated Crypto API here: +https://www.idrix.fr/Root/content/view/37/54/ + +I took this code and converted it to the newer CNG API. The original code was more +flexible, but this is not needed here so i refactored it a bit and just kept what is needed. + +The define "HAS_BCRYPTDERIVEKEYPBKDF2" controls whether "BCryptDeriveKeyPBKDF2" +of the CNG API is used or not. This define must not be set if you are compiling for WEC2013 or Windows Vista. + + +2.) "BCryptCreateHash" can't manage the memory needed for the hash object internally + +On Windows 7 or later it is possible to pass NULL for the hash object buffer. +This is not supported on WEC2013, so we have to handle the memory allocation/deallocation ourselves. +There is no #ifdef to control that, because this is working for all supported OSes. + +*/ + +#if !defined(WINCE) && !defined(__MINGW32__) +#define HAS_BCRYPTDERIVEKEYPBKDF2 +#endif + +#ifdef HAS_BCRYPTDERIVEKEYPBKDF2 + +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; + } + + result = BCRYPT_SUCCESS(BCryptDeriveKeyPBKDF2(hAlgorithm, (PUCHAR)key, (ULONG)key_length, (PUCHAR)salt, salt_length, iterations, output, output_length, 0)); + + BCryptCloseAlgorithmProvider(hAlgorithm, 0); + + return result; +} + +#else + +#include + +#define DIGEST_SIZE 20 +#define BLOCK_SIZE 64 + +typedef struct { + BCRYPT_ALG_HANDLE hAlgorithm; + BCRYPT_HASH_HANDLE hInnerHash; + BCRYPT_HASH_HANDLE hOuterHash; + ULONG cbHashObject; + PUCHAR pbInnerHash; + PUCHAR pbOuterHash; +} PRF_CTX; + +static void +hmacFree(PRF_CTX *pContext) { + if (pContext->hOuterHash) + BCryptDestroyHash(pContext->hOuterHash); + if (pContext->hInnerHash) + BCryptDestroyHash(pContext->hInnerHash); + free(pContext->pbOuterHash); + free(pContext->pbInnerHash); + if (pContext->hAlgorithm) + BCryptCloseAlgorithmProvider(pContext->hAlgorithm, 0); +} + +static BOOL +hmacPrecomputeDigest(BCRYPT_HASH_HANDLE hHash, PUCHAR pbPassword, DWORD cbPassword, BYTE mask) { + BYTE buffer[BLOCK_SIZE]; + DWORD i; + + if (cbPassword > BLOCK_SIZE) { + return FALSE; + } + + memset(buffer, mask, sizeof(buffer)); + + for (i = 0; i < cbPassword; ++i) { + buffer[i] = (char)(pbPassword[i] ^ mask); + } + + return BCRYPT_SUCCESS(BCryptHashData(hHash, buffer, sizeof(buffer), 0)); +} + +static BOOL +hmacInit(PRF_CTX *pContext, PUCHAR pbPassword, DWORD cbPassword) { + BOOL bStatus = FALSE; + ULONG cbResult; + 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; + } + + if (cbPassword > BLOCK_SIZE) { + 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)); + + if (hHash) + BCryptDestroyHash(hHash); + free(pbHashObject); + + if (!bStatus) { + goto hmacInit_end; + } + + pbPassword = key; + } + + bStatus = hmacPrecomputeDigest(pContext->hInnerHash, pbPassword, cbPassword, 0x36) && hmacPrecomputeDigest(pContext->hOuterHash, pbPassword, cbPassword, 0x5C); + +hmacInit_end: + + if (bStatus == FALSE) + hmacFree(pContext); + + return bStatus; +} + +static BOOL +hmacCalculateInternal(BCRYPT_HASH_HANDLE hHashTemplate, PUCHAR pbData, DWORD cbData, PUCHAR pbOutput, DWORD cbOutput, DWORD cbHashObject) { + BOOL success = FALSE; + BCRYPT_HASH_HANDLE hHash = NULL; + PUCHAR pbHashObject = malloc(cbHashObject); + + if (pbHashObject == NULL) { + 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)); + + BCryptDestroyHash(hHash); + } + + free(pbHashObject); + + return success; +} + +static BOOL +hmacCalculate(PRF_CTX *pContext, PUCHAR pbData, DWORD cbData, PUCHAR pbDigest) { + DWORD cbResult; + DWORD cbHashObject; + + return BCRYPT_SUCCESS(BCryptGetProperty(pContext->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&cbHashObject, sizeof(cbHashObject), &cbResult, 0)) && hmacCalculateInternal(pContext->hInnerHash, pbData, cbData, pbDigest, DIGEST_SIZE, cbHashObject) && hmacCalculateInternal(pContext->hOuterHash, pbDigest, DIGEST_SIZE, pbDigest, DIGEST_SIZE, cbHashObject); +} + +static void +myxor(LPBYTE ptr1, LPBYTE ptr2, DWORD dwLen) { + while (dwLen--) + *ptr1++ ^= *ptr2++; +} + +BOOL +pbkdf2(PUCHAR pbPassword, ULONG cbPassword, PUCHAR pbSalt, ULONG cbSalt, DWORD cIterations, PUCHAR pbDerivedKey, ULONG cbDerivedKey) { + BOOL bStatus = FALSE; + DWORD l, r, dwULen, i, j; + BYTE Ti[DIGEST_SIZE]; + BYTE V[DIGEST_SIZE]; + LPBYTE U = malloc(max((cbSalt + 4), DIGEST_SIZE)); + PRF_CTX prfCtx = {0}; + + if (U == NULL) { + return FALSE; + } + + if (pbPassword == NULL || cbPassword == 0 || pbSalt == NULL || cbSalt == 0 || cIterations == 0 || pbDerivedKey == NULL || cbDerivedKey == 0) { + free(U); + return FALSE; + } + + if (!hmacInit(&prfCtx, pbPassword, cbPassword)) { + 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; + } + + if (!hmacCalculate(&prfCtx, U, dwULen, V)) { + goto PBKDF2_end; + } + + 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); + } + } + + bStatus = TRUE; + +PBKDF2_end: + + hmacFree(&prfCtx); + free(U); + return bStatus; +} + +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) { + return (key_length <= ZIP_UINT32_MAX) && pbkdf2((PUCHAR)key, (ULONG)key_length, (PUCHAR)salt, salt_length, iterations, output, output_length); +} + +#endif + + +struct _zip_crypto_aes_s { + BCRYPT_ALG_HANDLE hAlgorithm; + BCRYPT_KEY_HANDLE hKey; + ULONG cbKeyObject; + PUCHAR pbKeyObject; +}; + +_zip_crypto_aes_t * +_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) { + _zip_crypto_aes_t *aes = (_zip_crypto_aes_t *)calloc(1, sizeof(*aes)); + + ULONG cbResult; + ULONG key_length = key_size / 8; + + if (aes == 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; + } + + 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; + } + + if (!BCRYPT_SUCCESS(BCryptGetProperty(aes->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&aes->cbKeyObject, sizeof(aes->cbKeyObject), &cbResult, 0))) { + _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; + } + + if (!BCRYPT_SUCCESS(BCryptGenerateSymmetricKey(aes->hAlgorithm, &aes->hKey, aes->pbKeyObject, aes->cbKeyObject, (PUCHAR)key, key_length, 0))) { + _zip_crypto_aes_free(aes); + return NULL; + } + + return aes; +} + +void +_zip_crypto_aes_free(_zip_crypto_aes_t *aes) { + if (aes == NULL) { + return; + } + + if (aes->hKey != NULL) { + BCryptDestroyKey(aes->hKey); + } + + if (aes->pbKeyObject != NULL) { + free(aes->pbKeyObject); + } + + if (aes->hAlgorithm != NULL) { + BCryptCloseAlgorithmProvider(aes->hAlgorithm, 0); + } + + free(aes); +} + +bool +_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) { + ULONG cbResult; + NTSTATUS status = BCryptEncrypt(aes->hKey, (PUCHAR)in, ZIP_CRYPTO_AES_BLOCK_LENGTH, NULL, NULL, 0, (PUCHAR)out, ZIP_CRYPTO_AES_BLOCK_LENGTH, &cbResult, 0); + return BCRYPT_SUCCESS(status); +} + +struct _zip_crypto_hmac_s { + BCRYPT_ALG_HANDLE hAlgorithm; + BCRYPT_HASH_HANDLE hHash; + DWORD cbHashObject; + PUCHAR pbHashObject; + DWORD cbHash; + PUCHAR pbHash; +}; + +/* https://code.msdn.microsoft.com/windowsdesktop/Hmac-Computation-Sample-11fe8ec1/sourcecode?fileId=42820&pathId=283874677 */ + +_zip_crypto_hmac_t * +_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) { + NTSTATUS status; + ULONG cbResult; + _zip_crypto_hmac_t *hmac; + + if (secret_length > INT_MAX) { + 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; + } + + status = BCryptOpenAlgorithmProvider(&hmac->hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG); + if (!BCRYPT_SUCCESS(status)) { + _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; + } + + hmac->pbHashObject = malloc(hmac->cbHashObject); + if (hmac->pbHashObject == 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; + } + + hmac->pbHash = malloc(hmac->cbHash); + if (hmac->pbHash == 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; + } + + return hmac; +} + +void +_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) { + if (hmac == NULL) { + return; + } + + if (hmac->hHash != NULL) { + BCryptDestroyHash(hmac->hHash); + } + + if (hmac->pbHash != NULL) { + free(hmac->pbHash); + } + + if (hmac->pbHashObject != NULL) { + free(hmac->pbHashObject); + } + + if (hmac->hAlgorithm) { + BCryptCloseAlgorithmProvider(hmac->hAlgorithm, 0); + } + + free(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 BCRYPT_SUCCESS(BCryptHashData(hmac->hHash, data, (ULONG)length, 0)); +} + +bool +_zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data) { + if (hmac == NULL) { + return false; + } + + return BCRYPT_SUCCESS(BCryptFinishHash(hmac->hHash, data, hmac->cbHash, 0)); +} + +ZIP_EXTERN bool +zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { + return BCRYPT_SUCCESS(BCryptGenRandom(NULL, buffer, length, BCRYPT_USE_SYSTEM_PREFERRED_RNG)); +} diff --git a/src/Common/libzip/zip_crypto_win.h b/src/Common/libzip/zip_crypto_win.h new file mode 100644 index 00000000..a533fe2d --- /dev/null +++ b/src/Common/libzip/zip_crypto_win.h @@ -0,0 +1,53 @@ +/* + zip_crypto_win.h -- Windows Crypto API wrapper. + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HAD_ZIP_CRYPTO_WIN_H +#define HAD_ZIP_CRYPTO_WIN_H + +#define HAVE_SECURE_RANDOM + +typedef struct _zip_crypto_aes_s _zip_crypto_aes_t; +typedef struct _zip_crypto_hmac_s _zip_crypto_hmac_t; + +void _zip_crypto_aes_free(_zip_crypto_aes_t *aes); +_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error); +bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out); + +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); + +_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error); +void _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); +bool _zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data); + +#endif /* HAD_ZIP_CRYPTO_WIN_H */ diff --git a/src/Common/libzip/zip_delete.c b/src/Common/libzip/zip_delete.c index 97701a01..676c16bf 100644 --- a/src/Common/libzip/zip_delete.c +++ b/src/Common/libzip/zip_delete.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_dir_add.c b/src/Common/libzip/zip_dir_add.c index c40b1cb9..42ba5e84 100644 --- a/src/Common/libzip/zip_dir_add.c +++ b/src/Common/libzip/zip_dir_add.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_dirent.c b/src/Common/libzip/zip_dirent.c index 1691071f..4615fc65 100644 --- a/src/Common/libzip/zip_dirent.c +++ b/src/Common/libzip/zip_dirent.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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; - } - - 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; - } - } + 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, 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); - - 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; + 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 (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; - } - - 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 (!_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); + 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 (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; + + 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,68 +645,67 @@ _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 */ crc_valid = true; switch (_zip_buffer_get_16(buffer)) { - case 1: - break; - - case 2: - if (de->uncomp_size < 20 /* TODO: constant */) { - crc_valid = false; - } - break; + case 1: + break; - default: - zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0); - _zip_buffer_free(buffer); - return false; + case 2: + crc_valid = false; + /* TODO: When checking consistency, check that crc is 0. */ + break; + + default: + 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 +728,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 +780,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 +811,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; - } - - 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; - } - - 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; + 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 (!_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; } 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; - - 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); - - 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; + 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; + } + + _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; + } + + 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 +906,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 +942,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 +1029,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 +1048,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 +1063,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 +1097,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 +1118,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/src/Common/libzip/zip_discard.c b/src/Common/libzip/zip_discard.c index 12f06367..d1dc4f8b 100644 --- a/src/Common/libzip/zip_discard.c +++ b/src/Common/libzip/zip_discard.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_entry.c b/src/Common/libzip/zip_entry.c index 52ecaef9..35a36e4a 100644 --- a/src/Common/libzip/zip_entry.c +++ b/src/Common/libzip/zip_entry.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/src/Common/libzip/zip_error.c b/src/Common/libzip/zip_error.c index a0f74f02..5fc2e838 100644 --- a/src/Common/libzip/zip_error.c +++ b/src/Common/libzip/zip_error.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_error_clear.c b/src/Common/libzip/zip_error_clear.c index eec1568f..94ff5062 100644 --- a/src/Common/libzip/zip_error_clear.c +++ b/src/Common/libzip/zip_error_clear.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_error_get.c b/src/Common/libzip/zip_error_get.c index 9588b4c4..c0418f0d 100644 --- a/src/Common/libzip/zip_error_get.c +++ b/src/Common/libzip/zip_error_get.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/src/Common/libzip/zip_error_get_sys_type.c b/src/Common/libzip/zip_error_get_sys_type.c index 3dfe5c26..a22ffb03 100644 --- a/src/Common/libzip/zip_error_get_sys_type.c +++ b/src/Common/libzip/zip_error_get_sys_type.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_error_strerror.c b/src/Common/libzip/zip_error_strerror.c index 93b24eab..2a1fbaf2 100644 --- a/src/Common/libzip/zip_error_strerror.c +++ b/src/Common/libzip/zip_error_strerror.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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]; - - 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; - } + zip_error_string = _zip_err_str[err->zip_err].description; + + 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/src/Common/libzip/zip_error_to_str.c b/src/Common/libzip/zip_error_to_str.c index 34a3331f..acd91c93 100644 --- a/src/Common/libzip/zip_error_to_str.c +++ b/src/Common/libzip/zip_error_to_str.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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); - - zs = _zip_err_str[ze]; - - switch (_zip_err_type[ze]) { - case ZIP_ET_SYS: - ss = strerror(se); - break; + if (ze < 0 || ze >= _zip_err_str_count) { + return snprintf(buf, len, "Unknown error %d", ze); + } - case ZIP_ET_ZLIB: - ss = zError(se); - break; + zs = _zip_err_str[ze].description; - 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/src/Common/libzip/zip_extra_field.c b/src/Common/libzip/zip_extra_field.c index 7114a251..92cec011 100644 --- a/src/Common/libzip/zip_extra_field.c +++ b/src/Common/libzip/zip_extra_field.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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 (head == NULL) - head = def; - if (prev) - prev->next = def; - prev = def; - - ef = ef->next; + 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; + + 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 (id_idx == ZIP_EXTRA_FIELD_ALL) - continue; - } - } - - i++; - if (i > id_idx) - break; - } - prev = 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; + } + } + + 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 (lenp) - *lenp = ef->size; - if (ef->size > 0) - return ef->data; - else - return empty; - } + 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; + } } 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; - - 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; + 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; + } + } + + 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; - - 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 ((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; + 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); + + 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 (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/src/Common/libzip/zip_extra_field_api.c b/src/Common/libzip/zip_extra_field_api.c index 605f95d0..cd143f39 100644 --- a/src/Common/libzip/zip_extra_field_api.c +++ b/src/Common/libzip/zip_extra_field_api.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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 (idp) - *idp = ef->id; - if (lenp) - *lenp = ef->size; - if (ef->size > 0) - return ef->data; - else - return empty; - } + 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; + } } 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/src/Common/libzip/zip_fclose.c b/src/Common/libzip/zip_fclose.c index 6eb9dc91..b820d98b 100644 --- a/src/Common/libzip/zip_fclose.c +++ b/src/Common/libzip/zip_fclose.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_fdopen.c b/src/Common/libzip/zip_fdopen.c index 5a732cd4..5cd43914 100644 --- a/src/Common/libzip/zip_fdopen.c +++ b/src/Common/libzip/zip_fdopen.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_file_add.c b/src/Common/libzip/zip_file_add.c index c019d8dd..c2c41e15 100644 --- a/src/Common/libzip/zip_file_add.c +++ b/src/Common/libzip/zip_file_add.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_file_error_clear.c b/src/Common/libzip/zip_file_error_clear.c index 47e5da63..a10bff80 100644 --- a/src/Common/libzip/zip_file_error_clear.c +++ b/src/Common/libzip/zip_file_error_clear.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_file_error_get.c b/src/Common/libzip/zip_file_error_get.c index 1ed68df1..b93117bb 100644 --- a/src/Common/libzip/zip_file_error_get.c +++ b/src/Common/libzip/zip_file_error_get.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/src/Common/libzip/zip_file_get_comment.c b/src/Common/libzip/zip_file_get_comment.c index 8f68141a..fa998f02 100644 --- a/src/Common/libzip/zip_file_get_comment.c +++ b/src/Common/libzip/zip_file_get_comment.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_file_get_external_attributes.c b/src/Common/libzip/zip_file_get_external_attributes.c index ebc20580..a79bb3ed 100644 --- a/src/Common/libzip/zip_file_get_external_attributes.c +++ b/src/Common/libzip/zip_file_get_external_attributes.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_file_get_offset.c b/src/Common/libzip/zip_file_get_offset.c index 2cf4480d..213f7d3a 100644 --- a/src/Common/libzip/zip_file_get_offset.c +++ b/src/Common/libzip/zip_file_get_offset.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_file_rename.c b/src/Common/libzip/zip_file_rename.c index 7ca428c4..9ac25814 100644 --- a/src/Common/libzip/zip_file_rename.c +++ b/src/Common/libzip/zip_file_rename.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_file_replace.c b/src/Common/libzip/zip_file_replace.c index 87401f4a..4262d453 100644 --- a/src/Common/libzip/zip_file_replace.c +++ b/src/Common/libzip/zip_file_replace.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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; - } - } - - za->entry[idx].changes->comp_method = ZIP_CM_REPLACED_DEFAULT; - za->entry[idx].changes->changed |= ZIP_DIRENT_COMP_METHOD; + 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].source = source; diff --git a/src/Common/libzip/zip_file_set_comment.c b/src/Common/libzip/zip_file_set_comment.c index c309db8b..f50953bf 100644 --- a/src/Common/libzip/zip_file_set_comment.c +++ b/src/Common/libzip/zip_file_set_comment.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_file_set_encryption.c b/src/Common/libzip/zip_file_set_encryption.c new file mode 100644 index 00000000..41392c1f --- /dev/null +++ b/src/Common/libzip/zip_file_set_encryption.c @@ -0,0 +1,116 @@ +/* + zip_file_set_encryption.c -- set encryption for file in archive + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +#include +#include + +ZIP_EXTERN int +zip_file_set_encryption(zip_t *za, zip_uint64_t idx, zip_uint16_t method, const char *password) { + zip_entry_t *e; + zip_uint16_t old_method; + + 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; + } + + 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; + } + + e = za->entry + idx; + + 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; + } + } + } + else { + char *our_password = NULL; + + 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; + } + } + + 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/src/Common/libzip/zip_file_set_external_attributes.c b/src/Common/libzip/zip_file_set_external_attributes.c index bb2ea614..1a0028d3 100644 --- a/src/Common/libzip/zip_file_set_external_attributes.c +++ b/src/Common/libzip/zip_file_set_external_attributes.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_file_set_mtime.c b/src/Common/libzip/zip_file_set_mtime.c index 838548ef..10abe81b 100644 --- a/src/Common/libzip/zip_file_set_mtime.c +++ b/src/Common/libzip/zip_file_set_mtime.c @@ -1,9 +1,9 @@ /* zip_file_set_mtime.c -- set modification time of entry. - Copyright (C) 2014-2020 Dieter Baron and Thomas Klausner + Copyright (C) 2014-2022 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -45,20 +45,25 @@ 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->orig != NULL && e->orig->encryption_method == ZIP_EM_TRAD_PKWARE && !ZIP_ENTRY_CHANGED(e, ZIP_DIRENT_ENCRYPTION_METHOD) && !ZIP_ENTRY_DATA_CHANGED(e)) { + zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 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; + } } e->changes->last_mod = mtime; diff --git a/src/Common/libzip/zip_file_strerror.c b/src/Common/libzip/zip_file_strerror.c index 1fa7fffd..5b5a0092 100644 --- a/src/Common/libzip/zip_file_strerror.c +++ b/src/Common/libzip/zip_file_strerror.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/src/Common/libzip/zip_filerange_crc.c b/src/Common/libzip/zip_filerange_crc.c deleted file mode 100644 index b8873634..00000000 --- a/src/Common/libzip/zip_filerange_crc.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - zip_filerange_crc.c -- compute CRC32 for a range of a file - Copyright (C) 2008-2019 Dieter Baron and Thomas Klausner - - This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - 3. The names of the authors may not be used to endorse or promote - products derived from this software without specific prior - written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include - -#include "zipint.h" - - -int -_zip_filerange_crc(zip_source_t *src, zip_uint64_t start, zip_uint64_t len, uLong *crcp, zip_error_t *error) { - DEFINE_BYTE_ARRAY(buf, BUFSIZE); - - zip_int64_t n; - - *crcp = crc32(0L, Z_NULL, 0); - - if (start > ZIP_INT64_MAX) { - zip_error_set(error, ZIP_ER_SEEK, EFBIG); - return -1; - } - - if (zip_source_seek(src, (zip_int64_t)start, SEEK_SET) != 0) { - _zip_error_set_from_source(error, src); - return -1; - } - - if (!byte_array_init(buf, BUFSIZE)) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return -1; - } - - while (len > 0) { - n = (zip_int64_t)(len > BUFSIZE ? BUFSIZE : len); - if ((n = zip_source_read(src, buf, (zip_uint64_t)n)) < 0) { - _zip_error_set_from_source(error, src); - byte_array_fini(buf); - return -1; - } - if (n == 0) { - zip_error_set(error, ZIP_ER_EOF, 0); - byte_array_fini(buf); - return -1; - } - - *crcp = crc32(*crcp, buf, (uInt)n); - - len -= (zip_uint64_t)n; - } - - byte_array_fini(buf); - - return 0; -} diff --git a/src/Common/libzip/zip_fopen.c b/src/Common/libzip/zip_fopen.c index 4f1a051d..e3cde9be 100644 --- a/src/Common/libzip/zip_fopen.c +++ b/src/Common/libzip/zip_fopen.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_fopen_encrypted.c b/src/Common/libzip/zip_fopen_encrypted.c index 9e9b13e5..d5880dcb 100644 --- a/src/Common/libzip/zip_fopen_encrypted.c +++ b/src/Common/libzip/zip_fopen_encrypted.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_fopen_index.c b/src/Common/libzip/zip_fopen_index.c index e5205b73..a449b83a 100644 --- a/src/Common/libzip/zip_fopen_index.c +++ b/src/Common/libzip/zip_fopen_index.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/src/Common/libzip/zip_fopen_index_encrypted.c b/src/Common/libzip/zip_fopen_index_encrypted.c index 6712c32a..a69dfb94 100644 --- a/src/Common/libzip/zip_fopen_index_encrypted.c +++ b/src/Common/libzip/zip_fopen_index_encrypted.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_fread.c b/src/Common/libzip/zip_fread.c index 646d7124..22fabe39 100644 --- a/src/Common/libzip/zip_fread.c +++ b/src/Common/libzip/zip_fread.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_fseek.c b/src/Common/libzip/zip_fseek.c new file mode 100644 index 00000000..33136155 --- /dev/null +++ b/src/Common/libzip/zip_fseek.c @@ -0,0 +1,61 @@ +/* + zip_fseek.c -- seek in file + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +ZIP_EXTERN zip_int8_t +zip_fseek(zip_file_t *zf, zip_int64_t offset, int whence) { + if (!zf) + return -1; + + if (zf->error.zip_err != 0) + return -1; + + if (zip_source_seek(zf->src, offset, whence) < 0) { + _zip_error_set_from_source(&zf->error, zf->src); + return -1; + } + + return 0; +} + + +ZIP_EXTERN int +zip_file_is_seekable(zip_file_t *zfile) { + if (!zfile) { + return -1; + } + + return ZIP_SOURCE_CHECK_SUPPORTED(zip_source_supports(zfile->src), ZIP_SOURCE_SEEK); +} diff --git a/src/Common/libzip/zip_ftell.c b/src/Common/libzip/zip_ftell.c new file mode 100644 index 00000000..7a3cda08 --- /dev/null +++ b/src/Common/libzip/zip_ftell.c @@ -0,0 +1,54 @@ +/* + zip_ftell.c -- tell position in file + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +ZIP_EXTERN zip_int64_t +zip_ftell(zip_file_t *zf) { + zip_int64_t res; + + if (!zf) + return -1; + + if (zf->error.zip_err != 0) + return -1; + + res = zip_source_tell(zf->src); + if (res < 0) { + _zip_error_set_from_source(&zf->error, zf->src); + return -1; + } + + return res; +} diff --git a/src/Common/libzip/zip_get_archive_comment.c b/src/Common/libzip/zip_get_archive_comment.c index 953c6f42..ea9a00ab 100644 --- a/src/Common/libzip/zip_get_archive_comment.c +++ b/src/Common/libzip/zip_get_archive_comment.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_get_archive_flag.c b/src/Common/libzip/zip_get_archive_flag.c index fa4dd502..fc200bdc 100644 --- a/src/Common/libzip/zip_get_archive_flag.c +++ b/src/Common/libzip/zip_get_archive_flag.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/src/Common/libzip/zip_get_encryption_implementation.c b/src/Common/libzip/zip_get_encryption_implementation.c index 3909e6f6..72e48fe8 100644 --- a/src/Common/libzip/zip_get_encryption_implementation.c +++ b/src/Common/libzip/zip_get_encryption_implementation.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_get_file_comment.c b/src/Common/libzip/zip_get_file_comment.c index f8006861..d58e22ba 100644 --- a/src/Common/libzip/zip_get_file_comment.c +++ b/src/Common/libzip/zip_get_file_comment.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_get_name.c b/src/Common/libzip/zip_get_name.c index 43442093..4828d781 100644 --- a/src/Common/libzip/zip_get_name.c +++ b/src/Common/libzip/zip_get_name.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_get_num_entries.c b/src/Common/libzip/zip_get_num_entries.c index 410d26e1..667dc511 100644 --- a/src/Common/libzip/zip_get_num_entries.c +++ b/src/Common/libzip/zip_get_num_entries.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_get_num_files.c b/src/Common/libzip/zip_get_num_files.c index 4895eaab..140e34f9 100644 --- a/src/Common/libzip/zip_get_num_files.c +++ b/src/Common/libzip/zip_get_num_files.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_hash.c b/src/Common/libzip/zip_hash.c index 3206dbf7..d3a954ec 100644 --- a/src/Common/libzip/zip_hash.c +++ b/src/Common/libzip/zip_hash.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_io_util.c b/src/Common/libzip/zip_io_util.c index dd07cbb9..0a1e4d5f 100644 --- a/src/Common/libzip/zip_io_util.c +++ b/src/Common/libzip/zip_io_util.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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); - - if (data == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - free(r); - return NULL; - } - memcpy(r, data, 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); } 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/src/Common/libzip/zip_libzip_version.c b/src/Common/libzip/zip_libzip_version.c new file mode 100644 index 00000000..4200727f --- /dev/null +++ b/src/Common/libzip/zip_libzip_version.c @@ -0,0 +1,41 @@ +/* + zip_libzip_version.c -- return run-time version of library + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN const char * +zip_libzip_version(void) { + return LIBZIP_VERSION; +} diff --git a/src/Common/libzip/zip_memdup.c b/src/Common/libzip/zip_memdup.c index 05fcb7b7..38459d8a 100644 --- a/src/Common/libzip/zip_memdup.c +++ b/src/Common/libzip/zip_memdup.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_name_locate.c b/src/Common/libzip/zip_name_locate.c index f7318ece..806053cc 100644 --- a/src/Common/libzip/zip_name_locate.c +++ b/src/Common/libzip/zip_name_locate.c @@ -1,9 +1,9 @@ /* zip_name_locate.c -- get index by name - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -49,44 +49,59 @@ zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags) { zip_int64_t _zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags, zip_error_t *error) { int (*cmp)(const char *, const char *); + zip_string_t *str = NULL; const char *fn, *p; 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; - - 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; - - 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 ((flags & (ZIP_FL_ENC_UTF_8 | ZIP_FL_ENC_RAW)) == 0 && fname[0] != '\0') { + if ((str = _zip_string_new((const zip_uint8_t *)fname, strlen(fname), flags, error)) == NULL) { + return -1; + } + if ((fname = (const char *)_zip_string_get(str, NULL, 0, error)) == NULL) { + _zip_string_free(str); + return -1; + } + } - zip_error_set(error, ZIP_ER_NOENT, 0); - return -1; + if (flags & (ZIP_FL_NOCASE | ZIP_FL_NODIR | ZIP_FL_ENC_RAW | ZIP_FL_ENC_STRICT)) { + /* 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); + + /* 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 (cmp(fname, fn) == 0) { + _zip_error_clear(error); + _zip_string_free(str); + return (zip_int64_t)i; + } + } + + zip_error_set(error, ZIP_ER_NOENT, 0); + _zip_string_free(str); + return -1; } else { - return _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error); + zip_int64_t ret = _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error); + _zip_string_free(str); + return ret; } } diff --git a/src/Common/libzip/zip_new.c b/src/Common/libzip/zip_new.c index 4f58ecc7..4f69c8a2 100644 --- a/src/Common/libzip/zip_new.c +++ b/src/Common/libzip/zip_new.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_open.c b/src/Common/libzip/zip_open.c index 019cd987..96f4dbc3 100644 --- a/src/Common/libzip/zip_open.c +++ b/src/Common/libzip/zip_open.c @@ -1,9 +1,9 @@ /* zip_open.c -- open zip archive by name - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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); @@ -77,73 +77,66 @@ zip_open(const char *fn, int _flags, int *zep) { ZIP_EXTERN zip_t * zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error) { - static zip_int64_t needed_support_read = -1; - static zip_int64_t needed_support_write = -1; - unsigned int flags; zip_int64_t supported; 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); - } - if ((supported & needed_support_read) != needed_support_read) { - zip_error_set(error, ZIP_ER_OPNOTSUPP, 0); - return NULL; + if ((supported & ZIP_SOURCE_SUPPORTS_SEEKABLE) != ZIP_SOURCE_SUPPORTS_SEEKABLE) { + zip_error_set(error, ZIP_ER_OPNOTSUPP, 0); + return NULL; } - if ((supported & needed_support_write) != needed_support_write) { - flags |= ZIP_RDONLY; + if ((supported & ZIP_SOURCE_SUPPORTS_WRITABLE) != ZIP_SOURCE_SUPPORTS_WRITABLE) { + 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; - } - - 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; + 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 (za == NULL) { + zip_source_close(src); + return NULL; + } + return za; } } } @@ -158,31 +151,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 +188,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; - } - - 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; - } - } + 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; + } + } } za->ch_flags = za->flags; @@ -223,14 +216,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 +248,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); - - 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; - } + 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, 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; - - 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 (!_zip_cdir_grow(cd, 0x10000, error)) { - _zip_cdir_free(cd); - _zip_buffer_free(cd_buffer); - return NULL; + 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 (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)); } - 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; - - 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 (!ok) { - zip_error_set(error, ZIP_ER_INCONS, 0); - _zip_buffer_free(cd_buffer); - _zip_cdir_free(cd); - return NULL; - } + bool ok; + + 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 (!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 +422,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; - } - - 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_dirent_read(&temp, za->src, NULL, true, error) == -1) { - _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; - } - - 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); + 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; + } + + 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) { + 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, 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; + + _zip_dirent_finalize(&temp); } return (max - min) < ZIP_INT64_MAX ? (zip_int64_t)(max - min) : ZIP_INT64_MAX; @@ -481,14 +486,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 +505,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 +527,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 +551,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); - } - - 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))); + _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; + } + + 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 +632,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 +649,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 +658,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 +668,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 +722,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 +761,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 +777,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 +813,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/src/Common/libzip/zip_pkware.c b/src/Common/libzip/zip_pkware.c index eb12b1e9..6a8c9fcd 100644 --- a/src/Common/libzip/zip_pkware.c +++ b/src/Common/libzip/zip_pkware.c @@ -3,7 +3,7 @@ Copyright (C) 2009-2020 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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]; - - 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); - } + 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); + } } } @@ -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/src/Common/libzip/zip_progress.c b/src/Common/libzip/zip_progress.c index ddb47c70..e080514b 100644 --- a/src/Common/libzip/zip_progress.c +++ b/src/Common/libzip/zip_progress.c @@ -3,7 +3,7 @@ Copyright (C) 2017-2020 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_random_unix.c b/src/Common/libzip/zip_random_unix.c new file mode 100644 index 00000000..f84a5482 --- /dev/null +++ b/src/Common/libzip/zip_random_unix.c @@ -0,0 +1,104 @@ +/* + zip_random_unix.c -- fill the user's buffer with random stuff (Unix version) + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#ifdef HAVE_CRYPTO +#include "zip_crypto.h" +#endif + +#ifdef HAVE_ARC4RANDOM + +#include + +#ifndef HAVE_SECURE_RANDOM +ZIP_EXTERN bool +zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { + arc4random_buf(buffer, length); + return true; +} +#endif + +#ifndef HAVE_RANDOM_UINT32 +zip_uint32_t +zip_random_uint32(void) { + return arc4random(); +} +#endif + +#else /* HAVE_ARC4RANDOM */ + +#ifndef HAVE_SECURE_RANDOM +#include +#include + +ZIP_EXTERN bool +zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { + int fd; + + if ((fd = open("/dev/urandom", O_RDONLY)) < 0) { + return false; + } + + if (read(fd, buffer, length) != length) { + close(fd); + return false; + } + + close(fd); + return true; +} +#endif + +#ifndef HAVE_RANDOM_UINT32 +#include + +zip_uint32_t +zip_random_uint32(void) { + static bool seeded = false; + + zip_uint32_t value; + + if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) { + return value; + } + + if (!seeded) { + srandom((unsigned int)time(NULL)); + } + + return (zip_uint32_t)random(); +} +#endif + +#endif /* HAVE_ARC4RANDOM */ diff --git a/src/Common/libzip/zip_random_uwp.c b/src/Common/libzip/zip_random_uwp.c new file mode 100644 index 00000000..9f842b99 --- /dev/null +++ b/src/Common/libzip/zip_random_uwp.c @@ -0,0 +1,81 @@ +/* + zip_random_uwp.c -- fill the user's buffer with random stuff (UWP version) + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#ifdef HAVE_CRYPTO +#include "zip_crypto.h" +#endif + +#ifndef HAVE_SECURE_RANDOM + +#include +#include + +ZIP_EXTERN bool +zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { + BCRYPT_ALG_HANDLE hAlg = NULL; + NTSTATUS hr = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); + if (!BCRYPT_SUCCESS(hr) || hAlg == NULL) { + return false; + } + hr = BCryptGenRandom(&hAlg, buffer, length, 0); + BCryptCloseAlgorithmProvider(&hAlg, 0); + if (!BCRYPT_SUCCESS(hr)) { + return false; + } + return true; +} + +#endif + +#ifndef HAVE_RANDOM_UINT32 +#include + +zip_uint32_t +zip_random_uint32(void) { + static bool seeded = false; + + zip_uint32_t value; + + if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) { + return value; + } + + if (!seeded) { + srand((unsigned int)time(NULL)); + } + + return (zip_uint32_t)rand(); +} +#endif diff --git a/src/Common/libzip/zip_random_win32.c b/src/Common/libzip/zip_random_win32.c new file mode 100644 index 00000000..966b9a5e --- /dev/null +++ b/src/Common/libzip/zip_random_win32.c @@ -0,0 +1,81 @@ +/* + zip_random_win32.c -- fill the user's buffer with random stuff (Windows version) + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#ifdef HAVE_CRYPTO +#include "zip_crypto.h" +#endif + +#include + +#ifndef HAVE_SECURE_RANDOM + +#include + +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; + } + if (!CryptGenRandom(hprov, length, buffer)) { + return false; + } + if (!CryptReleaseContext(hprov, 0)) { + return false; + } + return true; +} +#endif + +#ifndef HAVE_RANDOM_UINT32 +#include + +zip_uint32_t +zip_random_uint32(void) { + static bool seeded = false; + + zip_uint32_t value; + + if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) { + return value; + } + + if (!seeded) { + srand((unsigned int)time(NULL)); + } + + return (zip_uint32_t)rand(); +} +#endif diff --git a/src/Common/libzip/zip_rename.c b/src/Common/libzip/zip_rename.c index 75b456de..c89b06c9 100644 --- a/src/Common/libzip/zip_rename.c +++ b/src/Common/libzip/zip_rename.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/src/Common/libzip/zip_replace.c b/src/Common/libzip/zip_replace.c index 30a2eb1d..96c083c3 100644 --- a/src/Common/libzip/zip_replace.c +++ b/src/Common/libzip/zip_replace.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/src/Common/libzip/zip_set_archive_comment.c b/src/Common/libzip/zip_set_archive_comment.c index 3f050b3e..90637100 100644 --- a/src/Common/libzip/zip_set_archive_comment.c +++ b/src/Common/libzip/zip_set_archive_comment.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_set_archive_flag.c b/src/Common/libzip/zip_set_archive_flag.c index e0d55021..610409d5 100644 --- a/src/Common/libzip/zip_set_archive_flag.c +++ b/src/Common/libzip/zip_set_archive_flag.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_set_default_password.c b/src/Common/libzip/zip_set_default_password.c index 41c7c519..4bab513f 100644 --- a/src/Common/libzip/zip_set_default_password.c +++ b/src/Common/libzip/zip_set_default_password.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_set_file_comment.c b/src/Common/libzip/zip_set_file_comment.c index 4277893f..5d2b0b8a 100644 --- a/src/Common/libzip/zip_set_file_comment.c +++ b/src/Common/libzip/zip_set_file_comment.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_set_file_compression.c b/src/Common/libzip/zip_set_file_compression.c index 927fbb76..1a19fb77 100644 --- a/src/Common/libzip/zip_set_file_compression.c +++ b/src/Common/libzip/zip_set_file_compression.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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; - } - } - - e->changes->comp_method = method; - e->changes->compression_level = (zip_uint16_t)flags; - e->changes->changed |= ZIP_DIRENT_COMP_METHOD; + 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; } return 0; diff --git a/src/Common/libzip/zip_set_name.c b/src/Common/libzip/zip_set_name.c index 43c772e4..f1bf703e 100644 --- a/src/Common/libzip/zip_set_name.c +++ b/src/Common/libzip/zip_set_name.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_accept_empty.c b/src/Common/libzip/zip_source_accept_empty.c index e6d51516..d6a04959 100644 --- a/src/Common/libzip/zip_source_accept_empty.c +++ b/src/Common/libzip/zip_source_accept_empty.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_begin_write.c b/src/Common/libzip/zip_source_begin_write.c index 432c2c15..37818321 100644 --- a/src/Common/libzip/zip_source_begin_write.c +++ b/src/Common/libzip/zip_source_begin_write.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_begin_write_cloning.c b/src/Common/libzip/zip_source_begin_write_cloning.c index 41b4c73c..fc1bc266 100644 --- a/src/Common/libzip/zip_source_begin_write_cloning.c +++ b/src/Common/libzip/zip_source_begin_write_cloning.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_buffer.c b/src/Common/libzip/zip_source_buffer.c index 519d2c30..04cd4f0a 100644 --- a/src/Common/libzip/zip_source_buffer.c +++ b/src/Common/libzip/zip_source_buffer.c @@ -1,9 +1,9 @@ /* zip_source_buffer.c -- create zip data source from buffer - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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__ @@ -361,13 +361,13 @@ buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) { clone->fragment_offsets[clone->nfragments] = offset; clone->size = offset; - clone->first_owned_fragment = ZIP_MIN(buffer->first_owned_fragment, clone->nfragments - 1); + clone->first_owned_fragment = ZIP_MIN(buffer->first_owned_fragment, clone->nfragments); buffer->shared_buffer = clone; clone->shared_buffer = buffer; buffer->shared_fragments = clone->nfragments; clone->shared_fragments = fragment + 1; - + return clone; } @@ -376,20 +376,24 @@ static zip_uint64_t buffer_find_fragment(const buffer_t *buffer, zip_uint64_t offset) { zip_uint64_t low, high, mid; + if (buffer->nfragments == 0) { + return 0; + } + low = 0; 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 +405,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 +430,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 +454,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 +468,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; - - 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; + 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; + } + + 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 +516,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 +548,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 +562,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; - - 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 (!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; - } + 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 (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; + } + } + + 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/src/Common/libzip/zip_source_call.c b/src/Common/libzip/zip_source_call.c index e7c29544..8c98fc2e 100644 --- a/src/Common/libzip/zip_source_call.c +++ b/src/Common/libzip/zip_source_call.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_close.c b/src/Common/libzip/zip_source_close.c index ab7898ce..f4f3ff2b 100644 --- a/src/Common/libzip/zip_source_close.c +++ b/src/Common/libzip/zip_source_close.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_commit_write.c b/src/Common/libzip/zip_source_commit_write.c index d1254bf1..3e699ec7 100644 --- a/src/Common/libzip/zip_source_commit_write.c +++ b/src/Common/libzip/zip_source_commit_write.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_compress.c b/src/Common/libzip/zip_source_compress.c index e49929f5..0b849ded 100644 --- a/src/Common/libzip/zip_source_compress.c +++ b/src/Common/libzip/zip_source_compress.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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); - - if (ret != ZIP_COMPRESSION_ERROR) { - out_offset += out_len; - } - - 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->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_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; - } - - 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; - } + 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; + } + + 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->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_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; + } + + 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; + } } 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; - - if (!ctx->algorithm->start(ctx->ud)) { - return -1; - } - - return 0; + 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, &st, &attributes)) { + return -1; + } + + 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; - - 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; - } - } + zip_stat_t *st; + + 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; + } + } } - 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/src/Common/libzip/zip_source_crc.c b/src/Common/libzip/zip_source_crc.c index 4f3f223f..37ea022c 100644 --- a/src/Common/libzip/zip_source_crc.c +++ b/src/Common/libzip/zip_source_crc.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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 == 0) { - if (ctx->crc_position == ctx->position) { - ctx->crc_complete = 1; - ctx->size = ctx->position; - - 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 ((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; - - 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; + 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 (ctx->validate) { + struct zip_stat st; + + 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) { + /* 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); + + 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; - - 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; + zip_stat_t *st; + + 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; } 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/src/Common/libzip/zip_source_error.c b/src/Common/libzip/zip_source_error.c index 2257f715..dc7fa20c 100644 --- a/src/Common/libzip/zip_source_error.c +++ b/src/Common/libzip/zip_source_error.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/src/Common/libzip/zip_source_file.h b/src/Common/libzip/zip_source_file.h index 43a46453..cca9fd2b 100644 --- a/src/Common/libzip/zip_source_file.h +++ b/src/Common/libzip/zip_source_file.h @@ -1,9 +1,9 @@ /* zip_source_file.h -- header for common file operations - Copyright (C) 2020 Dieter Baron and Thomas Klausner + Copyright (C) 2020-2022 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -34,7 +34,7 @@ struct zip_source_file_stat { zip_uint64_t size; /* must be valid for regular files */ time_t mtime; /* must always be valid, is initialized to current time */ - bool exists; /* must always be vaild */ + bool exists; /* must always be valid */ bool regular_file; /* must always be valid */ }; diff --git a/src/Common/libzip/zip_source_file_common.c b/src/Common/libzip/zip_source_file_common.c index 74e21009..e92a43b3 100644 --- a/src/Common/libzip/zip_source_file_common.c +++ b/src/Common/libzip/zip_source_file_common.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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->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; - - /* 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); + 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->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; + } + } + } + + 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->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->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; case ZIP_SOURCE_READ: { - zip_int64_t i; - zip_uint64_t n; - - 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; - - return i; + zip_int64_t i; + zip_uint64_t n; + + 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; + + 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/src/Common/libzip/zip_source_file_stdio.c b/src/Common/libzip/zip_source_file_stdio.c index 4a22f78c..c4e3f8a1 100644 --- a/src/Common/libzip/zip_source_file_stdio.c +++ b/src/Common/libzip/zip_source_file_stdio.c @@ -3,7 +3,7 @@ Copyright (C) 2020 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_file_stdio.h b/src/Common/libzip/zip_source_file_stdio.h index 1bf698ce..87436b69 100644 --- a/src/Common/libzip/zip_source_file_stdio.h +++ b/src/Common/libzip/zip_source_file_stdio.h @@ -6,7 +6,7 @@ Copyright (C) 2020 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/src/Common/libzip/zip_source_file_stdio_named.c b/src/Common/libzip/zip_source_file_stdio_named.c new file mode 100644 index 00000000..92ae344a --- /dev/null +++ b/src/Common/libzip/zip_source_file_stdio_named.c @@ -0,0 +1,361 @@ +/* + zip_source_file_stdio_named.c -- source for stdio file opened by name + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#include "zip_source_file.h" +#include "zip_source_file_stdio.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_CLONEFILE +#include +#include +#define CAN_CLONE +#endif +#ifdef HAVE_FICLONERANGE +#include +#include +#define CAN_CLONE +#endif + +static int create_temp_file(zip_source_file_context_t *ctx, bool create_file); + +static zip_int64_t _zip_stdio_op_commit_write(zip_source_file_context_t *ctx); +static zip_int64_t _zip_stdio_op_create_temp_output(zip_source_file_context_t *ctx); +#ifdef CAN_CLONE +static zip_int64_t _zip_stdio_op_create_temp_output_cloning(zip_source_file_context_t *ctx, zip_uint64_t offset); +#endif +static bool _zip_stdio_op_open(zip_source_file_context_t *ctx); +static zip_int64_t _zip_stdio_op_remove(zip_source_file_context_t *ctx); +static void _zip_stdio_op_rollback_write(zip_source_file_context_t *ctx); +static char *_zip_stdio_op_strdup(zip_source_file_context_t *ctx, const char *string); +static zip_int64_t _zip_stdio_op_write(zip_source_file_context_t *ctx, const void *data, zip_uint64_t len); + +/* clang-format off */ +static zip_source_file_operations_t ops_stdio_named = { + _zip_stdio_op_close, + _zip_stdio_op_commit_write, + _zip_stdio_op_create_temp_output, +#ifdef CAN_CLONE + _zip_stdio_op_create_temp_output_cloning, +#else + NULL, +#endif + _zip_stdio_op_open, + _zip_stdio_op_read, + _zip_stdio_op_remove, + _zip_stdio_op_rollback_write, + _zip_stdio_op_seek, + _zip_stdio_op_stat, + _zip_stdio_op_strdup, + _zip_stdio_op_tell, + _zip_stdio_op_write +}; +/* clang-format on */ + +ZIP_EXTERN zip_source_t * +zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len) { + if (za == NULL) + return NULL; + + return zip_source_file_create(fname, start, len, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_file_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; + } + + return zip_source_file_common_new(fname, NULL, start, length, NULL, &ops_stdio_named, NULL, error); +} + + +static zip_int64_t +_zip_stdio_op_commit_write(zip_source_file_context_t *ctx) { + if (fclose(ctx->fout) < 0) { + zip_error_set(&ctx->error, ZIP_ER_WRITE, errno); + return -1; + } + if (rename(ctx->tmpname, ctx->fname) < 0) { + zip_error_set(&ctx->error, ZIP_ER_RENAME, errno); + return -1; + } + + return 0; +} + + +static zip_int64_t +_zip_stdio_op_create_temp_output(zip_source_file_context_t *ctx) { + int fd = create_temp_file(ctx, true); + + if (fd < 0) { + return -1; + } + + if ((ctx->fout = fdopen(fd, "r+b")) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + close(fd); + (void)remove(ctx->tmpname); + free(ctx->tmpname); + ctx->tmpname = NULL; + return -1; + } + + return 0; +} + +#ifdef CAN_CLONE +static zip_int64_t +_zip_stdio_op_create_temp_output_cloning(zip_source_file_context_t *ctx, zip_uint64_t offset) { + FILE *tfp; + + if (offset > ZIP_OFF_MAX) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, E2BIG); + return -1; + } + +#ifdef HAVE_CLONEFILE + /* clonefile insists on creating the file, so just create a name */ + if (create_temp_file(ctx, false) < 0) { + return -1; + } + + if (clonefile(ctx->fname, ctx->tmpname, 0) < 0) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + free(ctx->tmpname); + ctx->tmpname = NULL; + return -1; + } + if ((tfp = _zip_fopen_close_on_exec(ctx->tmpname, true)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + (void)remove(ctx->tmpname); + free(ctx->tmpname); + ctx->tmpname = NULL; + return -1; + } +#else + { + int fd; + struct file_clone_range range; + struct stat st; + + if (fstat(fileno(ctx->f), &st) < 0) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + return -1; + } + + if ((fd = create_temp_file(ctx, true)) < 0) { + return -1; + } + + range.src_fd = fileno(ctx->f); + range.src_offset = 0; + range.src_length = ((offset + st.st_blksize - 1) / st.st_blksize) * st.st_blksize; + if (range.src_length > st.st_size) { + range.src_length = 0; + } + range.dest_offset = 0; + if (ioctl(fd, FICLONERANGE, &range) < 0) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + (void)close(fd); + (void)remove(ctx->tmpname); + free(ctx->tmpname); + ctx->tmpname = NULL; + return -1; + } + + if ((tfp = fdopen(fd, "r+b")) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + (void)close(fd); + (void)remove(ctx->tmpname); + free(ctx->tmpname); + ctx->tmpname = NULL; + return -1; + } + } +#endif + + if (ftruncate(fileno(tfp), (off_t)offset) < 0) { + (void)fclose(tfp); + (void)remove(ctx->tmpname); + free(ctx->tmpname); + ctx->tmpname = NULL; + return -1; + } + if (fseeko(tfp, (off_t)offset, SEEK_SET) < 0) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + (void)fclose(tfp); + (void)remove(ctx->tmpname); + free(ctx->tmpname); + ctx->tmpname = NULL; + return -1; + } + + ctx->fout = tfp; + + return 0; +} +#endif + +static bool +_zip_stdio_op_open(zip_source_file_context_t *ctx) { + if ((ctx->f = _zip_fopen_close_on_exec(ctx->fname, false)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_OPEN, errno); + return false; + } + return true; +} + + +static zip_int64_t +_zip_stdio_op_remove(zip_source_file_context_t *ctx) { + if (remove(ctx->fname) < 0) { + zip_error_set(&ctx->error, ZIP_ER_REMOVE, errno); + return -1; + } + return 0; +} + + +static void +_zip_stdio_op_rollback_write(zip_source_file_context_t *ctx) { + if (ctx->fout) { + fclose(ctx->fout); + } + (void)remove(ctx->tmpname); +} + +static char * +_zip_stdio_op_strdup(zip_source_file_context_t *ctx, const char *string) { + return strdup(string); +} + + +static zip_int64_t +_zip_stdio_op_write(zip_source_file_context_t *ctx, const void *data, zip_uint64_t len) { + size_t ret; + + clearerr((FILE *)ctx->fout); + ret = fwrite(data, 1, len, (FILE *)ctx->fout); + if (ret != len || ferror((FILE *)ctx->fout)) { + zip_error_set(&ctx->error, ZIP_ER_WRITE, errno); + return -1; + } + + return (zip_int64_t)ret; +} + + +static int create_temp_file(zip_source_file_context_t *ctx, bool create_file) { + char *temp; + int mode; + struct stat st; + int fd; + char *start, *end; + + if (stat(ctx->fname, &st) == 0) { + mode = st.st_mode; + } + else { + mode = -1; + } + + if ((temp = (char *)malloc(strlen(ctx->fname) + 13)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; + } + sprintf(temp, "%s.XXXXXX.part", ctx->fname); + end = temp + strlen(temp) - 5; + start = end - 6; + + for (;;) { + zip_uint32_t value = zip_random_uint32(); + char *xs = start; + + while (xs < end) { + char digit = value % 36; + if (digit < 10) { + *(xs++) = digit + '0'; + } + else { + *(xs++) = digit - 10 + 'a'; + } + value /= 36; + } + + if (create_file) { + if ((fd = open(temp, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, mode == -1 ? 0666 : (mode_t)mode)) >= 0) { + if (mode != -1) { + /* open() honors umask(), which we don't want in this case */ +#ifdef HAVE_FCHMOD + (void)fchmod(fd, (mode_t)mode); +#else + (void)chmod(temp, (mode_t)mode); +#endif + } + break; + } + if (errno != EEXIST) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + free(temp); + return -1; + } + } + else { + if (stat(temp, &st) < 0) { + if (errno == ENOENT) { + break; + } + else { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + free(temp); + return -1; + } + } + } + } + + ctx->tmpname = temp; + + return create_file ? fd : 0; +} diff --git a/src/Common/libzip/zip_source_file_win32.c b/src/Common/libzip/zip_source_file_win32.c index 2fe838f1..4708dc85 100644 --- a/src/Common/libzip/zip_source_file_win32.c +++ b/src/Common/libzip/zip_source_file_win32.c @@ -1,9 +1,9 @@ /* zip_source_file_win32.c -- read-only Windows file source implementation - Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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; } @@ -112,7 +115,7 @@ _zip_win32_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, break; default: zip_error_set(&ctx->error, ZIP_ER_SEEK, EINVAL); - return -1; + return false; } li.QuadPart = (LONGLONG)offset; @@ -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; @@ -180,11 +184,11 @@ _zip_stat_win32(zip_source_file_context_t *ctx, zip_source_file_stat_t *st, HAND zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError())); return false; } - if (_zip_filetime_to_time_t(mtimeft, &mtime) < 0) { + if (!_zip_filetime_to_time_t(mtimeft, &mtime)) { 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/src/Common/libzip/zip_source_file_win32.h b/src/Common/libzip/zip_source_file_win32.h index 5092e630..f0123267 100644 --- a/src/Common/libzip/zip_source_file_win32.h +++ b/src/Common/libzip/zip_source_file_win32.h @@ -6,7 +6,7 @@ Copyright (C) 2020 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_file_win32_ansi.c b/src/Common/libzip/zip_source_file_win32_ansi.c new file mode 100644 index 00000000..9b8f1805 --- /dev/null +++ b/src/Common/libzip/zip_source_file_win32_ansi.c @@ -0,0 +1,85 @@ +/* + zip_source_file_win32_ansi.c -- source for Windows file opened by ANSI name + Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zip_source_file_win32.h" + +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, + DeleteFileA, + GetFileAttributesA, + GetFileAttributesExA, + ansi_make_tempname, + MoveFileExA, + SetFileAttributesA, + 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 zip_source_win32a_create(fname, start, len, &za->error); +} + + +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; + } + + return zip_source_file_common_new(fname, NULL, start, length, NULL, &_zip_source_file_win32_named_ops, &ops_ansi, error); +} + + +static char * +ansi_allocate_tempname(const char *name, size_t extra_chars, size_t *lengthp) { + *lengthp = strlen(name) + extra_chars; + return (char *)malloc(*lengthp); +} + + +static void +ansi_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i) { + snprintf(buf, len, "%s.%08x", name, i); +} diff --git a/src/Common/libzip/zip_source_file_win32_named.c b/src/Common/libzip/zip_source_file_win32_named.c index 63791f8e..d1547284 100644 --- a/src/Common/libzip/zip_source_file_win32_named.c +++ b/src/Common/libzip/zip_source_file_win32_named.c @@ -3,7 +3,7 @@ Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -65,13 +65,13 @@ 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; - + DWORD attributes; + if (!CloseHandle((HANDLE)ctx->fout)) { zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError())); return -1; } - + 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())); @@ -109,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; - } - } - - #ifndef MS_UWP + 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 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; } @@ -157,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; } @@ -194,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)) { @@ -206,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; @@ -236,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; } @@ -249,8 +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; - + HANDLE h; + if (temporary) { access = GENERIC_READ | GENERIC_WRITE; share_mode = FILE_SHARE_READ; @@ -259,7 +266,7 @@ win32_named_open(zip_source_file_context_t *ctx, const char *name, bool temporar } 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/src/Common/libzip/zip_source_file_win32_utf16.c b/src/Common/libzip/zip_source_file_win32_utf16.c index 83786483..08443d3d 100644 --- a/src/Common/libzip/zip_source_file_win32_utf16.c +++ b/src/Common/libzip/zip_source_file_win32_utf16.c @@ -3,7 +3,7 @@ Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -33,20 +33,13 @@ #include "zip_source_file_win32.h" -#define RtlGenRandom SystemFunction036 -BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength); - -bool zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) -{ - return RtlGenRandom (buffer, (ULONG) length); -} - - static char *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 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, @@ -59,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); } @@ -71,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; } @@ -87,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; @@ -97,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/src/Common/libzip/zip_source_file_win32_utf8.c b/src/Common/libzip/zip_source_file_win32_utf8.c index 4f258bc4..687c30f9 100644 --- a/src/Common/libzip/zip_source_file_win32_utf8.c +++ b/src/Common/libzip/zip_source_file_win32_utf8.c @@ -3,7 +3,7 @@ Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_free.c b/src/Common/libzip/zip_source_free.c index 2f10ef8f..1a800405 100644 --- a/src/Common/libzip/zip_source_free.c +++ b/src/Common/libzip/zip_source_free.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_function.c b/src/Common/libzip/zip_source_function.c index d5c1b5b0..e4eac9df 100644 --- a/src/Common/libzip/zip_source_function.c +++ b/src/Common/libzip/zip_source_function.c @@ -1,9 +1,9 @@ /* zip_source_function.c -- create zip data source from callback function - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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); + zs->supports = zcb(ud, NULL, 0, ZIP_SOURCE_SUPPORTS) | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, -1); 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/src/Common/libzip/zip_source_get_file_attributes.c b/src/Common/libzip/zip_source_get_file_attributes.c index acbede1d..df7ad584 100644 --- a/src/Common/libzip/zip_source_get_file_attributes.c +++ b/src/Common/libzip/zip_source_get_file_attributes.c @@ -3,7 +3,7 @@ Copyright (C) 2020 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_is_deleted.c b/src/Common/libzip/zip_source_is_deleted.c index edd10ca2..838aa909 100644 --- a/src/Common/libzip/zip_source_is_deleted.c +++ b/src/Common/libzip/zip_source_is_deleted.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/src/Common/libzip/zip_source_layered.c b/src/Common/libzip/zip_source_layered.c index d02bc852..3c21441a 100644 --- a/src/Common/libzip/zip_source_layered.c +++ b/src/Common/libzip/zip_source_layered.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_open.c b/src/Common/libzip/zip_source_open.c index 414c677a..7116beff 100644 --- a/src/Common/libzip/zip_source_open.c +++ b/src/Common/libzip/zip_source_open.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_pkware_decode.c b/src/Common/libzip/zip_source_pkware_decode.c index c85b590c..01b6417e 100644 --- a/src/Common/libzip/zip_source_pkware_decode.c +++ b/src/Common/libzip/zip_source_pkware_decode.c @@ -3,7 +3,7 @@ Copyright (C) 2009-2020 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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,23 +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; + 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: @@ -106,25 +106,23 @@ decrypt_header(zip_source_t *src, struct trad_pkware *ctx) { * CRC - old PKWare way */ - 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; @@ -140,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; } } @@ -195,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); @@ -214,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/src/Common/libzip/zip_source_pkware_encode.c b/src/Common/libzip/zip_source_pkware_encode.c index 1e8f42c3..5958af40 100644 --- a/src/Common/libzip/zip_source_pkware_encode.c +++ b/src/Common/libzip/zip_source_pkware_encode.c @@ -3,7 +3,7 @@ Copyright (C) 2009-2020 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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; - - return 0; + 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; } 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/src/Common/libzip/zip_source_read.c b/src/Common/libzip/zip_source_read.c index 33088cb1..0938fcb0 100644 --- a/src/Common/libzip/zip_source_read.c +++ b/src/Common/libzip/zip_source_read.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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 == 0) { - src->eof = 1; - break; - } - - bytes_read += (zip_uint64_t)n; + 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; + } + + 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/src/Common/libzip/zip_source_remove.c b/src/Common/libzip/zip_source_remove.c index 14eddb8f..c94fa1ef 100644 --- a/src/Common/libzip/zip_source_remove.c +++ b/src/Common/libzip/zip_source_remove.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_rollback_write.c b/src/Common/libzip/zip_source_rollback_write.c index e8259bff..13aa097b 100644 --- a/src/Common/libzip/zip_source_rollback_write.c +++ b/src/Common/libzip/zip_source_rollback_write.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_seek.c b/src/Common/libzip/zip_source_seek.c index 163daf1b..e3baad5a 100644 --- a/src/Common/libzip/zip_source_seek.c +++ b/src/Common/libzip/zip_source_seek.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_seek_write.c b/src/Common/libzip/zip_source_seek_write.c index 6b0aa78e..30f16432 100644 --- a/src/Common/libzip/zip_source_seek_write.c +++ b/src/Common/libzip/zip_source_seek_write.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_stat.c b/src/Common/libzip/zip_source_stat.c index 3421d2cb..e7954e72 100644 --- a/src/Common/libzip/zip_source_stat.c +++ b/src/Common/libzip/zip_source_stat.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_supports.c b/src/Common/libzip/zip_source_supports.c index 84715598..ff8e4786 100644 --- a/src/Common/libzip/zip_source_supports.c +++ b/src/Common/libzip/zip_source_supports.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_tell.c b/src/Common/libzip/zip_source_tell.c index 772e2524..49057ce5 100644 --- a/src/Common/libzip/zip_source_tell.c +++ b/src/Common/libzip/zip_source_tell.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_tell_write.c b/src/Common/libzip/zip_source_tell_write.c index 96ad7e26..4b96535a 100644 --- a/src/Common/libzip/zip_source_tell_write.c +++ b/src/Common/libzip/zip_source_tell_write.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_window.c b/src/Common/libzip/zip_source_window.c index d996015d..7e4d8ed6 100644 --- a/src/Common/libzip/zip_source_window.c +++ b/src/Common/libzip/zip_source_window.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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; + if (length == -1) { + ctx->end_valid = false; + } + else { + 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)); + memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes)); } else { - zip_file_attributes_init(&ctx->attributes); + 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 ((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 (!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; - } - - 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); - } - - ctx->offset = ctx->start; - return 0; + 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, 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 (!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; + } + } + + byte_array_fini(b); + } + + ctx->offset = ctx->start; + return 0; case ZIP_SOURCE_READ: - if (len > ctx->end - ctx->offset) - len = ctx->end - ctx->offset; - - 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 ((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; - - if (ret == 0) { - if (ctx->offset < ctx->end) { - zip_error_set(&ctx->error, ZIP_ER_EOF, 0); - return -1; - } - } - return ret; + if (ctx->end_valid && len > ctx->end - ctx->offset) { + len = ctx->end - ctx->offset; + } + + 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 ((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; + + 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); - - if (new_offset < 0) { - return -1; - } - - ctx->offset = (zip_uint64_t)new_offset + ctx->start; - return 0; + 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; + } + } + + 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/src/Common/libzip/zip_source_winzip_aes_decode.c b/src/Common/libzip/zip_source_winzip_aes_decode.c new file mode 100644 index 00000000..a3d978d5 --- /dev/null +++ b/src/Common/libzip/zip_source_winzip_aes_decode.c @@ -0,0 +1,265 @@ +/* + zip_source_winzip_aes_decode.c -- Winzip AES decryption routines + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + +struct winzip_aes { + char *password; + zip_uint16_t encryption_method; + + zip_uint64_t data_length; + zip_uint64_t current_position; + + zip_winzip_aes_t *aes_ctx; + zip_error_t error; +}; + + +static int decrypt_header(zip_source_t *src, struct winzip_aes *ctx); +static void winzip_aes_free(struct winzip_aes *); +static zip_int64_t winzip_aes_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd); +static struct winzip_aes *winzip_aes_new(zip_uint16_t encryption_method, const char *password, zip_error_t *error); + + +zip_source_t * +zip_source_winzip_aes_decode(zip_t *za, zip_source_t *src, zip_uint16_t encryption_method, int flags, const char *password) { + zip_source_t *s2; + zip_stat_t st; + zip_uint64_t aux_length; + 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; + } + if (flags & ZIP_CODEC_ENCODE) { + 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; + } + + 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; + } + + if ((ctx = winzip_aes_new(encryption_method, password, &za->error)) == 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; + } + + return s2; +} + + +static int +decrypt_header(zip_source_t *src, struct winzip_aes *ctx) { + zip_uint8_t header[WINZIP_AES_MAX_HEADER_LENGTH]; + zip_uint8_t password_verification[WINZIP_AES_PASSWORD_VERIFY_LENGTH]; + unsigned int headerlen; + zip_int64_t n; + + 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; + } + + if (n != headerlen) { + 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; + } + 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; + } + return 0; +} + + +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; + } + + if (!_zip_winzip_aes_finish(ctx->aes_ctx, computed)) { + 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; + } + + return true; +} + + +static zip_int64_t +winzip_aes_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { + struct winzip_aes *ctx; + zip_int64_t n; + + ctx = (struct winzip_aes *)ud; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + 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 == 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 (!_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; + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: { + zip_stat_t *st; + + 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); + } + + 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); + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); + + case ZIP_SOURCE_FREE: + winzip_aes_free(ctx); + return 0; + + default: + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } +} + + +static void +winzip_aes_free(struct winzip_aes *ctx) { + if (ctx == NULL) { + return; + } + + _zip_crypto_clear(ctx->password, strlen(ctx->password)); + free(ctx->password); + zip_error_fini(&ctx->error); + _zip_winzip_aes_free(ctx->aes_ctx); + free(ctx); +} + + +static struct winzip_aes * +winzip_aes_new(zip_uint16_t encryption_method, const char *password, zip_error_t *error) { + struct winzip_aes *ctx; + + if ((ctx = (struct winzip_aes *)malloc(sizeof(*ctx))) == 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; + } + + ctx->encryption_method = encryption_method; + ctx->aes_ctx = NULL; + + zip_error_init(&ctx->error); + + return ctx; +} diff --git a/src/Common/libzip/zip_source_winzip_aes_encode.c b/src/Common/libzip/zip_source_winzip_aes_encode.c new file mode 100644 index 00000000..73586bab --- /dev/null +++ b/src/Common/libzip/zip_source_winzip_aes_encode.c @@ -0,0 +1,254 @@ +/* + zip_source_winzip_aes_encode.c -- Winzip AES encryption routines + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + + +struct winzip_aes { + char *password; + zip_uint16_t encryption_method; + + zip_uint8_t data[ZIP_MAX(WINZIP_AES_MAX_HEADER_LENGTH, SHA1_LENGTH)]; + zip_buffer_t *buffer; + + zip_winzip_aes_t *aes_ctx; + bool eof; + zip_error_t error; +}; + + +static int encrypt_header(zip_source_t *src, struct winzip_aes *ctx); +static void winzip_aes_free(struct winzip_aes *); +static zip_int64_t winzip_aes_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd); +static struct winzip_aes *winzip_aes_new(zip_uint16_t encryption_method, const char *password, zip_error_t *error); + + +zip_source_t * +zip_source_winzip_aes_encode(zip_t *za, zip_source_t *src, zip_uint16_t encryption_method, int flags, const char *password) { + zip_source_t *s2; + 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; + } + + if ((ctx = winzip_aes_new(encryption_method, password, &za->error)) == NULL) { + return NULL; + } + + if ((s2 = zip_source_layered(za, src, winzip_aes_encrypt, ctx)) == NULL) { + winzip_aes_free(ctx); + return NULL; + } + + return s2; +} + + +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; + } + + 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; + } + + 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; + } + + return 0; +} + + +static zip_int64_t +winzip_aes_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length, zip_source_cmd_t cmd) { + struct winzip_aes *ctx; + zip_int64_t ret; + zip_uint64_t buffer_n; + + ctx = (struct winzip_aes *)ud; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + ctx->eof = false; + if (encrypt_header(src, ctx) < 0) { + return -1; + } + return 0; + + case ZIP_SOURCE_READ: + buffer_n = 0; + + if (ctx->buffer) { + 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 (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 (!_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); + } + + return (zip_int64_t)(buffer_n + (zip_uint64_t)ret); + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: { + 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); + } + + 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; + + 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); + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, length); + + case ZIP_SOURCE_FREE: + winzip_aes_free(ctx); + return 0; + + default: + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } +} + + +static void +winzip_aes_free(struct winzip_aes *ctx) { + if (ctx == NULL) { + return; + } + + _zip_crypto_clear(ctx->password, strlen(ctx->password)); + free(ctx->password); + zip_error_fini(&ctx->error); + _zip_buffer_free(ctx->buffer); + _zip_winzip_aes_free(ctx->aes_ctx); + free(ctx); +} + + +static struct winzip_aes * +winzip_aes_new(zip_uint16_t encryption_method, const char *password, zip_error_t *error) { + struct winzip_aes *ctx; + + if ((ctx = (struct winzip_aes *)malloc(sizeof(*ctx))) == 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; + } + + ctx->encryption_method = encryption_method; + ctx->buffer = NULL; + ctx->aes_ctx = NULL; + + zip_error_init(&ctx->error); + + ctx->eof = false; + return ctx; +} diff --git a/src/Common/libzip/zip_source_write.c b/src/Common/libzip/zip_source_write.c index 73fc3a31..24dde9b2 100644 --- a/src/Common/libzip/zip_source_write.c +++ b/src/Common/libzip/zip_source_write.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_source_zip.c b/src/Common/libzip/zip_source_zip.c index 8a7feaa4..737fa4d3 100644 --- a/src/Common/libzip/zip_source_zip.c +++ b/src/Common/libzip/zip_source_zip.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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; + flags &= ~ZIP_FL_COMPRESSED; + + return _zip_source_zip_new(srcza, srcidx, flags, start, (zip_uint64_t)len, NULL, error); +} + - return _zip_source_zip_new(za, srcza, srcidx, flags, start, (zip_uint64_t)len, NULL); +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/src/Common/libzip/zip_source_zip_new.c b/src/Common/libzip/zip_source_zip_new.c index 6d547f0e..68394b78 100644 --- a/src/Common/libzip/zip_source_zip_new.c +++ b/src/Common/libzip/zip_source_zip_new.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_stat.c b/src/Common/libzip/zip_stat.c index 341c6f77..51d8026d 100644 --- a/src/Common/libzip/zip_stat.c +++ b/src/Common/libzip/zip_stat.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_stat_index.c b/src/Common/libzip/zip_stat_index.c index 71f80491..fb532ec1 100644 --- a/src/Common/libzip/zip_stat_index.c +++ b/src/Common/libzip/zip_stat_index.c @@ -3,7 +3,7 @@ Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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); - - 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; + 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->index = index; diff --git a/src/Common/libzip/zip_stat_init.c b/src/Common/libzip/zip_stat_init.c index 6d0903d6..9c6088a7 100644 --- a/src/Common/libzip/zip_stat_init.c +++ b/src/Common/libzip/zip_stat_init.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_strerror.c b/src/Common/libzip/zip_strerror.c index 906c7f76..7d827931 100644 --- a/src/Common/libzip/zip_strerror.c +++ b/src/Common/libzip/zip_strerror.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/src/Common/libzip/zip_string.c b/src/Common/libzip/zip_string.c index 122721d8..570a8fac 100644 --- a/src/Common/libzip/zip_string.c +++ b/src/Common/libzip/zip_string.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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); - - 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; - } + /* 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 (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/src/Common/libzip/zip_unchange.c b/src/Common/libzip/zip_unchange.c index 1a78e2c3..d69a3dfe 100644 --- a/src/Common/libzip/zip_unchange.c +++ b/src/Common/libzip/zip_unchange.c @@ -1,9 +1,9 @@ /* zip_unchange.c -- undo changes to file in zip archive - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -46,42 +46,47 @@ zip_unchange(zip_t *za, zip_uint64_t idx) { int _zip_unchange(zip_t *za, zip_uint64_t idx, int allow_duplicates) { zip_int64_t i; - const char *orig_name, *changed_name; + bool renamed; 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; - } - - 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 (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; - } + renamed = za->entry[idx].changes && (za->entry[idx].changes->changed & ZIP_DIRENT_FILENAME); + if (!allow_duplicates && (renamed || za->entry[idx].deleted)) { + const char *orig_name = NULL; + const char *changed_name = NULL; + + 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; + } + } + + if (renamed) { + 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 (changed_name) { + 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/src/Common/libzip/zip_unchange_all.c b/src/Common/libzip/zip_unchange_all.c index 2ae742f8..34f3702e 100644 --- a/src/Common/libzip/zip_unchange_all.c +++ b/src/Common/libzip/zip_unchange_all.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_unchange_archive.c b/src/Common/libzip/zip_unchange_archive.c index bd223ef5..56a8e31f 100644 --- a/src/Common/libzip/zip_unchange_archive.c +++ b/src/Common/libzip/zip_unchange_archive.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_unchange_data.c b/src/Common/libzip/zip_unchange_data.c index 74a429c9..6bdecd18 100644 --- a/src/Common/libzip/zip_unchange_data.c +++ b/src/Common/libzip/zip_unchange_data.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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/src/Common/libzip/zip_utf-8.c b/src/Common/libzip/zip_utf-8.c index 099db9bf..678912f6 100644 --- a/src/Common/libzip/zip_utf-8.c +++ b/src/Common/libzip/zip_utf-8.c @@ -1,9 +1,9 @@ /* 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 + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -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_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; - } - - 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; - } + 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; + } + + 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; + } } 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/src/Common/libzip/zip_winzip_aes.c b/src/Common/libzip/zip_winzip_aes.c new file mode 100644 index 00000000..74a003f6 --- /dev/null +++ b/src/Common/libzip/zip_winzip_aes.c @@ -0,0 +1,162 @@ +/* + zip_winzip_aes.c -- Winzip AES de/encryption backend routines + 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 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#include "zip_crypto.h" + +#include +#include + + +#define MAX_KEY_LENGTH 256 +#define PBKDF2_ITERATIONS 1000 + +struct _zip_winzip_aes { + _zip_crypto_aes_t *aes; + _zip_crypto_hmac_t *hmac; + zip_uint8_t counter[ZIP_CRYPTO_AES_BLOCK_LENGTH]; + zip_uint8_t pad[ZIP_CRYPTO_AES_BLOCK_LENGTH]; + int pad_offset; +}; + +static bool +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++]; + } + + return true; +} + + +zip_winzip_aes_t * +_zip_winzip_aes_new(const zip_uint8_t *password, zip_uint64_t password_length, const zip_uint8_t *salt, zip_uint16_t encryption_method, zip_uint8_t *password_verify, zip_error_t *error) { + zip_winzip_aes_t *ctx; + zip_uint8_t buffer[2 * (MAX_KEY_LENGTH / 8) + WINZIP_AES_PASSWORD_VERIFY_LENGTH]; + zip_uint16_t key_size = 0; /* in bits */ + zip_uint16_t key_length; /* in bytes */ + + switch (encryption_method) { + case ZIP_EM_AES_128: + key_size = 128; + break; + case ZIP_EM_AES_192: + key_size = 192; + break; + case ZIP_EM_AES_256: + 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; + } + + 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; + } + + 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; + } + + if ((ctx->aes = _zip_crypto_aes_new(buffer, key_size, error)) == 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; + } + + if (password_verify) { + memcpy(password_verify, buffer + (2 * key_size / 8), WINZIP_AES_PASSWORD_VERIFY_LENGTH); + } + + return ctx; +} + + +bool +_zip_winzip_aes_encrypt(zip_winzip_aes_t *ctx, zip_uint8_t *data, zip_uint64_t length) { + return aes_crypt(ctx, data, length) && _zip_crypto_hmac(ctx->hmac, data, length); +} + + +bool +_zip_winzip_aes_decrypt(zip_winzip_aes_t *ctx, zip_uint8_t *data, zip_uint64_t length) { + return _zip_crypto_hmac(ctx->hmac, data, length) && aes_crypt(ctx, data, length); +} + + +bool +_zip_winzip_aes_finish(zip_winzip_aes_t *ctx, zip_uint8_t *hmac) { + return _zip_crypto_hmac_output(ctx->hmac, hmac); +} + + +void +_zip_winzip_aes_free(zip_winzip_aes_t *ctx) { + if (ctx == NULL) { + return; + } + + _zip_crypto_aes_free(ctx->aes); + _zip_crypto_hmac_free(ctx->hmac); + free(ctx); +} diff --git a/src/Common/libzip/zipconf.h b/src/Common/libzip/zipconf.h index e4224da2..00689335 100644 --- a/src/Common/libzip/zipconf.h +++ b/src/Common/libzip/zipconf.h @@ -1,40 +1,52 @@ -/* - This file was generated automatically by C:\dev\prj\Github\VeraCrypt\src\Common\libzip\make_zip_err_str.sh - from C:\dev\libraries\libzip\build\config.h; make changes there. - */ - #ifndef _HAD_ZIPCONF_H #define _HAD_ZIPCONF_H -extern const char * const _zip_err_str[]; - -extern const int _zip_nerr_str; - -#define N ZIP_ET_NONE -#define S ZIP_ET_SYS -#define Z ZIP_ET_ZLIB - -extern const int _zip_err_type[]; - +/* + zipconf.h -- platform specific include file -typedef signed char zip_int8_t; -typedef unsigned char zip_uint8_t; -typedef signed short zip_int16_t; -typedef unsigned short zip_uint16_t; -typedef signed int zip_int32_t; -typedef unsigned int zip_uint32_t; -typedef signed long long zip_int64_t; -typedef unsigned long long zip_uint64_t; + This file was generated automatically by CMake + based on ../cmake-zipconf.h.in. + */ -#define ZIP_INT8_MIN -0x80 +#define LIBZIP_VERSION "1.9.2" +#define LIBZIP_VERSION_MAJOR 1 +#define LIBZIP_VERSION_MINOR 9 +#define LIBZIP_VERSION_MICRO 2 + +/* #undef ZIP_STATIC */ + +#define _Nullable +#define _Nonnull + +#if !defined(__STDC_FORMAT_MACROS) +#define __STDC_FORMAT_MACROS 1 +#endif +#if defined(_MSC_VER) && _MSC_VER < 1700 +#include +#define PRIu32 "lu" +#define PRIu64 "llu" +#else +#include +#endif + +typedef int8_t zip_int8_t; +typedef uint8_t zip_uint8_t; +typedef int16_t zip_int16_t; +typedef uint16_t zip_uint16_t; +typedef int32_t zip_int32_t; +typedef uint32_t zip_uint32_t; +typedef int64_t zip_int64_t; +typedef uint64_t zip_uint64_t; + +#define ZIP_INT8_MIN (-ZIP_INT8_MAX-1) #define ZIP_INT8_MAX 0x7f #define ZIP_UINT8_MAX 0xff -#define ZIP_INT16_MIN -0x8000 +#define ZIP_INT16_MIN (-ZIP_INT16_MAX-1) #define ZIP_INT16_MAX 0x7fff #define ZIP_UINT16_MAX 0xffff -#define ZIP_INT32_MIN -0x80000000L +#define ZIP_INT32_MIN (-ZIP_INT32_MAX-1L) #define ZIP_INT32_MAX 0x7fffffffL #define ZIP_UINT32_MAX 0xffffffffLU @@ -43,4 +55,3 @@ typedef unsigned long long zip_uint64_t; #define ZIP_UINT64_MAX 0xffffffffffffffffULL #endif /* zipconf.h */ - diff --git a/src/Common/libzip/zipint.h b/src/Common/libzip/zipint.h index 5f504ca9..75942208 100644 --- a/src/Common/libzip/zipint.h +++ b/src/Common/libzip/zipint.h @@ -3,10 +3,10 @@ /* zipint.h -- internal declarations. - Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at + The authors can be contacted at Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -35,14 +35,13 @@ */ #include "config.h" + #include "compat.h" #ifdef ZIP_ALLOCATE_BUFFER #include #endif -#include - #ifndef _ZIP_COMPILING_DEPRECATED #define ZIP_DISABLE_DEPRECATED #endif @@ -123,6 +122,9 @@ enum zip_compression_status { typedef enum zip_compression_status zip_compression_status_t; struct zip_compression_algorithm { + /* Return maximum 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 */ @@ -134,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); @@ -155,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. */ @@ -167,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); @@ -175,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 */ @@ -336,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; @@ -347,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) @@ -421,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)) @@ -532,7 +576,7 @@ zip_hash_t *_zip_hash_new(zip_error_t *error); bool _zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t *error); bool _zip_hash_revert(zip_hash_t *hash, zip_error_t *error); -int _zip_mkstempm(char *path, int mode); +int _zip_mkstempm(char *path, int mode, bool create_file); zip_t *_zip_open(zip_source_t *, unsigned int, zip_error_t *); @@ -563,16 +607,16 @@ 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 *); -void _zip_string_free(zip_string_t *); -zip_uint32_t _zip_string_crc32(const zip_string_t *); -const zip_uint8_t *_zip_string_get(zip_string_t *, zip_uint32_t *, zip_flags_t, zip_error_t *); -zip_uint16_t _zip_string_length(const zip_string_t *); -zip_string_t *_zip_string_new(const zip_uint8_t *, zip_uint16_t, zip_flags_t, zip_error_t *); +int _zip_string_equal(const zip_string_t *a, const zip_string_t *b); +void _zip_string_free(zip_string_t *string); +zip_uint32_t _zip_string_crc32(const zip_string_t *string); +const zip_uint8_t *_zip_string_get(zip_string_t *string, zip_uint32_t *lenp, zip_flags_t flags, zip_error_t *error); +zip_uint16_t _zip_string_length(const zip_string_t *string); +zip_string_t *_zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags, zip_error_t *error); int _zip_string_write(zip_t *za, const zip_string_t *string); bool _zip_winzip_aes_decrypt(zip_winzip_aes_t *ctx, zip_uint8_t *data, zip_uint64_t length); bool _zip_winzip_aes_encrypt(zip_winzip_aes_t *ctx, zip_uint8_t *data, zip_uint64_t length); -- cgit v1.2.3