* Update LZMA to latest

* Update Libzip

Libzip updated to latest.
This commit is contained in:
DLL125 2023-07-17 14:11:12 +02:00 committed by GitHub
parent 6267b91931
commit 65765798d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
77 changed files with 1381 additions and 546 deletions

View File

@ -1,14 +1,32 @@
1.9.2 [2022-06-28]
# 1.10.0 [2023-06-23]
* Make support for layered sources public.
* Add `zip_source_zip_file` and `zip_source_zip_file_create`, deprecate `zip_source_zip` and `zip_source_zip_create`.
* Allow reading changed file data.
* Fix handling of files of size 4294967295.
* `zipmerge`: copy extra fields.
* `zipmerge`: add option to keep files uncompressed.
* Switch test framework to use nihtest instead of Perl.
* Fix reading/writing compressed data with buffers > 4GiB.
* Restore support for torrentzip.
* Add warnings when using deprecated functions.
* Allow keeping files for empty archives.
* Support mbedTLS>=3.3.0.
* Support OpenSSL 3.
* Use ISO C secure library functions, if available.
# 1.9.2 [2022-06-28]
* Fix version number in header file.
1.9.1 [2022-06-28]
===================
# 1.9.1 [2022-06-28]
* Fix `zip_file_is_seekable()`.
1.9.0 [2022-06-13]
==================
# 1.9.0 [2022-06-13]
* Add `zip_file_is_seekable()`.
* Improve compatibility with WinAES.
@ -16,8 +34,8 @@
* Add option to `zipcmp` to output summary of changes.
* Various bug fixes and documentation improvements.
1.8.0 [2021-06-18]
==================
# 1.8.0 [2021-06-18]
* Add support for zstd (Zstandard) compression.
* Add support for lzma (ID 14) compression.
@ -30,29 +48,29 @@
* In `zipcmp`, dont 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]
==================
# 1.7.3 [2020-07-15]
* Support cmake < 3.17 again.
* Fix pkgconfig file (regression in 1.7.2).
1.7.2 [2020-07-11]
==================
# 1.7.2 [2020-07-11]
* Fixes for the CMake `find_project()` files.
* libzip moved to the CMake `libzip::` `NAMESPACE`.
* CMake usage best practice cleanups.
1.7.1 [2020-06-13]
==================
# 1.7.1 [2020-06-13]
* Restore `LIBZIP_VERSION_{MAJOR,MINOR,MICRO}` symbols.
* Fixes warnings reported by PVS-Studio.
* Add `LIBZIP_DO_INSTALL` build setting to make it easier to use
libzip as subproject.
1.7.0 [2020-06-05]
==================
# 1.7.0 [2020-06-05]
* Add support for encrypting using traditional PKWare encryption.
* Add `zip_compression_method_supported()`.
@ -61,13 +79,13 @@
* Refactor stdio file backend.
* Add CMake find_project() support.
1.6.1 [2020-02-03]
==================
# 1.6.1 [2020-02-03]
* Bugfix for double-free in `zipcmp(1)` during cleanup.
1.6.0 [2020-01-24]
==================
# 1.6.0 [2020-01-24]
* Avoid using `umask()` since it's not thread-safe.
* Set close-on-exec flag when opening files.
@ -76,8 +94,8 @@
* Add support for cancelling while closing zip archives.
* Add support for setting the time in the on-disk format.
1.5.2 [2019-03-12]
==================
# 1.5.2 [2019-03-12]
* Fix bug in AES encryption affecting certain file sizes
* Keep file permissions when modifying zip archives
@ -85,8 +103,8 @@
* Support mbed TLS as crypto backend.
* Add nullability annotations.
1.5.1 [2018-04-11]
==================
# 1.5.1 [2018-04-11]
* Choose format of installed documentation based on available tools.
* Fix visibility of symbols.
@ -96,16 +114,16 @@
* Fix build with LibreSSL.
* Various bugfixes.
1.5.0 [2018-03-11]
==================
# 1.5.0 [2018-03-11]
* Use standard cryptographic library instead of custom AES implementation.
This also simplifies the license.
* Use `clang-format` to format the source code.
* More Windows improvements.
1.4.0 [2017-12-29]
==================
# 1.4.0 [2017-12-29]
* Improve build with cmake
* Retire autoconf/automake build system
@ -114,20 +132,20 @@
Supported for buffer sources and on Apple File System.
* Add support for Microsoft Universal Windows Platform.
1.3.2 [2017-11-20]
==================
# 1.3.2 [2017-11-20]
* Fix bug introduced in last: zip_t was erroneously freed if zip_close() failed.
1.3.1 [2017-11-19]
==================
# 1.3.1 [2017-11-19]
* Install zipconf.h into ${PREFIX}/include
* Add zip_libzip_version()
* Fix AES tests on Linux
1.3.0 [2017-09-02]
==================
# 1.3.0 [2017-09-02]
* Support bzip2 compressed zip archives
* Improve file progress callback code
@ -135,8 +153,8 @@
* CVE-2017-12858: Fix double free()
* CVE-2017-14107: Improve EOCD64 parsing
1.2.0 [2017-02-19]
==================
# 1.2.0 [2017-02-19]
* Support for AES encryption (Winzip version), both encryption
and decryption
@ -146,24 +164,24 @@
* Add zip_ftell() for telling position in uncompressed data
* Add zip_register_progress_callback() for UI updates during zip_close()
1.1.3 [2016-05-28]
==================
# 1.1.3 [2016-05-28]
* Fix build on Windows when using autoconf
1.1.2 [2016-02-19]
==================
# 1.1.2 [2016-02-19]
* Improve support for 3MF files
1.1.1 [2016-02-07]
==================
# 1.1.1 [2016-02-07]
* Build fixes for Linux
* Fix some warnings reported by PVS-Studio
1.1 [2016-01-26]
================
# 1.1 [2016-01-26]
* ziptool(1): command line tool to modify zip archives
* Speedups for archives with many entries
@ -174,13 +192,13 @@
* Portability fixes
* Documentation improvements
1.0.1 [2015-05-04]
==================
# 1.0.1 [2015-05-04]
* Build fixes for Windows
1.0 [2015-05-03]
================
# 1.0 [2015-05-03]
* Implemented an I/O abstraction layer
* Added support for native Windows API for files
@ -191,22 +209,22 @@
* CVE-2015-2331 was fixed
* Addressed all Coverity CIDs
0.11.2 [2013-12-19]
===================
# 0.11.2 [2013-12-19]
* Support querying/setting operating system and external attributes
* For newly added files, set operating system to UNIX, permissions
to 0666 (0777 for directories)
* Fix bug when writing zip archives containing files bigger than 4GB
0.11.1 [2013-04-27]
===================
# 0.11.1 [2013-04-27]
* Fix bugs in zip_set_file_compression()
* Include Xcode build infrastructure
0.11 [2013-03-23]
=================
# 0.11 [2013-03-23]
* Added Zip64 support (large file support)
* Added UTF-8 support for file names, file comments, and archive comments
@ -220,14 +238,14 @@
* More changes for Windows support
* Additional test cases
0.10.1 [2012-03-20]
===================
# 0.10.1 [2012-03-20]
* Fixed CVE-2012-1162
* Fixed CVE-2012-1163
0.10 [2010-03-18]
=================
# 0.10 [2010-03-18]
* Added zip_get_num_entries(), deprecated zip_get_num_files()
* Better windows support
@ -239,27 +257,27 @@
* Fixed CVE-2011-0421 (no security implications though)
* More documentation
0.9.3 [2010-02-01]
==================
# 0.9.3 [2010-02-01]
* Include m4/ directory in distribution; some packagers need it
0.9.2 [2010-01-31]
==================
# 0.9.2 [2010-01-31]
* Avoid passing uninitialized data to deflate()
* Fix memory leak when closing zip archives
0.9.1 [2010-01-24]
==================
# 0.9.1 [2010-01-24]
* Fix infinite loop on reading some broken files
* Optimization in time conversion (don't call localtime())
* Clear data descriptor flag in central directory, fixing Open Office files
* Allow more than 64k entries
0.9 [2008-07-25]
==================
# 0.9 [2008-07-25]
* on Windows, explicitly set dllimport/dllexport
* remove erroneous references to GPL
@ -268,8 +286,8 @@
* zip_source_zip: add flag to force recompression
* zip_sorce_file: only keep file open while reading from it
0.8 [2007-06-06]
==================
# 0.8 [2007-06-06]
* fix for zip archives larger than 2GiB
* fix zip_error_strerror to include libzip error string
@ -277,13 +295,13 @@
* new functions: zip_add_dir, zip_error_clear, zip_file_error_clear
* add basic support for building with CMake (incomplete)
0.7.1 [2006-05-18]
==================
# 0.7.1 [2006-05-18]
* bugfix for zip_close
0.7 [2006-05-06]
================
# 0.7 [2006-05-06]
* struct zip_stat increased for future encryption support
* zip_add return value changed (now returns new index of added file)
@ -292,13 +310,13 @@
New functions: zip_get_archive_comment, zip_get_file_comment,
zip_set_archive_comment, zip_set_file_comment, zip_unchange_archive
0.6.1 [2005-07-14]
==================
# 0.6.1 [2005-07-14]
* various bug fixes
0.6 [2005-06-09]
================
# 0.6 [2005-06-09]
* first standalone release
* changed license to three-clause BSD

View File

@ -41,6 +41,9 @@
/* to have *_MAX definitions for all types when compiling with g++ */
#define __STDC_LIMIT_MACROS
/* to have ISO C secure library functions */
#define __STDC_WANT_LIB_EXT1__ 1
#if defined(_WIN32) && defined(ZIP_DLL) && !defined(ZIP_STATIC)
#ifdef BUILDING_LIBZIP
#define ZIP_EXTERN __declspec(dllexport)
@ -100,6 +103,9 @@ typedef char bool;
#if !defined(HAVE_SNPRINTF) && defined(HAVE__SNPRINTF)
#define snprintf _snprintf
#endif
#if !defined(HAVE__SNWPRINTF_S)
#define _snwprintf_s(buf, bufsz, len, fmt, ...) (_snwprintf((buf), (len), (fmt), __VA_ARGS__))
#endif
#if defined(HAVE__STRDUP)
#if !defined(HAVE_STRDUP) || defined(_WIN32)
#undef strdup
@ -128,6 +134,33 @@ typedef char bool;
#define ftello(s) ((long)ftell((s)))
#endif
#ifdef HAVE_LOCALTIME_S
#ifdef _WIN32
/* Windows is incompatible to the C11 standard, hurray! */
#define zip_localtime(t, tm) (localtime_s((tm), (t)) == 0 ? tm : NULL)
#else
#define zip_localtime localtime_s
#endif
#else
#ifdef HAVE_LOCALTIME_R
#define zip_localtime localtime_r
#else
#define zip_localtime(t, tm) (localtime(t))
#endif
#endif
#ifndef HAVE_MEMCPY_S
#define memcpy_s(dest, destsz, src, count) (memcpy((dest), (src), (count)) == NULL)
#endif
#ifndef HAVE_SNPRINTF_S
#ifdef HAVE__SNPRINTF_S
#define snprintf_s(buf, bufsz, fmt, ...) (_snprintf_s((buf), (bufsz), (bufsz), (fmt), __VA_ARGS__))
#else
#define snprintf_s snprintf
#endif
#endif
#if !defined(HAVE_STRCASECMP)
#if defined(HAVE__STRICMP)
#define strcasecmp _stricmp
@ -136,6 +169,19 @@ typedef char bool;
#endif
#endif
#ifndef HAVE_STRNCPY_S
#define strncpy_s(dest, destsz, src, count) (strncpy((dest), (src), (count)), 0)
#endif
#ifndef HAVE_STRERROR_S
#define strerrorlen_s(errnum) (strlen(strerror(errnum)))
#define strerror_s(buf, bufsz, errnum) ((void)strncpy_s((buf), (bufsz), strerror(errnum), (bufsz)), (buf)[(bufsz)-1] = '\0', strerrorlen_s(errnum) >= (bufsz))
#else
#ifndef HAVE_STRERRORLEN_S
#define strerrorlen_s(errnum) 8192
#endif
#endif
#if SIZEOF_OFF_T == 8
#define ZIP_OFF_MAX ZIP_INT64_MAX
#define ZIP_OFF_MIN ZIP_INT64_MIN

View File

@ -4,6 +4,7 @@
#include "zipconf.h"
#endif
/* BEGIN DEFINES */
#define ENABLE_FDOPEN
/* #undef HAVE___PROGNAME */
#define HAVE__CLOSE
#define HAVE__DUP
@ -15,11 +16,12 @@
#else
/* #undef HAVE__SNPRINTF */
#endif
#define HAVE__SNPRINTF_S
#define HAVE__SNWPRINTF_S
#define HAVE__STRDUP
#define HAVE__STRICMP
#define HAVE__STRTOI64
#define HAVE__STRTOUI64
/* #undef HAVE__UMASK */
#define HAVE__UNLINK
/* #undef HAVE_ARC4RANDOM */
/* #undef HAVE_CLONEFILE */
@ -36,6 +38,8 @@
/* #undef HAVE_LIBLZMA */
/* #undef HAVE_LIBZSTD */
/* #undef HAVE_LOCALTIME_R */
#define HAVE_LOCALTIME_S
#define HAVE_MEMCPY_S
/* #undef HAVE_MBEDTLS */
/* #undef HAVE_MKSTEMP */
/* #undef HAVE_NULLABLE */
@ -46,9 +50,13 @@
#else
#define HAVE_SNPRINTF
#endif
/* #undef HAVE_SNPRINTF_S */
/* #undef HAVE_STRCASECMP */
#define HAVE_STRDUP
#define HAVE_STRERROR_S
/* #undef HAVE_STRERRORLEN_S */
#define HAVE_STRICMP
#define HAVE_STRNCPY_S
#if defined(_MSC_VER) && _MSC_VER < 1800
/* #undef HAVE_STRTOLL */
/* #undef HAVE_STRTOULL */
@ -80,6 +88,6 @@
#define HAVE_SHARED
/* END DEFINES */
#define PACKAGE "libzip"
#define VERSION "1.9.2"
#define VERSION "1.10.0"
#endif /* HAD_CONFIG_H */

View File

@ -62,6 +62,16 @@ extern "C" {
#endif
#endif
#ifndef ZIP_DEPRECATED
#if defined(__GNUC__) || defined(__clang__)
#define ZIP_DEPRECATED(x) __attribute__((deprecated(x)))
#elif defined(_MSC_VER)
#define ZIP_DEPRECATED(x) __declspec(deprecated(x))
#else
#define ZIP_DEPRECATED(x)
#endif
#endif
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
@ -81,7 +91,7 @@ extern "C" {
#define ZIP_FL_NODIR 2u /* ignore directory component */
#define ZIP_FL_COMPRESSED 4u /* read compressed data */
#define ZIP_FL_UNCHANGED 8u /* use original data, ignoring changes */
#define ZIP_FL_RECOMPRESS 16u /* force recompression of data */
/* 16u was ZIP_FL_RECOMPRESS, which is deprecated */
#define ZIP_FL_ENCRYPTED 32u /* read encrypted data (implies ZIP_FL_COMPRESSED) */
#define ZIP_FL_ENC_GUESS 0u /* guess string encoding (is default) */
#define ZIP_FL_ENC_RAW 64u /* get unmodified string */
@ -95,7 +105,10 @@ extern "C" {
/* archive global flags flags */
#define ZIP_AFL_RDONLY 2u /* read only -- cannot be cleared */
#define ZIP_AFL_RDONLY 2u /* read only -- cannot be cleared */
#define ZIP_AFL_IS_TORRENTZIP 4u /* current archive is torrentzipped */
#define ZIP_AFL_WANT_TORRENTZIP 8u /* write archive in torrentzip format */
#define ZIP_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE 16u /* don't remove file if archive is empty */
/* create a new extra field */
@ -139,6 +152,8 @@ extern "C" {
#define ZIP_ER_TELL 30 /* S Tell error */
#define ZIP_ER_COMPRESSED_DATA 31 /* N Compressed data invalid */
#define ZIP_ER_CANCELLED 32 /* N Operation cancelled */
#define ZIP_ER_DATA_LENGTH 33 /* N Unexpected length of data */
#define ZIP_ER_NOT_ALLOWED 34 /* N Not allowed in torrentzip */
/* type of system error value */
@ -240,7 +255,8 @@ enum zip_source_cmd {
ZIP_SOURCE_RESERVED_1, /* previously used internally */
ZIP_SOURCE_BEGIN_WRITE_CLONING, /* like ZIP_SOURCE_BEGIN_WRITE, but keep part of original file */
ZIP_SOURCE_ACCEPT_EMPTY, /* whether empty files are valid archives */
ZIP_SOURCE_GET_FILE_ATTRIBUTES /* get additional file attributes */
ZIP_SOURCE_GET_FILE_ATTRIBUTES, /* get additional file attributes */
ZIP_SOURCE_SUPPORTS_REOPEN /* allow reading from changed entry */
};
typedef enum zip_source_cmd zip_source_cmd_t;
@ -351,24 +367,29 @@ typedef struct zip_buffer_fragment zip_buffer_fragment_t;
typedef zip_uint32_t zip_flags_t;
typedef zip_int64_t (*zip_source_callback)(void *_Nullable, void *_Nullable, zip_uint64_t, zip_source_cmd_t);
typedef zip_int64_t (*zip_source_layered_callback)(zip_source_t *_Nonnull, void *_Nullable, void *_Nullable, zip_uint64_t, enum zip_source_cmd);
typedef void (*zip_progress_callback)(zip_t *_Nonnull, double, void *_Nullable);
typedef int (*zip_cancel_callback)(zip_t *_Nonnull, void *_Nullable);
#ifndef ZIP_DISABLE_DEPRECATED
typedef void (*zip_progress_callback_t)(double);
ZIP_EXTERN void zip_register_progress_callback(zip_t *_Nonnull, zip_progress_callback_t _Nullable); /* use zip_register_progress_callback_with_state */
#define ZIP_FL_RECOMPRESS 16u /* force recompression of data */
ZIP_EXTERN zip_int64_t zip_add(zip_t *_Nonnull, const char *_Nonnull, zip_source_t *_Nonnull); /* use zip_file_add */
ZIP_EXTERN zip_int64_t zip_add_dir(zip_t *_Nonnull, const char *_Nonnull); /* use zip_dir_add */
ZIP_EXTERN const char *_Nullable zip_get_file_comment(zip_t *_Nonnull, zip_uint64_t, int *_Nullable, int); /* use zip_file_get_comment */
ZIP_EXTERN int zip_get_num_files(zip_t *_Nonnull); /* use zip_get_num_entries instead */
ZIP_EXTERN int zip_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull); /* use zip_file_rename */
ZIP_EXTERN int zip_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull); /* use zip_file_replace */
ZIP_EXTERN int zip_set_file_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, int); /* use zip_file_set_comment */
ZIP_EXTERN int zip_error_get_sys_type(int); /* use zip_error_system_type */
ZIP_EXTERN void zip_error_get(zip_t *_Nonnull, int *_Nullable, int *_Nullable); /* use zip_get_error, zip_error_code_zip / zip_error_code_system */
ZIP_EXTERN int zip_error_to_str(char *_Nonnull, zip_uint64_t, int, int); /* use zip_error_init_with_code / zip_error_strerror */
ZIP_EXTERN void zip_file_error_get(zip_file_t *_Nonnull, int *_Nullable, int *_Nullable); /* use zip_file_get_error, zip_error_code_zip / zip_error_code_system */
typedef void (*zip_progress_callback_t)(double);
ZIP_DEPRECATED("use 'zip_register_progress_callback_with_state' instead") ZIP_EXTERN void zip_register_progress_callback(zip_t *_Nonnull, zip_progress_callback_t _Nullable);
ZIP_DEPRECATED("use 'zip_file_add' instead") ZIP_EXTERN zip_int64_t zip_add(zip_t *_Nonnull, const char *_Nonnull, zip_source_t *_Nonnull);
ZIP_DEPRECATED("use 'zip_dir_add' instead") ZIP_EXTERN zip_int64_t zip_add_dir(zip_t *_Nonnull, const char *_Nonnull);
ZIP_DEPRECATED("use 'zip_file_get_comment' instead") ZIP_EXTERN const char *_Nullable zip_get_file_comment(zip_t *_Nonnull, zip_uint64_t, int *_Nullable, int);
ZIP_DEPRECATED("use 'zip_get_num_entries' instead") ZIP_EXTERN int zip_get_num_files(zip_t *_Nonnull);
ZIP_DEPRECATED("use 'zip_file_rename' instead") ZIP_EXTERN int zip_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull);
ZIP_DEPRECATED("use 'zip_file_replace' instead") ZIP_EXTERN int zip_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull);
ZIP_DEPRECATED("use 'zip_file_set_comment' instead") ZIP_EXTERN int zip_set_file_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, int);
ZIP_DEPRECATED("use 'zip_error_init_with_code' and 'zip_error_system_type' instead") ZIP_EXTERN int zip_error_get_sys_type(int);
ZIP_DEPRECATED("use 'zip_get_error' instead") ZIP_EXTERN void zip_error_get(zip_t *_Nonnull, int *_Nullable, int *_Nullable);
ZIP_DEPRECATED("use 'zip_error_strerror' instead") ZIP_EXTERN int zip_error_to_str(char *_Nonnull, zip_uint64_t, int, int);
ZIP_DEPRECATED("use 'zip_file_get_error' instead") ZIP_EXTERN void zip_file_error_get(zip_file_t *_Nonnull, int *_Nullable, int *_Nullable);
ZIP_DEPRECATED("use 'zip_source_zip_file' instead") 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_DEPRECATED("use 'zip_source_zip_file_create' instead") 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);
#endif
ZIP_EXTERN int zip_close(zip_t *_Nonnull);
@ -384,6 +405,7 @@ ZIP_EXTERN void zip_error_fini(zip_error_t *_Nonnull);
ZIP_EXTERN void zip_error_init(zip_error_t *_Nonnull);
ZIP_EXTERN void zip_error_init_with_code(zip_error_t *_Nonnull, int);
ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int);
ZIP_EXTERN void zip_error_set_from_source(zip_error_t *_Nonnull, zip_source_t *_Nullable);
ZIP_EXTERN const char *_Nonnull zip_error_strerror(zip_error_t *_Nonnull);
ZIP_EXTERN int zip_error_system_type(const zip_error_t *_Nonnull);
ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *_Nonnull, void *_Nonnull, zip_uint64_t);
@ -451,9 +473,13 @@ ZIP_EXTERN zip_source_t *_Nullable zip_source_function(zip_t *_Nonnull, zip_sour
ZIP_EXTERN zip_source_t *_Nullable zip_source_function_create(zip_source_callback _Nonnull, void *_Nullable, zip_error_t *_Nullable);
ZIP_EXTERN int zip_source_get_file_attributes(zip_source_t *_Nonnull, zip_file_attributes_t *_Nonnull);
ZIP_EXTERN int zip_source_is_deleted(zip_source_t *_Nonnull);
ZIP_EXTERN int zip_source_is_seekable(zip_source_t *_Nonnull);
ZIP_EXTERN void zip_source_keep(zip_source_t *_Nonnull);
ZIP_EXTERN zip_source_t *_Nullable zip_source_layered(zip_t *_Nullable, zip_source_t *_Nonnull, zip_source_layered_callback _Nonnull, void *_Nullable);
ZIP_EXTERN zip_source_t *_Nullable zip_source_layered_create(zip_source_t *_Nonnull, zip_source_layered_callback _Nonnull, void *_Nullable, zip_error_t *_Nullable);
ZIP_EXTERN zip_int64_t zip_source_make_command_bitmap(zip_source_cmd_t, ...);
ZIP_EXTERN int zip_source_open(zip_source_t *_Nonnull);
ZIP_EXTERN zip_int64_t zip_source_pass_to_lower_layer(zip_source_t *_Nonnull, void *_Nullable, zip_uint64_t, zip_source_cmd_t);
ZIP_EXTERN zip_int64_t zip_source_read(zip_source_t *_Nonnull, void *_Nonnull, zip_uint64_t);
ZIP_EXTERN void zip_source_rollback_write(zip_source_t *_Nonnull);
ZIP_EXTERN int zip_source_seek(zip_source_t *_Nonnull, zip_int64_t, int);
@ -463,17 +489,17 @@ ZIP_EXTERN int zip_source_stat(zip_source_t *_Nonnull, zip_stat_t *_Nonnull);
ZIP_EXTERN zip_int64_t zip_source_tell(zip_source_t *_Nonnull);
ZIP_EXTERN zip_int64_t zip_source_tell_write(zip_source_t *_Nonnull);
#ifdef _WIN32
ZIP_EXTERN zip_source_t *zip_source_win32a(zip_t *, const char *, zip_uint64_t, zip_int64_t);
ZIP_EXTERN zip_source_t *zip_source_win32a_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *);
ZIP_EXTERN zip_source_t *zip_source_win32handle(zip_t *, void *, zip_uint64_t, zip_int64_t);
ZIP_EXTERN zip_source_t *zip_source_win32handle_create(void *, zip_uint64_t, zip_int64_t, zip_error_t *);
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 *);
ZIP_EXTERN zip_source_t *_Nullable zip_source_win32a(zip_t *_Nonnull, const char *_Nonnull, zip_uint64_t, zip_int64_t);
ZIP_EXTERN zip_source_t *_Nullable zip_source_win32a_create(const char *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
ZIP_EXTERN zip_source_t *_Nullable zip_source_win32handle(zip_t *_Nonnull, void *_Nonnull, zip_uint64_t, zip_int64_t);
ZIP_EXTERN zip_source_t *_Nullable zip_source_win32handle_create(void *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
ZIP_EXTERN zip_source_t *_Nullable zip_source_win32w(zip_t *_Nonnull, const wchar_t *_Nonnull, zip_uint64_t, zip_int64_t);
ZIP_EXTERN zip_source_t *_Nullable zip_source_win32w_create(const wchar_t *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
#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 zip_source_t *_Nullable zip_source_zip_file(zip_t *_Nonnull, zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t, const char *_Nullable);
ZIP_EXTERN zip_source_t *_Nullable zip_source_zip_file_create(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t, const char *_Nullable, 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);

View File

@ -58,7 +58,7 @@ maximum_compressed_size(zip_uint64_t uncompressed_size) {
static void *
allocate(bool compress, int compression_flags, zip_error_t *error) {
allocate(bool compress, zip_uint32_t compression_flags, zip_error_t *error) {
struct ctx *ctx;
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
@ -67,8 +67,10 @@ allocate(bool compress, int compression_flags, zip_error_t *error) {
ctx->error = error;
ctx->compress = compress;
ctx->compression_flags = compression_flags;
if (ctx->compression_flags < 1 || ctx->compression_flags > 9) {
if (compression_flags >= 1 && compression_flags <= 9) {
ctx->compression_flags = (int)compression_flags;
}
else {
ctx->compression_flags = 9;
}
ctx->end_of_input = false;
@ -82,13 +84,15 @@ allocate(bool compress, int compression_flags, zip_error_t *error) {
static void *
compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
compress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
(void)method;
return allocate(true, compression_flags, error);
}
static void *
decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
decompress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
(void)method;
return allocate(false, compression_flags, error);
}
@ -103,6 +107,7 @@ deallocate(void *ud) {
static zip_uint16_t
general_purpose_bit_flags(void *ud) {
(void)ud;
return 0;
}
@ -132,8 +137,6 @@ map_error(int ret) {
case BZ_IO_ERROR:
case BZ_OUTBUFF_FULL:
case BZ_SEQUENCE_ERROR:
return ZIP_ER_INTERNAL;
default:
return ZIP_ER_INTERNAL;
}
@ -144,6 +147,9 @@ start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
struct ctx *ctx = (struct ctx *)ud;
int ret;
(void)st;
(void)attributes;
ctx->zstr.avail_in = 0;
ctx->zstr.next_in = NULL;
ctx->zstr.avail_out = 0;
@ -213,6 +219,7 @@ end_of_input(void *ud) {
static zip_compression_status_t
process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
struct ctx *ctx = (struct ctx *)ud;
unsigned int avail_out;
int ret;
@ -221,7 +228,8 @@ process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
return ZIP_COMPRESSION_NEED_DATA;
}
ctx->zstr.avail_out = (unsigned int)ZIP_MIN(UINT_MAX, *length);
avail_out = (unsigned int)ZIP_MIN(UINT_MAX, *length);
ctx->zstr.avail_out = avail_out;
ctx->zstr.next_out = (char *)data;
if (ctx->compress) {
@ -231,7 +239,7 @@ process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
ret = BZ2_bzDecompress(&ctx->zstr);
}
*length = *length - ctx->zstr.avail_out;
*length = avail_out - ctx->zstr.avail_out;
switch (ret) {
case BZ_FINISH_OK: /* compression */

View File

@ -40,7 +40,8 @@
struct ctx {
zip_error_t *error;
bool compress;
int compression_flags;
int level;
int mem_level;
bool end_of_input;
z_stream zstr;
};
@ -60,7 +61,7 @@ maximum_compressed_size(zip_uint64_t uncompressed_size) {
static void *
allocate(bool compress, int compression_flags, zip_error_t *error) {
allocate(bool compress, zip_uint32_t compression_flags, zip_error_t *error) {
struct ctx *ctx;
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
@ -70,10 +71,13 @@ allocate(bool compress, int compression_flags, zip_error_t *error) {
ctx->error = error;
ctx->compress = compress;
ctx->compression_flags = compression_flags;
if (ctx->compression_flags < 1 || ctx->compression_flags > 9) {
ctx->compression_flags = Z_BEST_COMPRESSION;
if (compression_flags >= 1 && compression_flags <= 9) {
ctx->level = (int)compression_flags;
}
else {
ctx->level = Z_BEST_COMPRESSION;
}
ctx->mem_level = compression_flags == TORRENTZIP_COMPRESSION_FLAGS ? TORRENTZIP_MEM_LEVEL : MAX_MEM_LEVEL;
ctx->end_of_input = false;
ctx->zstr.zalloc = Z_NULL;
@ -85,13 +89,15 @@ allocate(bool compress, int compression_flags, zip_error_t *error) {
static void *
compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
compress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
(void)method;
return allocate(true, compression_flags, error);
}
static void *
decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
decompress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
(void)method;
return allocate(false, compression_flags, error);
}
@ -112,10 +118,10 @@ general_purpose_bit_flags(void *ud) {
return 0;
}
if (ctx->compression_flags < 3) {
if (ctx->level < 3) {
return 2 << 1;
}
else if (ctx->compression_flags > 7) {
else if (ctx->level > 7) {
return 1 << 1;
}
return 0;
@ -127,6 +133,9 @@ start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
struct ctx *ctx = (struct ctx *)ud;
int ret;
(void)st;
(void)attributes;
ctx->zstr.avail_in = 0;
ctx->zstr.next_in = NULL;
ctx->zstr.avail_out = 0;
@ -134,7 +143,7 @@ start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
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);
ret = deflateInit2(&ctx->zstr, ctx->level, Z_DEFLATED, -MAX_WBITS, ctx->mem_level, Z_DEFAULT_STRATEGY);
}
else {
ret = inflateInit2(&ctx->zstr, -MAX_WBITS);
@ -198,10 +207,12 @@ end_of_input(void *ud) {
static zip_compression_status_t
process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
struct ctx *ctx = (struct ctx *)ud;
uInt avail_out;
int ret;
ctx->zstr.avail_out = (uInt)ZIP_MIN(UINT_MAX, *length);
avail_out = (uInt)ZIP_MIN(UINT_MAX, *length);
ctx->zstr.avail_out = avail_out;
ctx->zstr.next_out = (Bytef *)data;
if (ctx->compress) {
@ -211,7 +222,7 @@ process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
}
*length = *length - ctx->zstr.avail_out;
*length = avail_out - ctx->zstr.avail_out;
switch (ret) {
case Z_OK:

View File

@ -104,7 +104,7 @@ maximum_compressed_size(zip_uint64_t uncompressed_size) {
static void *
allocate(bool compress, int compression_flags, zip_error_t *error, zip_uint16_t method) {
allocate(bool compress, zip_uint32_t compression_flags, zip_error_t *error, zip_uint16_t method) {
struct ctx *ctx;
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
@ -114,16 +114,16 @@ allocate(bool compress, int compression_flags, zip_error_t *error, zip_uint16_t
ctx->error = error;
ctx->compress = compress;
if (compression_flags < 0 || compression_flags > 9) {
ctx->compression_flags = 6; /* default value */
if (compression_flags <= 9) {
ctx->compression_flags = compression_flags;
} else {
ctx->compression_flags = (zip_uint32_t)compression_flags;
ctx->compression_flags = 6; /* default value */
}
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) {
if (method == ZIP_CM_LZMA) {
ctx->header_state = INCOMPLETE;
}
else {
@ -136,13 +136,13 @@ allocate(bool compress, int compression_flags, zip_error_t *error, zip_uint16_t
static void *
compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
compress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
return allocate(true, compression_flags, error, method);
}
static void *
decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
decompress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
return allocate(false, compression_flags, error, method);
}
@ -258,7 +258,7 @@ input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
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);
(void)memcpy_s(ctx->header + ctx->header_bytes_offset, sizeof(ctx->header) - ctx->header_bytes_offset, data, got);
ctx->header_bytes_offset += got;
length -= got;
data += got;
@ -313,6 +313,7 @@ end_of_input(void *ud) {
static zip_compression_status_t
process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
struct ctx *ctx = (struct ctx *)ud;
uInt avail_out;
lzma_ret ret;
/* for compression of LZMA1 */
if (ctx->method == ZIP_CM_LZMA && ctx->compress) {
@ -335,7 +336,7 @@ process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
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);
(void)memcpy_s(data, *length, 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) {
@ -345,11 +346,12 @@ process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
}
}
ctx->zstr.avail_out = (uInt)ZIP_MIN(UINT_MAX, *length);
avail_out = (uInt)ZIP_MIN(UINT_MAX, *length);
ctx->zstr.avail_out = avail_out;
ctx->zstr.next_out = (Bytef *)data;
ret = lzma_code(&ctx->zstr, ctx->end_of_input ? LZMA_FINISH : LZMA_RUN);
*length = *length - ctx->zstr.avail_out;
*length = avail_out - ctx->zstr.avail_out;
switch (ret) {
case LZMA_OK:

View File

@ -33,7 +33,6 @@
#include "zipint.h"
#include <limits.h>
#include <stdlib.h>
#include <zstd.h>
#include <zstd_errors.h>
@ -56,21 +55,20 @@ maximum_compressed_size(zip_uint64_t uncompressed_size) {
static void *
allocate(bool compress, int compression_flags, zip_error_t *error) {
allocate(bool compress, zip_uint32_t compression_flags, zip_error_t *error) {
struct ctx *ctx;
/* 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->compression_flags = (zip_int32_t)compression_flags;
if (ctx->compression_flags < ZSTD_minCLevel() || ctx->compression_flags > ZSTD_maxCLevel()) {
ctx->compression_flags = 0; /* let zstd choose */
}
ctx->error = error;
ctx->compress = compress;
ctx->compression_flags = compression_flags;
ctx->end_of_input = false;
ctx->zdstream = NULL;
@ -87,13 +85,15 @@ allocate(bool compress, int compression_flags, zip_error_t *error) {
static void *
compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
compress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
(void)method;
return allocate(true, compression_flags, error);
}
static void *
decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
decompress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
(void)method;
return allocate(false, compression_flags, error);
}
@ -107,7 +107,7 @@ deallocate(void *ud) {
static zip_uint16_t
general_purpose_bit_flags(void *ud) {
/* struct ctx *ctx = (struct ctx *)ud; */
(void)ud;
return 0;
}
@ -139,6 +139,10 @@ map_error(size_t ret) {
static bool
start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
struct ctx *ctx = (struct ctx *)ud;
(void)st;
(void)attributes;
ctx->in.src = NULL;
ctx->in.pos = 0;
ctx->in.size = 0;

View File

@ -132,13 +132,20 @@ _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) {
zip_uint64_t copied;
if (_zip_buffer_left(buffer) < length) {
length = _zip_buffer_left(buffer);
}
memcpy(data, _zip_buffer_get(buffer, length), length);
copied = 0;
while (copied < length) {
size_t n = ZIP_MIN(length - copied, SIZE_MAX);
(void)memcpy_s(data + copied, n, _zip_buffer_get(buffer, n), n);
copied += n;
}
return length;
return copied;
}
@ -147,8 +154,14 @@ _zip_buffer_new(zip_uint8_t *data, zip_uint64_t size) {
bool free_data = (data == NULL);
zip_buffer_t *buffer;
#if ZIP_UINT64_MAX > SIZE_MAX
if (size > SIZE_MAX) {
return NULL;
}
#endif
if (data == NULL) {
if ((data = (zip_uint8_t *)malloc(size)) == NULL) {
if ((data = (zip_uint8_t *)malloc((size_t)size)) == NULL) {
return NULL;
}
}
@ -221,7 +234,7 @@ _zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length) {
return -1;
}
memcpy(dst, src, length);
(void)memcpy_s(dst, length, src, length);
return 0;
}

View File

@ -45,6 +45,7 @@
static int add_data(zip_t *, zip_source_t *, zip_dirent_t *, zip_uint32_t);
static int copy_data(zip_t *, zip_uint64_t);
static int copy_source(zip_t *, zip_source_t *, zip_int64_t);
static int torrentzip_compare_names(const void *a, const void *b);
static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t);
static int write_data_descriptor(zip_t *za, const zip_dirent_t *dirent, int is_zip64);
@ -61,12 +62,12 @@ zip_close(zip_t *za) {
changed = _zip_changed(za, &survivors);
/* don't create zip files with no entries */
if (survivors == 0) {
if (survivors == 0 && !(za->ch_flags & ZIP_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE)) {
/* don't create zip files with no entries */
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);
zip_error_set_from_source(&za->error, za->src);
return -1;
}
}
@ -75,7 +76,8 @@ zip_close(zip_t *za) {
return 0;
}
if (!changed) {
/* Always write empty archive if we are told to keep it, otherwise it wouldn't be created if the file doesn't already exist. */
if (!changed && survivors > 0) {
zip_discard(za);
return 0;
}
@ -105,6 +107,7 @@ zip_close(zip_t *za) {
}
filelist[j].idx = i;
filelist[j].name = zip_get_name(za, i, 0);
j++;
}
if (j < survivors) {
@ -113,7 +116,11 @@ zip_close(zip_t *za) {
return -1;
}
if ((zip_source_supports(za->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING)) == 0) {
if (ZIP_WANT_TORRENTZIP(za)) {
qsort(filelist, (size_t)survivors, sizeof(filelist[0]), torrentzip_compare_names);
}
if (ZIP_WANT_TORRENTZIP(za) || (zip_source_supports(za->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING)) == 0) {
unchanged_offset = 0;
}
else {
@ -146,7 +153,7 @@ zip_close(zip_t *za) {
}
if (unchanged_offset == 0) {
if (zip_source_begin_write(za->src) < 0) {
_zip_error_set_from_source(&za->error, za->src);
zip_error_set_from_source(&za->error, za->src);
free(filelist);
return -1;
}
@ -178,7 +185,7 @@ zip_close(zip_t *za) {
continue;
}
new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD));
new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD)) || (ZIP_WANT_TORRENTZIP(za) && !ZIP_IS_TORRENTZIP(za));
/* create new local directory entry */
if (entry->changes == NULL) {
@ -195,8 +202,12 @@ zip_close(zip_t *za) {
break;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_dirent_torrentzip_normalize(entry->changes);
}
if ((off = zip_source_tell_write(za->src)) < 0) {
_zip_error_set_from_source(&za->error, za->src);
zip_error_set_from_source(&za->error, za->src);
error = 1;
break;
}
@ -207,7 +218,7 @@ zip_close(zip_t *za) {
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) {
if ((zs = zip_source_zip_file_create(za, i, ZIP_FL_UNCHANGED, 0, -1, NULL, &za->error)) == NULL) {
error = 1;
break;
}
@ -240,7 +251,7 @@ zip_close(zip_t *za) {
break;
}
if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
_zip_error_set_from_source(&za->error, za->src);
zip_error_set_from_source(&za->error, za->src);
error = 1;
break;
}
@ -267,7 +278,7 @@ zip_close(zip_t *za) {
if (!error) {
if (zip_source_commit_write(za->src) != 0) {
_zip_error_set_from_source(&za->error, za->src);
zip_error_set_from_source(&za->error, za->src);
error = 1;
}
_zip_progress_end(za->progress);
@ -296,7 +307,7 @@ 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);
zip_error_set_from_source(&za->error, src);
return -1;
}
@ -324,6 +335,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
flags = ZIP_EF_LOCAL;
if ((st.valid & ZIP_STAT_SIZE) == 0) {
/* TODO: not valid for torrentzip */
flags |= ZIP_FL_FORCE_ZIP64;
data_length = -1;
}
@ -350,6 +362,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
}
if (max_compressed_size > 0xffffffffu) {
/* TODO: not valid for torrentzip */
flags |= ZIP_FL_FORCE_ZIP64;
}
}
@ -360,7 +373,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
}
if ((offstart = zip_source_tell_write(za->src)) < 0) {
_zip_error_set_from_source(&za->error, za->src);
zip_error_set_from_source(&za->error, za->src);
return -1;
}
@ -370,7 +383,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
return -1;
}
needs_recompress = st.comp_method != ZIP_CM_ACTUAL(de->comp_method);
needs_recompress = ZIP_WANT_TORRENTZIP(za) || 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;
@ -397,7 +410,6 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
return -1;
}
zip_source_free(src_final);
src_final = src_tmp;
}
@ -407,7 +419,6 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
return -1;
}
zip_source_free(src_final);
src_final = src_tmp;
}
@ -417,7 +428,6 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
return -1;
}
zip_source_free(src_final);
src_final = src_tmp;
}
@ -427,7 +437,6 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
return -1;
}
zip_source_free(src_final);
src_final = src_tmp;
}
@ -458,11 +467,10 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
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) {
if ((src_tmp = _zip_source_window_new(src_final, 0, -1, &st_mtime, 0, NULL, NULL, 0, true, &za->error)) == NULL) {
zip_source_free(src_final);
return -1;
}
zip_source_free(src_final);
src_final = src_tmp;
}
}
@ -473,25 +481,24 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
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);
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);
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);
zip_error_set_from_source(&za->error, src_final);
ret = -1;
}
@ -502,12 +509,12 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
}
if ((offend = zip_source_tell_write(za->src)) < 0) {
_zip_error_set_from_source(&za->error, za->src);
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);
zip_error_set_from_source(&za->error, za->src);
return -1;
}
@ -528,6 +535,10 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
de->comp_size = (zip_uint64_t)(offend - offdata);
_zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed);
if (ZIP_WANT_TORRENTZIP(za)) {
zip_dirent_torrentzip_normalize(de);
}
if ((ret = _zip_dirent_write(za, de, flags)) < 0)
return -1;
@ -538,7 +549,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
}
if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
_zip_error_set_from_source(&za->error, za->src);
zip_error_set_from_source(&za->error, za->src);
return -1;
}
@ -555,7 +566,6 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
static int
copy_data(zip_t *za, zip_uint64_t len) {
DEFINE_BYTE_ARRAY(buf, BUFSIZE);
size_t n;
double total = (double)len;
if (!byte_array_init(buf, BUFSIZE)) {
@ -564,7 +574,8 @@ copy_data(zip_t *za, zip_uint64_t len) {
}
while (len > 0) {
n = len > BUFSIZE ? BUFSIZE : len;
zip_uint64_t n = ZIP_MIN(len, BUFSIZE);
if (_zip_read(za->src, buf, n, &za->error) < 0) {
byte_array_fini(buf);
return -1;
@ -595,7 +606,7 @@ 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);
zip_error_set_from_source(&za->error, src);
return -1;
}
@ -622,7 +633,7 @@ copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
}
if (n < 0) {
_zip_error_set_from_source(&za->error, src);
zip_error_set_from_source(&za->error, src);
ret = -1;
}
@ -659,7 +670,7 @@ _zip_changed(const zip_t *za, zip_uint64_t *survivorsp) {
changed = 0;
survivors = 0;
if (za->comment_changed || za->ch_flags != za->flags) {
if (za->comment_changed || (ZIP_WANT_TORRENTZIP(za) && !ZIP_IS_TORRENTZIP(za))) {
changed = 1;
}
@ -712,3 +723,18 @@ write_data_descriptor(zip_t *za, const zip_dirent_t *de, int is_zip64) {
return ret;
}
static int torrentzip_compare_names(const void *a, const void *b) {
const char *aname = ((const zip_filelist_t *)a)->name;
const char *bname = ((const zip_filelist_t *)b)->name;
if (aname == NULL) {
return (bname != NULL) * -1;
}
else if (bname == NULL) {
return 1;
}
return strcasecmp(aname, bname);
}

View File

@ -117,6 +117,8 @@ _zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_ui
mbedtls_md_context_t sha1_ctx;
bool ok = true;
#if MBEDTLS_VERSION_NUMBER < 0x03030000
mbedtls_md_init(&sha1_ctx);
if (mbedtls_md_setup(&sha1_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1) != 0) {
@ -128,6 +130,13 @@ _zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_ui
}
mbedtls_md_free(&sha1_ctx);
#else
ok = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, (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;
#endif // !defined(MBEDTLS_DEPRECATED_REMOVED) || MBEDTLS_VERSION_NUMBER < 0x03030000
return ok;
}

View File

@ -40,11 +40,28 @@
#include <limits.h>
#include <openssl/rand.h>
#if OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
#define USE_OPENSSL_1_0_API
#ifdef USE_OPENSSL_3_API
static _zip_crypto_hmac_t* hmac_new() {
_zip_crypto_hmac_t *hmac = (_zip_crypto_hmac_t*)malloc(sizeof(*hmac));
if (hmac != NULL) {
hmac->mac = NULL;
hmac->ctx = NULL;
}
return hmac;
}
static void hmac_free(_zip_crypto_hmac_t* hmac) {
if (hmac != NULL) {
if (hmac->ctx != NULL) {
EVP_MAC_CTX_free(hmac->ctx);
}
if (hmac->mac != NULL) {
EVP_MAC_free(hmac->mac);
}
free(hmac);
}
}
#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;
@ -126,13 +143,34 @@ _zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_
return NULL;
}
#ifdef USE_OPENSSL_3_API
if ((hmac = hmac_new()) == NULL
|| (hmac->mac = EVP_MAC_fetch(NULL, "HMAC", "provider=default")) == NULL
|| (hmac->ctx = EVP_MAC_CTX_new(hmac->mac)) == NULL) {
hmac_free(hmac);
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
{
OSSL_PARAM params[2];
params[0] = OSSL_PARAM_construct_utf8_string("digest", "SHA1", 0);
params[1] = OSSL_PARAM_construct_end();
if (!EVP_MAC_init(hmac->ctx, (const unsigned char *)secret, secret_length, params)) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
hmac_free(hmac);
return NULL;
}
}
#else
#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);
HMAC_CTX_init(hmac);
#else
if ((hmac = HMAC_CTX_new()) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
@ -149,6 +187,7 @@ _zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_
#endif
return NULL;
}
#endif
return hmac;
}
@ -160,7 +199,9 @@ _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
return;
}
#ifdef USE_OPENSSL_1_0_API
#if defined(USE_OPENSSL_3_API)
hmac_free(hmac);
#elif defined(USE_OPENSSL_1_0_API)
HMAC_CTX_cleanup(hmac);
_zip_crypto_clear(hmac, sizeof(*hmac));
free(hmac);
@ -172,9 +213,13 @@ _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
bool
_zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data) {
#ifdef USE_OPENSSL_3_API
size_t length;
return EVP_MAC_final(hmac->ctx, data, &length, ZIP_CRYPTO_SHA1_LENGTH) == 1 && length == ZIP_CRYPTO_SHA1_LENGTH;
#else
unsigned int length;
return HMAC_Final(hmac, data, &length) == 1;
#endif
}

View File

@ -39,14 +39,31 @@
#include <openssl/evp.h>
#include <openssl/hmac.h>
#if OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
#define USE_OPENSSL_1_0_API
#elif OPENSSL_VERSION_NUMBER < 0x3000000fL
#define USE_OPENSSL_1_1_API
#else
#define USE_OPENSSL_3_API
#endif
#define _zip_crypto_aes_t EVP_CIPHER_CTX
#ifdef USE_OPENSSL_3_API
struct _zip_crypto_hmac_t {
EVP_MAC *mac;
EVP_MAC_CTX *ctx;
};
typedef struct _zip_crypto_hmac_t _zip_crypto_hmac_t;
#define _zip_crypto_hmac(hmac, data, length) (EVP_MAC_update((hmac->ctx), (data), (length)) == 1)
#else
#define _zip_crypto_hmac_t HMAC_CTX
#define _zip_crypto_hmac(hmac, data, length) (HMAC_Update((hmac), (data), (length)) == 1)
#endif
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);

View File

@ -254,7 +254,7 @@ pbkdf2(PUCHAR pbPassword, ULONG cbPassword, PUCHAR pbSalt, ULONG cbSalt, DWORD c
for (j = 0; j < cIterations; j++) {
if (j == 0) {
/* construct first input for PRF */
memcpy(U, pbSalt, cbSalt);
(void)memcpy_s(U, cbSalt, pbSalt, cbSalt);
U[cbSalt] = (BYTE)((i & 0xFF000000) >> 24);
U[cbSalt + 1] = (BYTE)((i & 0x00FF0000) >> 16);
U[cbSalt + 2] = (BYTE)((i & 0x0000FF00) >> 8);
@ -262,7 +262,7 @@ pbkdf2(PUCHAR pbPassword, ULONG cbPassword, PUCHAR pbSalt, ULONG cbSalt, DWORD c
dwULen = cbSalt + 4;
}
else {
memcpy(U, V, DIGEST_SIZE);
(void)memcpy_s(U, DIGEST_SIZE, V, DIGEST_SIZE);
dwULen = DIGEST_SIZE;
}
@ -274,11 +274,11 @@ pbkdf2(PUCHAR pbPassword, ULONG cbPassword, PUCHAR pbSalt, ULONG cbSalt, DWORD c
}
if (i != l) {
memcpy(&pbDerivedKey[(i - 1) * DIGEST_SIZE], Ti, DIGEST_SIZE);
(void)memcpy_s(&pbDerivedKey[(i - 1) * DIGEST_SIZE], cbDerivedKey - (i - 1) * DIGEST_SIZE, Ti, DIGEST_SIZE);
}
else {
/* Take only the first r bytes */
memcpy(&pbDerivedKey[(i - 1) * DIGEST_SIZE], Ti, r);
(void)memcpy_s(&pbDerivedKey[(i - 1) * DIGEST_SIZE], cbDerivedKey - (i - 1) * DIGEST_SIZE, Ti, r);
}
}

View File

@ -61,11 +61,11 @@ zip_dir_add(zip_t *za, const char *name, zip_flags_t flags) {
len = strlen(name);
if (name[len - 1] != '/') {
if ((s = (char *)malloc(len + 2)) == NULL) {
if (len > SIZE_MAX - 2 || (s = (char *)malloc(len + 2)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
strcpy(s, name);
(void)strncpy_s(s, len + 2, name, len);
s[len] = '/';
s[len + 1] = '\0';
}

View File

@ -37,6 +37,7 @@
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <zlib.h>
#include "zipint.h"
@ -127,15 +128,21 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
zip_uint64_t i;
bool is_zip64;
int ret;
zip_uint32_t cdir_crc;
if ((off = zip_source_tell_write(za->src)) < 0) {
_zip_error_set_from_source(&za->error, za->src);
zip_error_set_from_source(&za->error, za->src);
return -1;
}
offset = (zip_uint64_t)off;
is_zip64 = false;
if (ZIP_WANT_TORRENTZIP(za)) {
cdir_crc = (zip_uint32_t)crc32(0, NULL, 0);
za->write_crc = &cdir_crc;
}
for (i = 0; i < survivors; i++) {
zip_entry_t *entry = za->entry + filelist[i].idx;
@ -145,15 +152,17 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
is_zip64 = true;
}
za->write_crc = NULL;
if ((off = zip_source_tell_write(za->src)) < 0) {
_zip_error_set_from_source(&za->error, za->src);
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)
if (offset > ZIP_UINT32_MAX || survivors > ZIP_UINT16_MAX) {
is_zip64 = true;
}
if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
@ -186,7 +195,13 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
comment = za->comment_changed ? za->comment_changes : za->comment_orig;
_zip_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0));
if (ZIP_WANT_TORRENTZIP(za)) {
_zip_buffer_put_16(buffer, TORRENTZIP_SIGNATURE_LENGTH + TORRENTZIP_CRC_LENGTH);
}
else {
_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);
@ -201,7 +216,15 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
_zip_buffer_free(buffer);
if (comment) {
if (ZIP_WANT_TORRENTZIP(za)) {
char torrentzip_comment[TORRENTZIP_SIGNATURE_LENGTH + TORRENTZIP_CRC_LENGTH + 1];
snprintf(torrentzip_comment, sizeof(torrentzip_comment), TORRENTZIP_SIGNATURE "%08X", cdir_crc);
if (_zip_write(za, torrentzip_comment, strlen(torrentzip_comment)) < 0) {
return -1;
}
}
else if (comment != NULL) {
if (_zip_write(za, comment->raw, comment->length) < 0) {
return -1;
}
@ -219,7 +242,7 @@ _zip_dirent_clone(const zip_dirent_t *sde) {
return NULL;
if (sde)
memcpy(tde, sde, sizeof(*sde));
(void)memcpy_s(tde, sizeof(*tde), sde, sizeof(*sde));
else
_zip_dirent_init(tde);
@ -503,76 +526,18 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
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, ZIP_ER_DETAIL_INVALID_ZIP64_EF);
_zip_buffer_free(ef_buffer);
if (ef != NULL) {
if (!zip_dirent_process_ef_zip64(zde, ef, got_len, local, error)) {
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) {
@ -599,6 +564,65 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
return (zip_int64_t)size + (zip_int64_t)variable_size;
}
bool zip_dirent_process_ef_zip64(zip_dirent_t* zde, const zip_uint8_t* ef, zip_uint64_t got_len, bool local, zip_error_t* error) {
zip_buffer_t *ef_buffer;
if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
}
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);
return false;
}
}
_zip_buffer_free(ef_buffer);
return true;
}
static zip_string_t *
_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str) {
@ -728,7 +752,7 @@ _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);
zip_error_set_from_source(error, src);
return -1;
}
@ -901,7 +925,13 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
_zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method);
}
_zip_u2d_time(de->last_mod, &dostime, &dosdate);
if (ZIP_WANT_TORRENTZIP(za)) {
dostime = 0xbc00;
dosdate = 0x2198;
}
else {
_zip_u2d_time(de->last_mod, &dostime, &dosdate);
}
_zip_buffer_put_16(buffer, dostime);
_zip_buffer_put_16(buffer, dosdate);
@ -937,12 +967,15 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
}
_zip_buffer_put_16(buffer, _zip_string_length(de->filename));
/* TODO: check for overflow */
ef_total_size = (zip_uint32_t)_zip_ef_size(de->extra_fields, flags) + (zip_uint32_t)_zip_ef_size(ef, ZIP_EF_BOTH);
ef_total_size = (zip_uint32_t)_zip_ef_size(ef, ZIP_EF_BOTH);
if (!ZIP_WANT_TORRENTZIP(za)) {
/* TODO: check for overflow */
ef_total_size += (zip_uint32_t)_zip_ef_size(de->extra_fields, 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_WANT_TORRENTZIP(za) ? 0 : _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);
@ -981,13 +1014,13 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
}
}
_zip_ef_free(ef);
if (de->extra_fields) {
if (de->extra_fields && !ZIP_WANT_TORRENTZIP(za)) {
if (_zip_ef_write(za, de->extra_fields, flags) < 0) {
return -1;
}
}
if ((flags & ZIP_FL_LOCAL) == 0) {
if ((flags & ZIP_FL_LOCAL) == 0 && !ZIP_WANT_TORRENTZIP(za)) {
if (de->comment) {
if (_zip_string_write(za, de->comment) < 0) {
return -1;
@ -1089,15 +1122,10 @@ _zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *err
void
_zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) {
struct tm *tpm;
#ifdef HAVE_LOCALTIME_R
struct tm tm;
tpm = localtime_r(&intime, &tm);
#else
tpm = localtime(&intime);
#endif
tpm = zip_localtime(&intime, &tm);
if (tpm == NULL) {
/* if localtime() fails, return an arbitrary date (1980-01-01 00:00:00) */
/* if localtime fails, return an arbitrary date (1980-01-01 00:00:00) */
*ddate = (1 << 5) + 1;
*dtime = 0;
return;
@ -1108,8 +1136,6 @@ _zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) {
*ddate = (zip_uint16_t)(((tpm->tm_year + 1900 - 1980) << 9) + ((tpm->tm_mon + 1) << 5) + tpm->tm_mday);
*dtime = (zip_uint16_t)(((tpm->tm_hour) << 11) + ((tpm->tm_min) << 5) + ((tpm->tm_sec) >> 1));
return;
}
@ -1160,3 +1186,22 @@ _zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes
de->version_madeby = (de->version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8);
}
}
/* _zip_dirent_torrent_normalize(de);
Set values suitable for torrentzip.
*/
void zip_dirent_torrentzip_normalize(zip_dirent_t *de) {
de->version_madeby = 0;
de->version_needed = 20; /* 2.0 */
de->bitflags = 2; /* maximum compression */
de->comp_method = ZIP_CM_DEFLATE;
de->compression_level = TORRENTZIP_COMPRESSION_FLAGS;
de->disk_number = 0;
de->int_attrib = 0;
de->ext_attrib = 0;
/* last_mod, extra_fields, and comment are normalized in zip_dirent_write() directly */
}

View File

@ -47,6 +47,8 @@ const struct _zip_err_info _zip_err_str[] = {
{ S, "Tell error" },
{ N, "Compressed data invalid" },
{ N, "Operation cancelled" },
{ N, "Unexpected length of data" },
{ N, "Not allowed in torrentzip" },
};
const int _zip_err_str_count = sizeof(_zip_err_str)/sizeof(_zip_err_str[0]);

View File

@ -132,7 +132,12 @@ zip_error_set(zip_error_t *err, int ze, int se) {
void
_zip_error_set_from_source(zip_error_t *err, zip_source_t *src) {
zip_error_set_from_source(zip_error_t *err, zip_source_t *src) {
if (src == NULL) {
zip_error_set(err, ZIP_ER_INVAL, 0);
return;
}
_zip_error_copy(err, zip_source_error(src));
}

View File

@ -42,23 +42,29 @@
ZIP_EXTERN const char *
zip_error_strerror(zip_error_t *err) {
const char *zip_error_string, *system_error_string;
char buf[128], *s;
char *s;
char *system_error_buffer = NULL;
zip_error_fini(err);
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 */
system_error_buffer = (char *)malloc(128);
snprintf_s(system_error_buffer, 128, "Unknown error %d", err->zip_err);
system_error_buffer[128 - 1] = '\0'; /* make sure string is NUL-terminated */
zip_error_string = NULL;
system_error_string = buf;
system_error_string = system_error_buffer;
}
else {
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);
case ZIP_ET_SYS: {
size_t len = strerrorlen_s(err->sys_err) + 1;
system_error_buffer = malloc(len);
strerror_s(system_error_buffer, len, err->sys_err);
system_error_string = system_error_buffer;
break;
}
case ZIP_ET_ZLIB:
system_error_string = zError(err->sys_err);
@ -72,14 +78,16 @@ zip_error_strerror(zip_error_t *err) {
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;
system_error_buffer = (char *)malloc(128);
snprintf_s(system_error_buffer, 128, "invalid detail error %u", error);
system_error_buffer[128 - 1] = '\0'; /* make sure string is NUL-terminated */
system_error_string = system_error_buffer;
}
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;
system_error_buffer = (char *)malloc(128);
snprintf_s(system_error_buffer, 128, "entry %d: %s", index, _zip_err_details[error].description);
system_error_buffer[128 - 1] = '\0'; /* make sure string is NUL-terminated */
system_error_string = system_error_buffer;
}
else {
system_error_string = _zip_err_details[error].description;
@ -93,16 +101,28 @@ zip_error_strerror(zip_error_t *err) {
}
if (system_error_string == NULL) {
free(system_error_buffer);
return zip_error_string;
}
else {
if ((s = (char *)malloc(strlen(system_error_string) + (zip_error_string ? strlen(zip_error_string) + 2 : 0) + 1)) == NULL) {
size_t length = strlen(system_error_string);
if (zip_error_string) {
size_t length_error = strlen(zip_error_string);
if (length + length_error + 2 < length) {
free(system_error_buffer);
return _zip_err_str[ZIP_ER_MEMORY].description;
}
length += length_error + 2;
}
if (length == SIZE_MAX || (s = (char *)malloc(length + 1)) == NULL) {
free(system_error_buffer);
return _zip_err_str[ZIP_ER_MEMORY].description;
}
sprintf(s, "%s%s%s", (zip_error_string ? zip_error_string : ""), (zip_error_string ? ": " : ""), system_error_string);
snprintf_s(s, length + 1, "%s%s%s", (zip_error_string ? zip_error_string : ""), (zip_error_string ? ": " : ""), system_error_string);
err->str = s;
free(system_error_buffer);
return s;
}
}

View File

@ -34,7 +34,6 @@
#include <stdio.h>
#include <string.h>
#include <zlib.h>
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
@ -42,26 +41,18 @@
ZIP_EXTERN int
zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se) {
const char *zs, *ss;
zip_error_t error;
const char *error_string;
int ret;
if (ze < 0 || ze >= _zip_err_str_count) {
return snprintf(buf, len, "Unknown error %d", ze);
}
zip_error_init(&error);
zip_error_set(&error, ze, se);
zs = _zip_err_str[ze].description;
error_string = zip_error_strerror(&error);
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;
}
ret = snprintf_s(buf, ZIP_MIN(len, SIZE_MAX), error_string, strlen(error_string));
return snprintf(buf, len, "%s%s%s", zs, (ss ? ": " : ""), (ss ? ss : ""));
zip_error_fini(&error);
return ret;
}

View File

@ -243,10 +243,11 @@ _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_
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 */
/* buffer is at most 64k long, so this can't overflow. */
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) {
if (glen >= 4 || garbage == NULL || memcmp(garbage, "\0\0\0", (size_t)glen) != 0) {
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EF_TRAILING_GARBAGE);
_zip_buffer_free(buffer);
_zip_ef_free(ef_head);
@ -370,7 +371,7 @@ _zip_read_local_ef(zip_t *za, zip_uint64_t idx) {
}
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);
zip_error_set_from_source(&za->error, za->src);
return -1;
}

View File

@ -56,6 +56,10 @@ zip_file_extra_field_delete(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zi
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
return -1;
}
if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
return -1;
@ -88,6 +92,10 @@ zip_file_extra_field_delete_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_i
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
return -1;
}
if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
return -1;
@ -236,6 +244,10 @@ zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_ui
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
return -1;
}
if (ZIP_EF_IS_INTERNAL(ef_id)) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);

View File

@ -51,6 +51,10 @@ zip_fdopen(int fd_orig, int _flags, int *zep) {
return NULL;
}
#ifndef ENABLE_FDOPEN
_zip_set_open_error(zep, NULL, ZIP_ER_OPNOTSUPP);
return NULL;
#else
/* We dup() here to avoid messing with the passed in fd.
We could not restore it to the original state in case of error. */
@ -83,4 +87,5 @@ zip_fdopen(int fd_orig, int _flags, int *zep) {
zip_error_fini(&error);
close(fd_orig);
return za;
#endif
}

View File

@ -57,7 +57,7 @@ _zip_file_get_offset(const zip_t *za, zip_uint64_t idx, zip_error_t *error) {
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);
zip_error_set_from_source(error, za->src);
return 0;
}
@ -93,11 +93,11 @@ _zip_file_get_end(const zip_t *za, zip_uint64_t index, zip_error_t *error) {
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);
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);
zip_error_set_from_source(error, za->src);
return 0;
}
if (memcmp(buf, DATADES_MAGIC, 4) == 0) {

View File

@ -50,6 +50,10 @@ zip_file_set_comment(zip_t *za, zip_uint64_t idx, const char *comment, zip_uint1
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
return -1;
}
if (len > 0 && comment == NULL) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);

View File

@ -51,6 +51,10 @@ zip_file_set_encryption(zip_t *za, zip_uint64_t idx, zip_uint16_t method, const
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 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);

View File

@ -47,6 +47,10 @@ zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags,
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
return -1;
}
e = za->entry + idx;

View File

@ -51,6 +51,10 @@ zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags)
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
return -1;
}
e = za->entry + idx;

View File

@ -49,11 +49,11 @@ zip_fopen_index_encrypted(zip_t *za, zip_uint64_t index, zip_flags_t flags, cons
password = NULL;
}
if ((src = _zip_source_zip_new(za, index, flags, 0, 0, password, &za->error)) == NULL)
if ((src = zip_source_zip_file_create(za, index, flags, 0, -1, password, &za->error)) == NULL)
return NULL;
if (zip_source_open(src) < 0) {
_zip_error_set_from_source(&za->error, src);
zip_error_set_from_source(&za->error, src);
zip_source_free(src);
return NULL;
}
@ -78,9 +78,7 @@ _zip_file_new(zip_t *za) {
return NULL;
}
zf->za = za;
zip_error_init(&zf->error);
zf->eof = 0;
zf->src = NULL;
return zf;

View File

@ -50,11 +50,12 @@ zip_fread(zip_file_t *zf, void *outbuf, zip_uint64_t toread) {
return -1;
}
if ((zf->eof) || (toread == 0))
if (toread == 0) {
return 0;
}
if ((n = zip_source_read(zf->src, outbuf, toread)) < 0) {
_zip_error_set_from_source(&zf->error, zf->src);
zip_error_set_from_source(&zf->error, zf->src);
return -1;
}

View File

@ -43,7 +43,7 @@ zip_fseek(zip_file_t *zf, zip_int64_t offset, int whence) {
return -1;
if (zip_source_seek(zf->src, offset, whence) < 0) {
_zip_error_set_from_source(&zf->error, zf->src);
zip_error_set_from_source(&zf->error, zf->src);
return -1;
}
@ -57,5 +57,5 @@ zip_file_is_seekable(zip_file_t *zfile) {
return -1;
}
return ZIP_SOURCE_CHECK_SUPPORTED(zip_source_supports(zfile->src), ZIP_SOURCE_SEEK);
return zip_source_is_seekable(zfile->src);
}

View File

@ -46,7 +46,7 @@ zip_ftell(zip_file_t *zf) {
res = zip_source_tell(zf->src);
if (res < 0) {
_zip_error_set_from_source(&zf->error, zf->src);
zip_error_set_from_source(&zf->error, zf->src);
return -1;
}

View File

@ -31,8 +31,10 @@
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
#include "zipint.h"
@ -46,7 +48,7 @@ _zip_read(zip_source_t *src, zip_uint8_t *b, zip_uint64_t length, zip_error_t *e
}
if ((n = zip_source_read(src, b, length)) < 0) {
_zip_error_set_from_source(error, src);
zip_error_set_from_source(error, src);
return -1;
}
@ -81,7 +83,7 @@ _zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp
free(r);
return NULL;
}
memcpy(r, data, length);
(void)memcpy_s(r, length, data, length);
}
else {
if (_zip_read(src, r, length, error) < 0) {
@ -122,7 +124,7 @@ _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);
zip_error_set_from_source(&za->error, za->src);
return -1;
}
if ((zip_uint64_t)n != length) {
@ -130,5 +132,15 @@ _zip_write(zip_t *za, const void *data, zip_uint64_t length) {
return -1;
}
if (za->write_crc != NULL) {
zip_uint64_t position = 0;
while (position < length) {
zip_uint64_t nn = ZIP_MIN(UINT_MAX, length - position);
*za->write_crc = (zip_uint32_t)crc32(*za->write_crc, (const Bytef *)data + position, (uInt)nn);
position += nn;
}
}
return 0;
}

View File

@ -50,7 +50,7 @@ _zip_memdup(const void *mem, size_t len, zip_error_t *error) {
return NULL;
}
memcpy(ret, mem, len);
(void)memcpy_s(ret, len, mem, len);
return ret;
}

View File

@ -49,20 +49,29 @@ 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 *);
size_t fname_length;
zip_string_t *str = NULL;
const char *fn, *p;
zip_uint64_t i;
if (za == NULL)
if (za == NULL) {
return -1;
}
if (fname == NULL) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return -1;
}
fname_length = strlen(fname);
if (fname_length > ZIP_UINT16_MAX) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return -1;
}
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) {
if ((str = _zip_string_new((const zip_uint8_t *)fname, (zip_uint16_t)strlen(fname), flags, error)) == NULL) {
return -1;
}
if ((fname = (const char *)_zip_string_get(str, NULL, 0, error)) == NULL) {

View File

@ -32,6 +32,7 @@
*/
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -41,10 +42,11 @@
typedef enum { EXISTS_ERROR = -1, EXISTS_NOT = 0, EXISTS_OK } exists_t;
static zip_t *_zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error);
static zip_int64_t _zip_checkcons(zip_t *za, zip_cdir_t *cdir, zip_error_t *error);
static void zip_check_torrentzip(zip_t *za, const zip_cdir_t *cdir);
static zip_cdir_t *_zip_find_central_dir(zip_t *za, zip_uint64_t len);
static exists_t _zip_file_exists(zip_source_t *src, zip_error_t *error);
static int _zip_headercomp(const zip_dirent_t *, const zip_dirent_t *);
static unsigned char *_zip_memmem(const unsigned char *, size_t, const unsigned char *, size_t);
static const unsigned char *_zip_memmem(const unsigned char *, size_t, const unsigned char *, size_t);
static zip_cdir_t *_zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error);
static zip_cdir_t *_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error);
static zip_cdir_t *_zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error);
@ -120,7 +122,7 @@ zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error) {
return NULL;
}
if (zip_source_open(src) < 0) {
_zip_error_set_from_source(error, src);
zip_error_set_from_source(error, src);
return NULL;
}
@ -151,7 +153,7 @@ _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);
zip_error_set_from_source(error, src);
return NULL;
}
if ((st.valid & ZIP_STAT_SIZE) == 0) {
@ -181,7 +183,16 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) {
za->entry = cdir->entry;
za->nentry = cdir->nentry;
za->nentry_alloc = cdir->nentry_alloc;
za->comment_orig = cdir->comment;
zip_check_torrentzip(za, cdir);
if (ZIP_IS_TORRENTZIP(za)) {
/* Torrentzip uses the archive comment to detect changes by tools that are not torrentzip aware. */
_zip_string_free(cdir->comment);
}
else {
za->comment_orig = cdir->comment;
}
free(cdir);
@ -321,7 +332,7 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
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_error_set_from_source(error, za->src);
_zip_cdir_free(cd);
return NULL;
}
@ -388,7 +399,7 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
zip_int64_t offset = zip_source_tell(za->src);
if (offset < 0) {
_zip_error_set_from_source(error, za->src);
zip_error_set_from_source(error, za->src);
_zip_cdir_free(cd);
return NULL;
}
@ -445,7 +456,7 @@ _zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error) {
}
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);
zip_error_set_from_source(error, za->src);
return -1;
}
@ -491,9 +502,20 @@ _zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *local) {
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))
This is in violation of the appnote.
macOS Archive sets the compressed size even when data descriptor is used ( but not the others),
also in violation of the appnote.
*/
/* if data descriptor is not used, the values must match */
if ((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0) {
return -1;
}
/* when using a data descriptor, the local header value must be zero or match */
if ((local->crc != 0 && central->crc != local->crc) ||
(local->comp_size != 0 && central->comp_size != local->comp_size) ||
(local->uncomp_size != 0 && central->uncomp_size != local->uncomp_size)) {
return -1;
}
}
return 0;
@ -510,10 +532,15 @@ _zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error) {
za->src = src;
za->open_flags = flags;
za->flags = 0;
za->ch_flags = 0;
za->write_crc = NULL;
if (flags & ZIP_RDONLY) {
za->flags |= ZIP_AFL_RDONLY;
za->ch_flags |= ZIP_AFL_RDONLY;
}
return za;
}
@ -542,7 +569,7 @@ _zip_file_exists(zip_source_t *src, zip_error_t *error) {
static zip_cdir_t *
_zip_find_central_dir(zip_t *za, zip_uint64_t len) {
zip_cdir_t *cdir, *cdirnew;
zip_uint8_t *match;
const zip_uint8_t *match;
zip_int64_t buf_offset;
zip_uint64_t buflen;
zip_int64_t a;
@ -565,7 +592,7 @@ _zip_find_central_dir(zip_t *za, zip_uint64_t len) {
}
}
if ((buf_offset = zip_source_tell(za->src)) < 0) {
_zip_error_set_from_source(&za->error, za->src);
zip_error_set_from_source(&za->error, za->src);
return NULL;
}
@ -582,7 +609,8 @@ _zip_find_central_dir(zip_t *za, zip_uint64_t len) {
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) {
/* The size of buffer never greater than CDBUFSIZE. */
while (_zip_buffer_left(buffer) >= EOCDLEN && (match = _zip_memmem(match, (size_t)_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) {
@ -627,19 +655,28 @@ _zip_find_central_dir(zip_t *za, zip_uint64_t len) {
}
static unsigned char *
_zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little, size_t littlelen) {
static const unsigned char *_zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little, size_t littlelen) {
const unsigned char *p;
if ((biglen < littlelen) || (littlelen == 0))
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 (littlelen == 0) {
return big;
}
return NULL;
if (biglen < littlelen) {
return NULL;
}
p = big;
while (true) {
p = (const unsigned char *)memchr(p, little[0], biglen - (littlelen - 1) - (size_t)(p - big));
if (p == NULL) {
return NULL;
}
if (memcmp(p + 1, little + 1, littlelen - 1) == 0) {
return p;
}
p += 1;
}
}
@ -739,7 +776,7 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
}
else {
if (zip_source_seek(src, (zip_int64_t)eocd_offset, SEEK_SET) < 0) {
_zip_error_set_from_source(error, src);
zip_error_set_from_source(error, src);
return NULL;
}
if ((buffer = _zip_buffer_new_from_source(src, EOCD64LEN, eocd, error)) == NULL) {
@ -852,3 +889,79 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
return cd;
}
static int decode_hex(char c) {
if (c >= '0' && c <= '9') {
return c - '0';
}
else if (c >= 'A' && c <= 'F') {
return c - 'A' + 10;
}
else {
return -1;
}
}
/* _zip_check_torrentzip:
check whether ZA has a valid TORRENTZIP comment, i.e. is torrentzipped */
static void zip_check_torrentzip(zip_t *za, const zip_cdir_t *cdir) {
zip_uint32_t crc_should;
char buf[8+1];
size_t i;
if (cdir == NULL) {
return;
}
if (_zip_string_length(cdir->comment) != TORRENTZIP_SIGNATURE_LENGTH + TORRENTZIP_CRC_LENGTH
|| strncmp((const char *)cdir->comment->raw, TORRENTZIP_SIGNATURE, TORRENTZIP_SIGNATURE_LENGTH) != 0)
return;
memcpy(buf, cdir->comment->raw + TORRENTZIP_SIGNATURE_LENGTH, TORRENTZIP_CRC_LENGTH);
buf[TORRENTZIP_CRC_LENGTH] = '\0';
crc_should = 0;
for (i = 0; i < TORRENTZIP_CRC_LENGTH; i += 2) {
int low, high;
high = decode_hex((buf[i]));
low = decode_hex(buf[i + 1]);
if (high < 0 || low < 0) {
return;
}
crc_should = (crc_should << 8) + (high << 4) + low;
}
{
zip_stat_t st;
zip_source_t* src_window;
zip_source_t* src_crc;
zip_uint8_t buffer[512];
zip_int64_t ret;
zip_stat_init(&st);
st.valid |= ZIP_STAT_SIZE | ZIP_STAT_CRC;
st.size = cdir->size;
st.crc = crc_should;
if ((src_window = _zip_source_window_new(za->src, cdir->offset, cdir->size, &st, 0, NULL, NULL, 0, false, NULL)) == NULL) {
return;
}
if ((src_crc = zip_source_crc_create(src_window, 1, NULL)) == NULL) {
zip_source_free(src_window);
return;
}
if (zip_source_open(src_crc) != 0) {
zip_source_free(src_crc);
return;
}
while ((ret = zip_source_read(src_crc, buffer, sizeof(buffer))) > 0) {
}
zip_source_free(src_crc);
if (ret < 0) {
return;
}
}
/* TODO: if check consistency, check cdir entries for valid values */
za->flags |= ZIP_AFL_IS_TORRENTZIP;
}

View File

@ -45,6 +45,10 @@ zip_set_archive_comment(zip_t *za, const char *comment, zip_uint16_t len) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
return -1;
}
if (len > 0 && comment == NULL) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);

View File

@ -39,13 +39,23 @@ ZIP_EXTERN int
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;
else
new_flags = za->ch_flags & ~flag;
if (flag == ZIP_AFL_IS_TORRENTZIP) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (new_flags == za->ch_flags)
/* TODO: when setting ZIP_AFL_WANT_TORRENTZIP, we should error out if any changes have been made that are not allowed for torrentzip. */
if (value) {
new_flags = za->ch_flags | flag;
}
else {
new_flags = za->ch_flags & ~flag;
}
if (new_flags == za->ch_flags) {
return 0;
}
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);

View File

@ -49,6 +49,10 @@ zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_ui
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
return -1;
}
if (!zip_compression_method_supported(method, true)) {
zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);

View File

@ -37,7 +37,7 @@
bool
zip_source_accept_empty(zip_source_t *src) {
int ret;
zip_int64_t ret;
if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY)) == 0) {
if (ZIP_SOURCE_IS_LAYERED(src)) {
@ -46,7 +46,7 @@ zip_source_accept_empty(zip_source_t *src) {
return true;
}
ret = (int)_zip_source_call(src, NULL, 0, ZIP_SOURCE_ACCEPT_EMPTY);
ret = _zip_source_call(src, NULL, 0, ZIP_SOURCE_ACCEPT_EMPTY);
return ret != 0;
}

View File

@ -37,6 +37,11 @@
ZIP_EXTERN int
zip_source_begin_write(zip_source_t *src) {
if (ZIP_SOURCE_IS_LAYERED(src)) {
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
return -1;

View File

@ -37,6 +37,11 @@
ZIP_EXTERN int
zip_source_begin_write_cloning(zip_source_t *src, zip_uint64_t offset) {
if (ZIP_SOURCE_IS_LAYERED(src)) {
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
return -1;

View File

@ -50,8 +50,8 @@ struct buffer {
zip_uint64_t shared_fragments; /* number of shared fragments */
struct buffer *shared_buffer; /* buffer fragments are shared with */
zip_uint64_t size; /* size of buffer */
zip_uint64_t size; /* size of buffer */
zip_uint64_t offset; /* current offset in buffer */
zip_uint64_t current_fragment; /* fragment current offset is in */
};
@ -159,7 +159,7 @@ zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *f
ctx->out = NULL;
ctx->mtime = time(NULL);
if (attributes) {
memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes));
(void)memcpy_s(&ctx->attributes, sizeof(ctx->attributes), attributes, sizeof(ctx->attributes));
}
else {
zip_file_attributes_init(&ctx->attributes);
@ -226,7 +226,7 @@ read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
return -1;
}
memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
(void)memcpy_s(data, sizeof(ctx->attributes), &ctx->attributes, sizeof(ctx->attributes));
return sizeof(ctx->attributes);
}
@ -287,7 +287,7 @@ read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
}
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, ZIP_SOURCE_SUPPORTS_REOPEN, -1);
case ZIP_SOURCE_TELL:
if (ctx->in->offset > ZIP_INT64_MAX) {
@ -344,6 +344,7 @@ buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) {
fragment_offset = buffer->fragments[fragment].length;
}
/* TODO: This should also consider the length of the fully shared fragments */
waste = buffer->fragments[fragment].length - fragment_offset;
if (waste > offset) {
zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
@ -356,7 +357,7 @@ buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) {
#ifndef __clang_analyzer__
/* clone->fragments can't be null, since it was created with at least one fragment */
clone->fragments[clone->nfragments - 1].length = fragment_offset;
clone->fragments[fragment].length = fragment_offset;
#endif
clone->fragment_offsets[clone->nfragments] = offset;
clone->size = offset;
@ -365,7 +366,7 @@ buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) {
buffer->shared_buffer = clone;
clone->shared_buffer = buffer;
buffer->shared_fragments = clone->nfragments;
buffer->shared_fragments = fragment + 1;
clone->shared_fragments = fragment + 1;
return clone;
@ -428,17 +429,27 @@ static bool
buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *error) {
zip_buffer_fragment_t *fragments;
zip_uint64_t *offsets;
zip_uint64_t fragments_size;
zip_uint64_t offsets_size;
if (capacity < buffer->fragments_capacity) {
return true;
}
if ((fragments = realloc(buffer->fragments, sizeof(buffer->fragments[0]) * capacity)) == NULL) {
fragments_size = sizeof(buffer->fragments[0]) * capacity;
offsets_size = sizeof(buffer->fragment_offsets[0]) * (capacity + 1);
if (capacity == ZIP_UINT64_MAX || fragments_size < capacity || fragments_size > SIZE_MAX|| offsets_size < capacity || offsets_size > SIZE_MAX) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
}
if ((fragments = realloc(buffer->fragments, (size_t)fragments_size)) == NULL) {
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) {
if ((offsets = realloc(buffer->fragment_offsets, (size_t)offsets_size)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
}
@ -497,6 +508,7 @@ buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int
buffer->fragments[j].data = fragments[i].data;
buffer->fragments[j].length = fragments[i].length;
buffer->fragment_offsets[i] = offset;
/* TODO: overflow */
offset += fragments[i].length;
j++;
}
@ -527,8 +539,11 @@ buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
n = 0;
while (n < length) {
zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
#if ZIP_UINT64_MAX > SIZE_MAX
left = ZIP_MIN(left, SIZE_MAX);
#endif
memcpy(data + n, buffer->fragments[i].data + fragment_offset, left);
(void)memcpy_s(data + n, (size_t)left, buffer->fragments[i].data + fragment_offset, (size_t)left);
if (left == buffer->fragments[i].length - fragment_offset) {
i++;
@ -559,7 +574,7 @@ buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error)
static zip_int64_t
buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *error) {
zip_uint64_t n, i, fragment_offset, capacity;
zip_uint64_t copied, i, fragment_offset, capacity;
if (buffer->offset + length + WRITE_FRAGMENT_SIZE - 1 < length) {
zip_error_set(error, ZIP_ER_INVAL, 0);
@ -601,24 +616,30 @@ buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip
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);
copied = 0;
while (copied < length) {
zip_uint64_t n = ZIP_MIN(ZIP_MIN(length - copied, buffer->fragments[i].length - fragment_offset), SIZE_MAX);
#if ZIP_UINT64_MAX > SIZE_MAX
n = ZIP_MIN(n, SIZE_MAX);
#endif
memcpy(buffer->fragments[i].data + fragment_offset, data + n, left);
(void)memcpy_s(buffer->fragments[i].data + fragment_offset, (size_t)n, data + copied, (size_t)n);
if (left == buffer->fragments[i].length - fragment_offset) {
if (n == buffer->fragments[i].length - fragment_offset) {
i++;
fragment_offset = 0;
}
n += left;
fragment_offset = 0;
else {
fragment_offset += n;
}
copied += n;
}
buffer->offset += n;
buffer->offset += copied;
buffer->current_fragment = i;
if (buffer->offset > buffer->size) {
buffer->size = buffer->offset;
}
return (zip_int64_t)n;
return (zip_int64_t)copied;
}

View File

@ -37,6 +37,11 @@
ZIP_EXTERN int
zip_source_commit_write(zip_source_t *src) {
if (ZIP_SOURCE_IS_LAYERED(src)) {
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) {
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
return -1;

View File

@ -83,10 +83,10 @@ static struct implementation implementations[] = {
static size_t implementations_size = sizeof(implementations) / sizeof(implementations[0]);
static zip_source_t *compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, int compression_flags);
static zip_source_t *compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, zip_uint32_t compression_flags);
static zip_int64_t compress_callback(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
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 struct context *context_new(zip_int32_t method, bool compress, zip_uint32_t compression_flags, zip_compression_algorithm_t *algorithm);
static zip_int64_t compress_read(zip_source_t *, struct context *, void *, zip_uint64_t);
zip_compression_algorithm_t *
@ -117,7 +117,7 @@ zip_compression_method_supported(zip_int32_t method, int compress) {
}
zip_source_t *
zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t method, int compression_flags) {
zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t method, zip_uint32_t compression_flags) {
return compression_source_new(za, src, method, true, compression_flags);
}
@ -128,7 +128,7 @@ zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t method) {
static zip_source_t *
compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, int compression_flags) {
compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, zip_uint32_t compression_flags) {
struct context *ctx;
zip_source_t *s2;
zip_compression_algorithm_t *algorithm = NULL;
@ -158,7 +158,7 @@ compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool co
static struct context *
context_new(zip_int32_t method, bool compress, int compression_flags, zip_compression_algorithm_t *algorithm) {
context_new(zip_int32_t method, bool compress, zip_uint32_t compression_flags, zip_compression_algorithm_t *algorithm) {
struct context *ctx;
if ((ctx = (struct context *)malloc(sizeof(*ctx))) == NULL) {
@ -240,7 +240,7 @@ compress_read(zip_source_t *src, struct context *ctx, void *data, zip_uint64_t l
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);
(void)memcpy_s(data, ctx->size, ctx->buffer, ctx->size);
return (zip_int64_t)ctx->size;
}
end = true;
@ -257,7 +257,7 @@ compress_read(zip_source_t *src, struct context *ctx, void *data, zip_uint64_t l
}
if ((n = zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
_zip_error_set_from_source(&ctx->error, src);
zip_error_set_from_source(&ctx->error, src);
end = true;
break;
}
@ -319,7 +319,7 @@ compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip
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);
zip_error_set_from_source(&ctx->error, src);
return -1;
}
@ -357,6 +357,7 @@ compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip
else {
st->comp_method = ZIP_CM_STORE;
st->valid |= ZIP_STAT_COMP_METHOD;
st->valid &= ~ZIP_STAT_COMP_SIZE;
if (ctx->end_of_stream) {
st->size = ctx->size;
st->valid |= ZIP_STAT_SIZE;
@ -389,10 +390,9 @@ compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip
}
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, ZIP_SOURCE_SUPPORTS_REOPEN, -1);
default:
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
return -1;
return zip_source_pass_to_lower_layer(src, data, len, cmd);
}
}

View File

@ -90,7 +90,7 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
case ZIP_SOURCE_READ:
if ((n = zip_source_read(src, data, len)) < 0) {
_zip_error_set_from_source(&ctx->error, src);
zip_error_set_from_source(&ctx->error, src);
return -1;
}
@ -103,7 +103,7 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
struct zip_stat st;
if (zip_source_stat(src, &st) < 0) {
_zip_error_set_from_source(&ctx->error, src);
zip_error_set_from_source(&ctx->error, src);
return -1;
}
@ -141,6 +141,10 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
st = (zip_stat_t *)data;
if (ctx->crc_complete) {
if ((st->valid & ZIP_STAT_SIZE) && st->size != ctx->size) {
zip_error_set(&ctx->error, ZIP_ER_DATA_LENGTH, 0);
return -1;
}
/* TODO: Set comp_size, comp_method, encryption_method?
After all, this only works for uncompressed data. */
st->size = ctx->size;
@ -164,11 +168,13 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
zip_int64_t mask = zip_source_supports(src);
if (mask < 0) {
_zip_error_set_from_source(&ctx->error, src);
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);
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);
mask |= zip_source_make_command_bitmap(ZIP_SOURCE_FREE, -1);
return mask;
}
case ZIP_SOURCE_SEEK: {
@ -179,7 +185,7 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
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);
zip_error_set_from_source(&ctx->error, src);
return -1;
}
@ -192,7 +198,6 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
return (zip_int64_t)ctx->position;
default:
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
return zip_source_pass_to_lower_layer(src, data, len, cmd);
}
}

View File

@ -109,7 +109,7 @@ zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zi
ctx->start = start;
ctx->len = (zip_uint64_t)len;
if (st) {
memcpy(&ctx->st, st, sizeof(ctx->st));
(void)memcpy_s(&ctx->st, sizeof(ctx->st), st, sizeof(*st));
ctx->st.name = NULL;
ctx->st.valid &= ~ZIP_STAT_NAME;
}
@ -130,7 +130,7 @@ zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zi
zip_error_init(&ctx->error);
zip_file_attributes_init(&ctx->attributes);
ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1);
ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, ZIP_SOURCE_SUPPORTS_REOPEN, -1);
zip_source_file_stat_init(&sb);
if (!ops->stat(ctx, &sb)) {
@ -262,7 +262,7 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
return -1;
}
memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
(void)memcpy_s(data, sizeof(ctx->attributes), &ctx->attributes, sizeof(ctx->attributes));
return sizeof(ctx->attributes);
case ZIP_SOURCE_OPEN:
@ -272,7 +272,7 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
}
}
if (ctx->start > 0) { // TODO: rewind on re-open
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;
@ -355,7 +355,7 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
return -1;
}
memcpy(data, &ctx->st, sizeof(ctx->st));
(void)memcpy_s(data, sizeof(ctx->st), &ctx->st, sizeof(ctx->st));
return sizeof(ctx->st);
}

View File

@ -176,33 +176,3 @@ _zip_stdio_op_tell(zip_source_file_context_t *ctx, void *f) {
return offset;
}
/*
* fopen replacement that sets the close-on-exec flag
* some implementations support an fopen 'e' flag for that,
* but e.g. macOS doesn't.
*/
FILE *
_zip_fopen_close_on_exec(const char *name, bool writeable) {
int fd;
int flags;
FILE *fp;
flags = O_CLOEXEC;
if (writeable) {
flags |= O_RDWR;
}
else {
flags |= O_RDONLY;
}
/* mode argument needed on Windows */
if ((fd = open(name, flags, 0666)) < 0) {
return NULL;
}
if ((fp = fdopen(fd, writeable ? "r+b" : "rb")) == NULL) {
return NULL;
}
return fp;
}

View File

@ -42,6 +42,4 @@ bool _zip_stdio_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t off
bool _zip_stdio_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st);
zip_int64_t _zip_stdio_op_tell(zip_source_file_context_t *ctx, void *f);
FILE *_zip_fopen_close_on_exec(const char *name, bool writeable);
#endif /* _HAD_ZIP_SOURCE_FILE_STDIO_H */

View File

@ -66,6 +66,7 @@ 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);
static FILE *_zip_fopen_close_on_exec(const char *name, bool writeable);
/* clang-format off */
static zip_source_file_operations_t ops_stdio_named = {
@ -300,11 +301,12 @@ static int create_temp_file(zip_source_file_context_t *ctx, bool create_file) {
mode = -1;
}
if ((temp = (char *)malloc(strlen(ctx->fname) + 13)) == NULL) {
size_t temp_size = strlen(ctx->fname) + 13;
if ((temp = (char *)malloc(temp_size)) == NULL) {
zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
return -1;
}
sprintf(temp, "%s.XXXXXX.part", ctx->fname);
snprintf_s(temp, temp_size, "%s.XXXXXX.part", ctx->fname);
end = temp + strlen(temp) - 5;
start = end - 6;
@ -359,3 +361,32 @@ static int create_temp_file(zip_source_file_context_t *ctx, bool create_file) {
return create_file ? fd : 0;
}
/*
* fopen replacement that sets the close-on-exec flag
* some implementations support an fopen 'e' flag for that,
* but e.g. macOS doesn't.
*/
static FILE *_zip_fopen_close_on_exec(const char *name, bool writeable) {
int fd;
int flags;
FILE *fp;
flags = O_CLOEXEC;
if (writeable) {
flags |= O_RDWR;
}
else {
flags |= O_RDONLY;
}
/* mode argument needed on Windows */
if ((fd = open(name, flags, 0666)) < 0) {
return NULL;
}
if ((fp = fdopen(fd, writeable ? "r+b" : "rb")) == NULL) {
return NULL;
}
return fp;
}

View File

@ -73,4 +73,12 @@ zip_int64_t _zip_win32_op_tell(zip_source_file_context_t *ctx, void *f);
bool _zip_filetime_to_time_t(FILETIME ft, time_t *t);
int _zip_win32_error_to_errno(DWORD win32err);
#ifdef __clang__
#define DONT_WARN_INCOMPATIBLE_FN_PTR_BEGIN _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wincompatible-function-pointer-types\"")
#define DONT_WARN_INCOMPATIBLE_FN_PTR_END _Pragma("GCC diagnostic pop")
#else
#define DONT_WARN_INCOMPATIBLE_FN_PTR_BEGIN
#define DONT_WARN_INCOMPATIBLE_FN_PTR_END
#endif
#endif /* _HAD_ZIP_SOURCE_FILE_WIN32_H */

View File

@ -37,6 +37,7 @@ static char *ansi_allocate_tempname(const char *name, size_t extra_chars, size_t
static void ansi_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i);
/* clang-format off */
DONT_WARN_INCOMPATIBLE_FN_PTR_BEGIN
zip_win32_file_operations_t ops_ansi = {
ansi_allocate_tempname,
@ -50,6 +51,7 @@ zip_win32_file_operations_t ops_ansi = {
strdup
};
DONT_WARN_INCOMPATIBLE_FN_PTR_END
/* clang-format on */
ZIP_EXTERN zip_source_t *
@ -81,5 +83,5 @@ 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) {
snprintf(buf, len, "%s.%08x", name, i);
snprintf_s(buf, len, "%s.%08x", name, i);
}

View File

@ -99,7 +99,6 @@ _zip_win32_named_op_create_temp_output(zip_source_file_context_t *ctx) {
zip_uint32_t value, i;
HANDLE th = INVALID_HANDLE_VALUE;
void *temp = NULL;
PSECURITY_DESCRIPTOR psd = NULL;
PSECURITY_ATTRIBUTES psa = NULL;
SECURITY_ATTRIBUTES sa;

View File

@ -39,6 +39,7 @@ static void utf16_make_tempname(char *buf, size_t len, const char *name, zip_uin
static char *utf16_strdup(const char *string);
/* clang-format off */
DONT_WARN_INCOMPATIBLE_FN_PTR_BEGIN
zip_win32_file_operations_t ops_utf16 = {
utf16_allocate_tempname,
@ -52,6 +53,7 @@ zip_win32_file_operations_t ops_utf16 = {
utf16_strdup
};
DONT_WARN_INCOMPATIBLE_FN_PTR_END
/* clang-format on */
ZIP_EXTERN zip_source_t *
@ -101,7 +103,7 @@ static HANDLE __stdcall utf16_create_file(const char *name, DWORD access, DWORD
static void
utf16_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i) {
_snwprintf((wchar_t *)buf, len, L"%s.%08x", (const wchar_t *)name, i);
_snwprintf_s((wchar_t *)buf, len, len, L"%s.%08x", (const wchar_t *)name, i);
}

View File

@ -57,10 +57,11 @@ zip_source_function_create(zip_source_callback zcb, void *ud, zip_error_t *error
zs->cb.f = zcb;
zs->ud = ud;
zs->supports = zcb(ud, NULL, 0, ZIP_SOURCE_SUPPORTS) | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, -1);
zs->supports = zcb(ud, NULL, 0, ZIP_SOURCE_SUPPORTS);
if (zs->supports < 0) {
zs->supports = ZIP_SOURCE_SUPPORTS_READABLE;
}
zs->supports |= zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, -1);
return zs;
}

View File

@ -60,8 +60,10 @@ zip_source_get_file_attributes(zip_source_t *src, zip_file_attributes_t *attribu
if (ZIP_SOURCE_IS_LAYERED(src)) {
zip_file_attributes_t lower_attributes;
zip_file_attributes_init(&lower_attributes);
if (zip_source_get_file_attributes(src->src, &lower_attributes) < 0) {
_zip_error_set_from_source(&src->error, src->src);
zip_error_set_from_source(&src->error, src->src);
return -1;
}

View File

@ -49,19 +49,27 @@ zip_source_layered(zip_t *za, zip_source_t *src, zip_source_layered_callback cb,
zip_source_t *
zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, void *ud, zip_error_t *error) {
zip_source_t *zs;
zip_int64_t lower_supports, supports;
if ((zs = _zip_source_new(error)) == NULL)
lower_supports = zip_source_supports(src);
supports = cb(src, ud, &lower_supports, sizeof(lower_supports), ZIP_SOURCE_SUPPORTS);
if (supports < 0) {
zip_error_set(error,ZIP_ER_INVAL, 0); /* Initialize in case cb doesn't return valid error. */
cb(src, ud, error, sizeof(*error), ZIP_SOURCE_ERROR);
return NULL;
}
if ((zs = _zip_source_new(error)) == NULL) {
return NULL;
}
zip_source_keep(src);
zs->src = src;
zs->cb.l = cb;
zs->ud = ud;
zs->supports = supports;
zs->supports = cb(src, ud, NULL, 0, ZIP_SOURCE_SUPPORTS);
if (zs->supports < 0) {
zs->supports = ZIP_SOURCE_SUPPORTS_READABLE;
}
/* Layered sources can't support writing, since we currently have no use case. If we want to revisit this, we have to define how the two sources interact. */
zs->supports &= ~(ZIP_SOURCE_SUPPORTS_WRITABLE & ~ZIP_SOURCE_SUPPORTS_SEEKABLE);
return zs;
}

View File

@ -53,7 +53,7 @@ zip_source_open(zip_source_t *src) {
else {
if (ZIP_SOURCE_IS_LAYERED(src)) {
if (zip_source_open(src->src) < 0) {
_zip_error_set_from_source(&src->error, src->src);
zip_error_set_from_source(&src->error, src->src);
return -1;
}
}

View File

@ -0,0 +1,78 @@
/*
zip_source_pass_to_lower_layer.c -- pass command to lower layer
Copyright (C) 2022 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
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_int64_t zip_source_pass_to_lower_layer(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command) {
switch (command) {
case ZIP_SOURCE_OPEN:
case ZIP_SOURCE_CLOSE:
case ZIP_SOURCE_FREE:
case ZIP_SOURCE_GET_FILE_ATTRIBUTES:
case ZIP_SOURCE_SUPPORTS_REOPEN:
return 0;
case ZIP_SOURCE_STAT:
return sizeof(zip_stat_t);
case ZIP_SOURCE_ACCEPT_EMPTY:
case ZIP_SOURCE_ERROR:
case ZIP_SOURCE_READ:
case ZIP_SOURCE_SEEK:
case ZIP_SOURCE_TELL:
return _zip_source_call(src, data, length, command);
case ZIP_SOURCE_BEGIN_WRITE:
case ZIP_SOURCE_BEGIN_WRITE_CLONING:
case ZIP_SOURCE_COMMIT_WRITE:
case ZIP_SOURCE_REMOVE:
case ZIP_SOURCE_ROLLBACK_WRITE:
case ZIP_SOURCE_SEEK_WRITE:
case ZIP_SOURCE_TELL_WRITE:
case ZIP_SOURCE_WRITE:
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
case ZIP_SOURCE_SUPPORTS:
if (length < sizeof(zip_int64_t)) {
zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
return -1;
}
return *(zip_int64_t *)data;
default:
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
}

View File

@ -85,7 +85,7 @@ decrypt_header(zip_source_t *src, struct trad_pkware *ctx) {
bool ok = false;
if ((n = zip_source_read(src, header, ZIP_CRYPTO_PKWARE_HEADERLEN)) < 0) {
_zip_error_set_from_source(&ctx->error, src);
zip_error_set_from_source(&ctx->error, src);
return -1;
}
@ -147,7 +147,7 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_so
case ZIP_SOURCE_READ:
if ((n = zip_source_read(src, data, len)) < 0) {
_zip_error_set_from_source(&ctx->error, src);
zip_error_set_from_source(&ctx->error, src);
return -1;
}
@ -172,7 +172,7 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_so
}
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, ZIP_SOURCE_SUPPORTS_REOPEN, -1);
case ZIP_SOURCE_ERROR:
return zip_error_to_data(&ctx->error, data, len);
@ -182,8 +182,7 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_so
return 0;
default:
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
return -1;
return zip_source_pass_to_lower_layer(src, data, len, cmd);
}
}

View File

@ -86,7 +86,7 @@ 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);
zip_error_set_from_source(&ctx->error, src);
return -1;
}
@ -156,7 +156,7 @@ pkware_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length, zip
}
if ((n = zip_source_read(src, data, length)) < 0) {
_zip_error_set_from_source(&ctx->error, src);
zip_error_set_from_source(&ctx->error, src);
return -1;
}
@ -209,8 +209,7 @@ pkware_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length, zip
return 0;
default:
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
return -1;
return zip_source_pass_to_lower_layer(src, data, length, cmd);
}
}

View File

@ -37,6 +37,11 @@
int
zip_source_remove(zip_source_t *src) {
if (ZIP_SOURCE_IS_LAYERED(src)) {
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) {
return 0;
}

View File

@ -37,6 +37,10 @@
ZIP_EXTERN void
zip_source_rollback_write(zip_source_t *src) {
if (ZIP_SOURCE_IS_LAYERED(src)) {
return;
}
if (src->write_state != ZIP_SOURCE_WRITE_OPEN && src->write_state != ZIP_SOURCE_WRITE_FAILED) {
return;
}

View File

@ -39,6 +39,11 @@ ZIP_EXTERN int
zip_source_seek_write(zip_source_t *src, zip_int64_t offset, int whence) {
zip_source_args_seek_t args;
if (ZIP_SOURCE_IS_LAYERED(src)) {
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
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;

View File

@ -45,11 +45,15 @@ zip_source_stat(zip_source_t *src, zip_stat_t *st) {
return -1;
}
if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) {
zip_error_set(&src->error, ZIP_ER_READ, ENOENT);
}
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);
zip_error_set_from_source(&src->error, src->src);
return -1;
}
}

View File

@ -42,6 +42,10 @@ zip_source_supports(zip_source_t *src) {
return src->supports;
}
bool
zip_source_supports_reopen(zip_source_t *src) {
return (zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SUPPORTS_REOPEN)) != 0;
}
ZIP_EXTERN zip_int64_t
zip_source_make_command_bitmap(zip_source_cmd_t cmd0, ...) {
@ -63,3 +67,8 @@ zip_source_make_command_bitmap(zip_source_cmd_t cmd0, ...) {
return bitmap;
}
ZIP_EXTERN int zip_source_is_seekable(zip_source_t *src) {
return ZIP_SOURCE_CHECK_SUPPORTED(zip_source_supports(src->src), ZIP_SOURCE_SEEK);
}

View File

@ -37,6 +37,11 @@
ZIP_EXTERN zip_int64_t
zip_source_tell_write(zip_source_t *src) {
if (ZIP_SOURCE_IS_LAYERED(src)) {
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) {
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
return -1;

View File

@ -49,6 +49,7 @@ struct window {
zip_uint64_t offset; /* offset in src for next read */
zip_stat_t stat;
zip_uint64_t stat_invalid;
zip_file_attributes_t attributes;
zip_error_t error;
zip_int64_t supports;
@ -60,12 +61,13 @@ static zip_int64_t window_read(zip_source_t *, void *, void *, zip_uint64_t, zip
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);
return _zip_source_window_new(src, start, len, NULL, 0, NULL, NULL, 0, false, error);
}
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_window_new(zip_source_t *src, zip_uint64_t start, zip_int64_t length, zip_stat_t *st, zip_uint64_t st_invalid, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, bool take_ownership, zip_error_t *error) {
zip_source_t* window_source;
struct window *ctx;
if (src == NULL || length < -1 || (source_archive == NULL && source_index != 0)) {
@ -94,8 +96,9 @@ _zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_int64_t length
ctx->end_valid = true;
}
zip_stat_init(&ctx->stat);
ctx->stat_invalid = st_invalid;
if (attributes != NULL) {
memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes));
(void)memcpy_s(&ctx->attributes, sizeof(ctx->attributes), attributes, sizeof(ctx->attributes));
}
else {
zip_file_attributes_init(&ctx->attributes);
@ -103,7 +106,7 @@ _zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_int64_t length
ctx->source_archive = source_archive;
ctx->source_index = source_index;
zip_error_init(&ctx->error);
ctx->supports = (zip_source_supports(src) & ZIP_SOURCE_SUPPORTS_SEEKABLE) | (zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1));
ctx->supports = (zip_source_supports(src) & (ZIP_SOURCE_SUPPORTS_SEEKABLE | ZIP_SOURCE_SUPPORTS_REOPEN)) | (zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, ZIP_SOURCE_FREE, -1));
ctx->needs_seek = (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) ? true : false;
if (st) {
@ -113,7 +116,11 @@ _zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_int64_t length
}
}
return zip_source_layered_create(src, window_read, ctx, error);
window_source = zip_source_layered_create(src, window_read, ctx, error);
if (window_source != NULL && !take_ownership) {
zip_source_keep(src);
}
return window_source;
}
@ -182,7 +189,7 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou
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);
zip_error_set_from_source(&ctx->error, src);
byte_array_fini(b);
return -1;
}
@ -210,7 +217,7 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou
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);
zip_error_set_from_source(&ctx->error, src);
return -1;
}
}
@ -241,12 +248,12 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou
}
if (args->whence == SEEK_END) {
if (zip_source_seek(src, args->offset, args->whence) < 0) {
_zip_error_set_from_source(&ctx->error, src);
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);
zip_error_set_from_source(&ctx->error, src);
return -1;
}
if ((zip_uint64_t)new_offset < ctx->start) {
@ -277,6 +284,19 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou
if (_zip_stat_merge(st, &ctx->stat, &ctx->error) < 0) {
return -1;
}
if (!(ctx->stat.valid & ZIP_STAT_SIZE)) {
if (ctx->end_valid) {
st->valid |= ZIP_STAT_SIZE;
st->size = ctx->end - ctx->start;
}
else if (st->valid & ZIP_STAT_SIZE) {
st->size -= ctx->start;
}
}
st->valid &= ~ctx->stat_invalid;
return 0;
}
@ -286,7 +306,7 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou
return -1;
}
memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
(void)memcpy_s(data, sizeof(ctx->attributes), &ctx->attributes, sizeof(ctx->attributes));
return sizeof(ctx->attributes);
case ZIP_SOURCE_SUPPORTS:
@ -296,8 +316,7 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou
return (zip_int64_t)(ctx->offset - ctx->start);
default:
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
return zip_source_pass_to_lower_layer(src, data, len, cmd);
}
}

View File

@ -36,6 +36,7 @@
#include <string.h>
#include "zipint.h"
#include "zip_crypto.h"
struct winzip_aes {
char *password;
@ -72,7 +73,7 @@ zip_source_winzip_aes_decode(zip_t *za, zip_source_t *src, zip_uint16_t encrypti
}
if (zip_source_stat(src, &st) != 0) {
_zip_error_set_from_source(&za->error, src);
zip_error_set_from_source(&za->error, src);
return NULL;
}
@ -107,7 +108,7 @@ decrypt_header(zip_source_t *src, struct winzip_aes *ctx) {
headerlen = WINZIP_AES_PASSWORD_VERIFY_LENGTH + SALT_LENGTH(ctx->encryption_method);
if ((n = zip_source_read(src, header, headerlen)) < 0) {
_zip_error_set_from_source(&ctx->error, src);
zip_error_set_from_source(&ctx->error, src);
return -1;
}
@ -131,9 +132,9 @@ decrypt_header(zip_source_t *src, struct winzip_aes *ctx) {
static bool
verify_hmac(zip_source_t *src, struct winzip_aes *ctx) {
unsigned char computed[SHA1_LENGTH], from_file[HMAC_LENGTH];
unsigned char computed[ZIP_CRYPTO_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);
zip_error_set_from_source(&ctx->error, src);
return false;
}
@ -181,7 +182,7 @@ winzip_aes_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zi
}
if ((n = zip_source_read(src, data, len)) < 0) {
_zip_error_set_from_source(&ctx->error, src);
zip_error_set_from_source(&ctx->error, src);
return -1;
}
ctx->current_position += (zip_uint64_t)n;
@ -211,7 +212,7 @@ winzip_aes_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zi
}
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, ZIP_SOURCE_SUPPORTS_REOPEN, -1);
case ZIP_SOURCE_ERROR:
return zip_error_to_data(&ctx->error, data, len);
@ -221,8 +222,7 @@ winzip_aes_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zi
return 0;
default:
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
return -1;
return zip_source_pass_to_lower_layer(src, data, len, cmd);
}
}

View File

@ -36,13 +36,13 @@
#include <string.h>
#include "zipint.h"
#include "zip_crypto.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_uint8_t data[ZIP_MAX(WINZIP_AES_MAX_HEADER_LENGTH, ZIP_CRYPTO_SHA1_LENGTH)];
zip_buffer_t *buffer;
zip_winzip_aes_t *aes_ctx;
@ -139,7 +139,7 @@ winzip_aes_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length,
}
if ((ret = zip_source_read(src, data, length)) < 0) {
_zip_error_set_from_source(&ctx->error, src);
zip_error_set_from_source(&ctx->error, src);
return -1;
}
@ -207,8 +207,7 @@ winzip_aes_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length,
return 0;
default:
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
return -1;
return zip_source_pass_to_lower_layer(src, data, length, cmd);
}
}

View File

@ -34,6 +34,7 @@
#include <stdlib.h>
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
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) {
@ -42,15 +43,18 @@ ZIP_EXTERN zip_source_t *zip_source_zip_create(zip_t *srcza, zip_uint64_t srcidx
return NULL;
}
if (len == -1)
len = 0;
if (len == 0) {
len = -1;
}
if (start == 0 && len == 0)
if (start == 0 && len == -1) {
flags |= ZIP_FL_COMPRESSED;
else
}
else {
flags &= ~ZIP_FL_COMPRESSED;
return _zip_source_zip_new(srcza, srcidx, flags, start, (zip_uint64_t)len, NULL, error);
}
return zip_source_zip_file_create(srcza, srcidx, flags, start, len, NULL, error);
}

View File

@ -38,52 +38,98 @@
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 *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_EXTERN zip_source_t *zip_source_zip_file(zip_t* za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_int64_t len, const char *password) {
return zip_source_zip_file_create(srcza, srcidx, flags, start, len, password, &za->error);
}
ZIP_EXTERN zip_source_t *zip_source_zip_file_create(zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_int64_t len, const char *password, zip_error_t *error) {
/* TODO: We need to make sure that the returned source is invalidated when srcza is closed. */
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;
bool partial_data, needs_crc, encrypted, needs_decrypt, compressed, needs_decompress, changed_data, have_size, have_comp_size;
zip_flags_t stat_flags;
zip_int64_t data_len;
bool take_ownership = false;
if (srcza == NULL || srcidx >= srcza->nentry || len > ZIP_INT64_MAX) {
if (srcza == NULL || srcidx >= srcza->nentry || len < -1) {
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(error, ZIP_ER_CHANGED, 0);
return NULL;
}
if (zip_stat_index(srcza, srcidx, flags | ZIP_FL_UNCHANGED, &st) < 0) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
return NULL;
}
if (flags & ZIP_FL_ENCRYPTED) {
flags |= ZIP_FL_COMPRESSED;
}
if ((start > 0 || len > 0) && (flags & ZIP_FL_COMPRESSED)) {
changed_data = false;
if ((flags & ZIP_FL_UNCHANGED) == 0) {
zip_entry_t *entry = srcza->entry + srcidx;
if (ZIP_ENTRY_DATA_CHANGED(entry)) {
if ((flags & ZIP_FL_COMPRESSED) || !zip_source_supports_reopen(entry->source)) {
zip_error_set(error, ZIP_ER_CHANGED, 0);
return NULL;
}
changed_data = true;
}
else if (entry->deleted) {
zip_error_set(error, ZIP_ER_CHANGED, 0);
return NULL;
}
}
stat_flags = flags;
if (!changed_data) {
stat_flags |= ZIP_FL_UNCHANGED;
}
if (zip_stat_index(srcza, srcidx, stat_flags, &st) < 0) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
return NULL;
}
if ((start > 0 || len >= 0) && (flags & ZIP_FL_COMPRESSED)) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
}
have_size = (st.valid & ZIP_STAT_SIZE) != 0;
/* overflow or past end of file */
if ((start > 0 || len > 0) && (start + len < start || start + len > st.size)) {
if (len >= 0 && ((start > 0 && start + len < start) || (have_size && start + len > st.size))) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
}
if (len == 0) {
len = st.size - start;
if (len == -1) {
if (have_size) {
if (st.size - start > ZIP_INT64_MAX) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
}
data_len = (zip_int64_t)(st.size - start);
}
else {
data_len = -1;
}
}
else {
data_len = len;
}
partial_data = len < st.size;
needs_decrypt = ((flags & ZIP_FL_ENCRYPTED) == 0) && (st.encryption_method != ZIP_EM_NONE);
needs_decompress = ((flags & ZIP_FL_COMPRESSED) == 0) && (st.comp_method != ZIP_CM_STORE);
if (have_size) {
partial_data = (zip_uint64_t)(data_len) < st.size;
}
else {
partial_data = true;
}
encrypted = (st.valid & ZIP_STAT_ENCRYPTION_METHOD) && (st.encryption_method != ZIP_EM_NONE);
needs_decrypt = ((flags & ZIP_FL_ENCRYPTED) == 0) && encrypted;
compressed = (st.valid & ZIP_STAT_COMP_METHOD) && (st.comp_method != ZIP_CM_STORE);
needs_decompress = ((flags & ZIP_FL_COMPRESSED) == 0) && compressed;
/* when reading the whole file, check for CRC errors */
needs_crc = ((flags & ZIP_FL_COMPRESSED) == 0 || st.comp_method == ZIP_CM_STORE) && !partial_data;
needs_crc = ((flags & ZIP_FL_COMPRESSED) == 0 || !compressed) && !partial_data && (st.valid & ZIP_STAT_CRC) != 0;
if (needs_decrypt) {
if (password == NULL) {
@ -100,32 +146,102 @@ zip_source_t *_zip_source_zip_new(zip_t *srcza, zip_uint64_t srcidx, zip_flags_t
}
_zip_file_attributes_from_dirent(&attributes, de);
if (st.comp_size == 0) {
return zip_source_buffer_with_attributes_create(NULL, 0, 0, &attributes, error);
have_comp_size = (st.valid & ZIP_STAT_COMP_SIZE) != 0;
if (compressed) {
if (have_comp_size && st.comp_size == 0) {
src = zip_source_buffer_with_attributes_create(NULL, 0, 0, &attributes, error);
}
else {
src = NULL;
}
}
else if (have_size && st.size == 0) {
src = zip_source_buffer_with_attributes_create(NULL, 0, 0, &attributes, error);
}
else {
src = NULL;
}
/* If we created source buffer above, we want the window source to take ownership of it. */
take_ownership = src != NULL;
/* if we created a buffer source above, then treat it as if
reading the changed data - that way we don't need add another
special case to the code below that wraps it in the window
source */
changed_data = changed_data || (src != NULL);
if (partial_data && !needs_decrypt && !needs_decompress) {
struct zip_stat st2;
zip_t *source_archive;
zip_uint64_t source_index;
if (changed_data) {
if (src == NULL) {
src = srcza->entry[srcidx].source;
}
source_archive = NULL;
source_index = 0;
}
else {
src = srcza->src;
source_archive = srcza;
source_index = srcidx;
}
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.valid = ZIP_STAT_COMP_METHOD;
if (data_len >= 0) {
st2.size = (zip_uint64_t)data_len;
st2.comp_size = (zip_uint64_t)data_len;
st2.valid |= ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE;
}
if (st.valid & ZIP_STAT_MTIME) {
st2.mtime = st.mtime;
st2.valid |= ZIP_STAT_MTIME;
}
if ((src = _zip_source_window_new(srcza->src, start, (zip_int64_t)len, &st2, &attributes, srcza, srcidx, error)) == NULL) {
if ((src = _zip_source_window_new(src, start, data_len, &st2, ZIP_STAT_NAME, &attributes, source_archive, source_index, take_ownership, error)) == NULL) {
return NULL;
}
}
else {
/* here we restrict src to file data, so no point in doing it for
source that already represents only the file data */
else if (!changed_data) {
/* this branch is executed only for archive sources; we know
that stat data come from the archive too, so it's safe to
assume that st has a comp_size specified */
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) {
/* despite the fact that we want the whole data file, we still
wrap the source into a window source to add st and
attributes and to have a source that positions the read
offset properly before each read for multiple zip_file_t
referring to the same underlying source */
if ((src = _zip_source_window_new(srcza->src, 0, (zip_int64_t)st.comp_size, &st, ZIP_STAT_NAME, &attributes, srcza, srcidx, take_ownership, error)) == NULL) {
return NULL;
}
}
else {
/* this branch gets executed when reading the whole changed
data file or when "reading" from a zero-sized source buffer
that we created above */
if (src == NULL) {
src = srcza->entry[srcidx].source;
}
/* despite the fact that we want the whole data file, we still
wrap the source into a window source to add st and
attributes and to have a source that positions the read
offset properly before each read for multiple zip_file_t
referring to the same underlying source */
if ((src = _zip_source_window_new(src, 0, data_len, &st, ZIP_STAT_NAME, &attributes, NULL, 0, take_ownership, error)) == NULL) {
return NULL;
}
}
/* In all cases, src is a window source and therefore is owned by this function. */
if (_zip_source_set_source_archive(src, srcza) < 0) {
zip_source_free(src);
@ -143,33 +259,40 @@ zip_source_t *_zip_source_zip_new(zip_t *srcza, zip_uint64_t srcidx, zip_flags_t
}
s2 = enc_impl(srcza, src, st.encryption_method, 0, password);
zip_source_free(src);
if (s2 == NULL) {
zip_source_free(src);
return NULL;
}
src = s2;
}
if (needs_decompress) {
s2 = zip_source_decompress(srcza, src, st.comp_method);
zip_source_free(src);
if (s2 == NULL) {
zip_source_free(src);
return NULL;
}
src = s2;
}
if (needs_crc) {
s2 = zip_source_crc_create(src, 1, error);
zip_source_free(src);
if (s2 == NULL) {
zip_source_free(src);
return NULL;
}
src = s2;
}
if (partial_data && (needs_decrypt || needs_decompress)) {
s2 = zip_source_window_create(src, start, (zip_int64_t)len, error);
zip_source_free(src);
zip_stat_t st2;
zip_stat_init(&st2);
if (data_len >= 0) {
st2.valid = ZIP_STAT_SIZE;
st2.size = (zip_uint64_t)data_len;
}
s2 = _zip_source_window_new(src, start, data_len, &st2, ZIP_STAT_NAME, NULL, NULL, 0, true, error);
if (s2 == NULL) {
zip_source_free(src);
return NULL;
}
src = s2;

View File

@ -39,22 +39,43 @@ ZIP_EXTERN int
zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, zip_stat_t *st) {
const char *name;
zip_dirent_t *de;
zip_entry_t *entry;
if ((de = _zip_get_dirent(za, index, flags, NULL)) == NULL)
if ((de = _zip_get_dirent(za, index, flags, NULL)) == NULL) {
return -1;
}
if ((name = zip_get_name(za, index, flags)) == NULL)
if ((name = zip_get_name(za, index, flags)) == NULL) {
return -1;
}
entry = za->entry + index;
if ((flags & ZIP_FL_UNCHANGED) == 0 && ZIP_ENTRY_DATA_CHANGED(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_CM_IS_DEFAULT(de->comp_method)) {
if (!(st->valid & ZIP_STAT_COMP_METHOD) || st->comp_method == ZIP_CM_STORE) {
st->valid &= ~(ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD);
}
}
else {
if ((st->valid & ZIP_STAT_COMP_METHOD) && st->comp_method != de->comp_method) {
st->valid &= ~ZIP_STAT_COMP_SIZE;
}
st->valid |= ZIP_STAT_COMP_METHOD;
st->comp_method = de->comp_method;
}
if (((st->valid & (ZIP_STAT_COMP_METHOD|ZIP_STAT_SIZE)) == (ZIP_STAT_COMP_METHOD|ZIP_STAT_SIZE)) && st->comp_method == ZIP_CM_STORE) {
st->valid |= ZIP_STAT_COMP_SIZE;
st->comp_size = st->size;
}
if (entry->changes != NULL && entry->changes->changed & ZIP_DIRENT_LAST_MOD) {
st->mtime = de->last_mod;
st->valid |= ZIP_STAT_MTIME;
@ -70,6 +91,16 @@ zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, zip_stat_t *st)
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;
if (entry->changes != NULL && entry->changes->changed & ZIP_DIRENT_COMP_METHOD) {
st->valid &= ~ZIP_STAT_COMP_SIZE;
}
}
if ((za->ch_flags & ZIP_AFL_WANT_TORRENTZIP) && (flags & ZIP_FL_UNCHANGED) == 0) {
st->comp_method = ZIP_CM_DEFLATE;
st->mtime = _zip_d2u_time(0xbc00, 0x2198);
st->valid |= ZIP_STAT_MTIME | ZIP_STAT_COMP_METHOD;
st->valid &= ~ZIP_STAT_COMP_SIZE;
}
st->index = index;

View File

@ -150,7 +150,7 @@ _zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags,
return NULL;
}
memcpy(s->raw, raw, length);
(void)memcpy_s(s->raw, length + 1, raw, length);
s->raw[length] = '\0';
s->length = length;
s->encoding = ZIP_ENCODING_UNKNOWN;

View File

@ -125,7 +125,7 @@ _zip_winzip_aes_new(const zip_uint8_t *password, zip_uint64_t password_length, c
}
if (password_verify) {
memcpy(password_verify, buffer + (2 * key_size / 8), WINZIP_AES_PASSWORD_VERIFY_LENGTH);
(void)memcpy_s(password_verify, WINZIP_AES_PASSWORD_VERIFY_LENGTH, buffer + (2 * key_size / 8), WINZIP_AES_PASSWORD_VERIFY_LENGTH);
}
return ctx;

View File

@ -8,10 +8,10 @@
based on ../cmake-zipconf.h.in.
*/
#define LIBZIP_VERSION "1.9.2"
#define LIBZIP_VERSION "1.10.0"
#define LIBZIP_VERSION_MAJOR 1
#define LIBZIP_VERSION_MINOR 9
#define LIBZIP_VERSION_MICRO 2
#define LIBZIP_VERSION_MINOR 10
#define LIBZIP_VERSION_MICRO 0
/* #undef ZIP_STATIC */

View File

@ -42,7 +42,9 @@
#include <stdlib.h>
#endif
#ifndef _ZIP_COMPILING_DEPRECATED
#ifdef _ZIP_COMPILING_DEPRECATED
#define ZIP_DEPRECATED(x)
#else
#define ZIP_DISABLE_DEPRECATED
#endif
@ -67,6 +69,12 @@
#define EF_WINZIP_AES_SIZE 7
#define MAX_DATA_DESCRIPTOR_LENGTH 24
#define TORRENTZIP_SIGNATURE "TORRENTZIPPED-"
#define TORRENTZIP_SIGNATURE_LENGTH 14
#define TORRENTZIP_CRC_LENGTH 8
#define TORRENTZIP_MEM_LEVEL 8
#define TORRENTZIP_COMPRESSION_FLAGS ZIP_UINT16_MAX
#define ZIP_CRYPTO_PKWARE_HEADERLEN 12
#define ZIP_CM_REPLACED_DEFAULT (-2)
@ -76,7 +84,6 @@
#define WINZIP_AES_MAX_HEADER_LENGTH (16 + WINZIP_AES_PASSWORD_VERIFY_LENGTH)
#define AES_BLOCK_SIZE 16
#define HMAC_LENGTH 10
#define SHA1_LENGTH 20
#define SALT_LENGTH(method) ((method) == ZIP_EM_AES_128 ? 8 : ((method) == ZIP_EM_AES_192 ? 12 : 16))
#define ZIP_CM_IS_DEFAULT(x) ((x) == ZIP_CM_DEFAULT || (x) == ZIP_CM_REPLACED_DEFAULT)
@ -126,7 +133,7 @@ struct zip_compression_algorithm {
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);
void *(*allocate)(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error);
/* called once to free context */
void (*deallocate)(void *ctx);
@ -170,16 +177,14 @@ const zip_uint8_t *zip_get_extra_field_by_id(zip_t *, int, int, zip_uint16_t, in
user-supplied compression/encryption implementation is finished.
Thus we will keep it private for now. */
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_compress(zip_t *za, zip_source_t *src, zip_int32_t cm, zip_uint32_t compression_flags);
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);
zip_source_t *zip_source_pkware_decode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
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);
bool zip_source_supports_reopen(zip_source_t *src);
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);
@ -300,14 +305,14 @@ struct zip {
zip_hash_t *names; /* hash table for name lookup */
zip_progress_t *progress; /* progress callback for zip_close() */
zip_uint32_t* write_crc; /* have _zip_write() compute CRC */
};
/* file in zip archive, part of API */
struct zip_file {
zip_t *za; /* zip archive containing this file */
zip_error_t error; /* error information */
bool eof;
zip_source_t *src; /* data source */
};
@ -346,7 +351,7 @@ struct zip_dirent {
zip_uint32_t ext_attrib; /* (c) external file attributes */
zip_uint64_t offset; /* (c) offset of local header */
zip_uint16_t compression_level; /* level of compression to use (never valid in orig) */
zip_uint32_t compression_level; /* level of compression to use (never valid in orig) */
zip_uint16_t encryption_method; /* encryption method, computed from other fields */
char *password; /* file specific encryption password */
};
@ -456,7 +461,7 @@ struct zip_buffer {
struct zip_filelist {
zip_uint64_t idx;
/* TODO const char *name; */
const char *name;
};
typedef struct zip_filelist zip_filelist_t;
@ -477,6 +482,8 @@ typedef struct _zip_pkware_keys zip_pkware_keys_t;
#define ZIP_ENTRY_HAS_CHANGES(e) (ZIP_ENTRY_DATA_CHANGED(e) || (e)->deleted || ZIP_ENTRY_CHANGED((e), ZIP_DIRENT_ALL))
#define ZIP_IS_RDONLY(za) ((za)->ch_flags & ZIP_AFL_RDONLY)
#define ZIP_IS_TORRENTZIP(za) ((za)->flags & ZIP_AFL_IS_TORRENTZIP)
#define ZIP_WANT_TORRENTZIP(za) ((za)->ch_flags & ZIP_AFL_WANT_TORRENTZIP)
#ifdef HAVE_EXPLICIT_MEMSET
@ -531,8 +538,11 @@ void _zip_dirent_finalize(zip_dirent_t *);
void _zip_dirent_init(zip_dirent_t *);
bool _zip_dirent_needs_zip64(const zip_dirent_t *, zip_flags_t);
zip_dirent_t *_zip_dirent_new(void);
bool zip_dirent_process_ef_zip64(zip_dirent_t * zde, const zip_uint8_t * ef, zip_uint64_t got_len, bool local, zip_error_t * error);
zip_int64_t _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, bool local, zip_error_t *error);
void _zip_dirent_set_version_needed(zip_dirent_t *de, bool force_zip64);
void zip_dirent_torrentzip_normalize(zip_dirent_t *de);
zip_int32_t _zip_dirent_size(zip_source_t *src, zip_uint16_t, zip_error_t *);
int _zip_dirent_write(zip_t *za, zip_dirent_t *dirent, zip_flags_t flags);
@ -554,7 +564,6 @@ void _zip_error_clear(zip_error_t *);
void _zip_error_get(const zip_error_t *, int *, int *);
void _zip_error_copy(zip_error_t *dst, const zip_error_t *src);
void _zip_error_set_from_source(zip_error_t *, zip_source_t *);
const zip_uint8_t *_zip_extract_extra_field_by_id(zip_error_t *, zip_uint16_t, int, const zip_uint8_t *, zip_uint16_t, zip_uint16_t *);
@ -607,8 +616,7 @@ 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_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);
zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_int64_t length, zip_stat_t *st, zip_uint64_t st_invalid, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, bool take_ownership, 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 *a, const zip_string_t *b);