diff options
Diffstat (limited to 'src/Common')
-rw-r--r-- | src/Common/libzip/NEWS.md | 5 | ||||
-rw-r--r-- | src/Common/libzip/config.h | 2 | ||||
-rw-r--r-- | src/Common/libzip/zip.h | 4 | ||||
-rw-r--r-- | src/Common/libzip/zip_close.c | 5 | ||||
-rw-r--r-- | src/Common/libzip/zip_random_unix.c | 6 | ||||
-rw-r--r-- | src/Common/libzip/zip_random_uwp.c | 1 | ||||
-rw-r--r-- | src/Common/libzip/zip_random_win32.c | 1 | ||||
-rw-r--r-- | src/Common/libzip/zip_set_archive_flag.c | 3 | ||||
-rw-r--r-- | src/Common/libzip/zip_source_file_common.c | 22 | ||||
-rw-r--r-- | src/Common/libzip/zip_source_file_stdio.c | 2 | ||||
-rw-r--r-- | src/Common/libzip/zip_source_file_stdio_named.c | 6 | ||||
-rw-r--r-- | src/Common/libzip/zip_source_file_win32.c | 2 | ||||
-rw-r--r-- | src/Common/libzip/zip_source_file_win32_ansi.c | 2 | ||||
-rw-r--r-- | src/Common/libzip/zip_source_file_win32_utf16.c | 2 | ||||
-rw-r--r-- | src/Common/libzip/zip_source_file_win32_utf8.c | 2 | ||||
-rw-r--r-- | src/Common/libzip/zip_source_pkware_encode.c | 35 | ||||
-rw-r--r-- | src/Common/libzip/zip_source_zip_new.c | 15 | ||||
-rw-r--r-- | src/Common/libzip/zipconf.h | 4 |
18 files changed, 87 insertions, 32 deletions
diff --git a/src/Common/libzip/NEWS.md b/src/Common/libzip/NEWS.md index a8ba5bcf..e117422d 100644 --- a/src/Common/libzip/NEWS.md +++ b/src/Common/libzip/NEWS.md @@ -1,3 +1,8 @@ +# 1.10.1 [2023-08-23] + +* Add `ZIP_LENGTH_TO_END` and `ZIP_LENGTH_UNCHECKED`. Unless `ZIP_LENGTH_UNCHECKED` is used as `length`, it is an error for a file to shrink between the time when the source is created and when its data is read. +* Fix test on Windows. + # 1.10.0 [2023-06-23] * Make support for layered sources public. diff --git a/src/Common/libzip/config.h b/src/Common/libzip/config.h index 755c29ad..2976249c 100644 --- a/src/Common/libzip/config.h +++ b/src/Common/libzip/config.h @@ -88,6 +88,6 @@ #define HAVE_SHARED /* END DEFINES */ #define PACKAGE "libzip" -#define VERSION "1.10.0" +#define VERSION "1.10.1" #endif /* HAD_CONFIG_H */ diff --git a/src/Common/libzip/zip.h b/src/Common/libzip/zip.h index bfe746fe..dc3751c8 100644 --- a/src/Common/libzip/zip.h +++ b/src/Common/libzip/zip.h @@ -116,6 +116,10 @@ extern "C" { #define ZIP_EXTRA_FIELD_ALL ZIP_UINT16_MAX #define ZIP_EXTRA_FIELD_NEW ZIP_UINT16_MAX +/* length parameter to various functions */ + +#define ZIP_LENGTH_TO_END 0 +#define ZIP_LENGTH_UNCHECKED (-2) /* only supported by zip_source_file and its variants */ /* libzip error codes */ diff --git a/src/Common/libzip/zip_close.c b/src/Common/libzip/zip_close.c index 6b33cbf5..ddc2c245 100644 --- a/src/Common/libzip/zip_close.c +++ b/src/Common/libzip/zip_close.c @@ -396,6 +396,11 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { src_final = src; zip_source_keep(src_final); + if (!needs_decrypt && st.encryption_method == ZIP_EM_TRAD_PKWARE && (de->changed & ZIP_DIRENT_LAST_MOD)) { + /* PKWare encryption uses the last modification time for password verification, therefore we can't change it without re-encrypting. Ignoring the requested modification time change seems more sensible than failing to close the archive. */ + de->changed &= ~ZIP_DIRENT_LAST_MOD; + } + if (needs_decrypt) { zip_encryption_implementation impl; diff --git a/src/Common/libzip/zip_random_unix.c b/src/Common/libzip/zip_random_unix.c index f84a5482..867df790 100644 --- a/src/Common/libzip/zip_random_unix.c +++ b/src/Common/libzip/zip_random_unix.c @@ -83,6 +83,11 @@ zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { #ifndef HAVE_RANDOM_UINT32 #include <stdlib.h> +#ifndef HAVE_RANDOM +#define srandom srand +#define random rand +#endif + zip_uint32_t zip_random_uint32(void) { static bool seeded = false; @@ -95,6 +100,7 @@ zip_random_uint32(void) { if (!seeded) { srandom((unsigned int)time(NULL)); + seeded = true; } return (zip_uint32_t)random(); diff --git a/src/Common/libzip/zip_random_uwp.c b/src/Common/libzip/zip_random_uwp.c index 9f842b99..0883ce45 100644 --- a/src/Common/libzip/zip_random_uwp.c +++ b/src/Common/libzip/zip_random_uwp.c @@ -74,6 +74,7 @@ zip_random_uint32(void) { if (!seeded) { srand((unsigned int)time(NULL)); + seeded = true; } return (zip_uint32_t)rand(); diff --git a/src/Common/libzip/zip_random_win32.c b/src/Common/libzip/zip_random_win32.c index 966b9a5e..789b9c20 100644 --- a/src/Common/libzip/zip_random_win32.c +++ b/src/Common/libzip/zip_random_win32.c @@ -74,6 +74,7 @@ zip_random_uint32(void) { if (!seeded) { srand((unsigned int)time(NULL)); + seeded = true; } return (zip_uint32_t)rand(); diff --git a/src/Common/libzip/zip_set_archive_flag.c b/src/Common/libzip/zip_set_archive_flag.c index ec6a86d0..834ef5ba 100644 --- a/src/Common/libzip/zip_set_archive_flag.c +++ b/src/Common/libzip/zip_set_archive_flag.c @@ -57,7 +57,8 @@ zip_set_archive_flag(zip_t *za, zip_flags_t flag, int value) { return 0; } - if (ZIP_IS_RDONLY(za)) { + /* Allow removing ZIP_AFL_RDONLY if manually set, not if archive was opened read-only. */ + if (za->flags & ZIP_AFL_RDONLY) { zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } diff --git a/src/Common/libzip/zip_source_file_common.c b/src/Common/libzip/zip_source_file_common.c index a2a46a44..6c58320f 100644 --- a/src/Common/libzip/zip_source_file_common.c +++ b/src/Common/libzip/zip_source_file_common.c @@ -54,6 +54,7 @@ zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zi zip_source_file_context_t *ctx; zip_source_t *zs; zip_source_file_stat_t sb; + zip_uint64_t length; if (ops == NULL) { zip_error_set(error, ZIP_ER_INVAL, 0); @@ -82,10 +83,17 @@ zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zi } if (len < 0) { - len = 0; + if (len == -1) { + len = ZIP_LENGTH_TO_END; + } + // TODO: return ZIP_ER_INVAL if len != ZIP_LENGTH_UNCHECKED? + length = 0; + } + else { + length = (zip_uint64_t)len; } - if (start > ZIP_INT64_MAX || start + (zip_uint64_t)len < start) { + if (start > ZIP_INT64_MAX || start + length < start) { zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } @@ -107,7 +115,7 @@ zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zi } ctx->f = file; ctx->start = start; - ctx->len = (zip_uint64_t)len; + ctx->len = length; if (st) { (void)memcpy_s(&ctx->st, sizeof(ctx->st), st, sizeof(*st)); ctx->st.name = NULL; @@ -169,9 +177,11 @@ zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zi } if (ctx->len == 0) { - ctx->len = sb.size - ctx->start; - ctx->st.size = ctx->len; - ctx->st.valid |= ZIP_STAT_SIZE; + if (len != ZIP_LENGTH_UNCHECKED) { + ctx->len = sb.size - ctx->start; + ctx->st.size = ctx->len; + ctx->st.valid |= ZIP_STAT_SIZE; + } /* when using a partial file, don't allow writing */ if (ctx->fname && start == 0 && ops->write != NULL) { diff --git a/src/Common/libzip/zip_source_file_stdio.c b/src/Common/libzip/zip_source_file_stdio.c index 7ed91674..6dcc5639 100644 --- a/src/Common/libzip/zip_source_file_stdio.c +++ b/src/Common/libzip/zip_source_file_stdio.c @@ -78,7 +78,7 @@ zip_source_filep(zip_t *za, FILE *file, zip_uint64_t start, zip_int64_t len) { ZIP_EXTERN zip_source_t * zip_source_filep_create(FILE *file, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { - if (file == NULL || length < -1) { + if (file == NULL || length < ZIP_LENGTH_UNCHECKED) { zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } diff --git a/src/Common/libzip/zip_source_file_stdio_named.c b/src/Common/libzip/zip_source_file_stdio_named.c index 51e06a91..1495d7dd 100644 --- a/src/Common/libzip/zip_source_file_stdio_named.c +++ b/src/Common/libzip/zip_source_file_stdio_named.c @@ -101,7 +101,7 @@ zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t le ZIP_EXTERN zip_source_t * zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { - if (fname == NULL || length < -1) { + if (fname == NULL || length < ZIP_LENGTH_UNCHECKED) { zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } @@ -291,7 +291,7 @@ static int create_temp_file(zip_source_file_context_t *ctx, bool create_file) { char *temp; int mode; struct stat st; - int fd; + int fd = 0; char *start, *end; if (stat(ctx->fname, &st) == 0) { @@ -359,7 +359,7 @@ static int create_temp_file(zip_source_file_context_t *ctx, bool create_file) { ctx->tmpname = temp; - return create_file ? fd : 0; + return fd; /* initialized to 0 if !create_file */ } diff --git a/src/Common/libzip/zip_source_file_win32.c b/src/Common/libzip/zip_source_file_win32.c index 4708dc85..624860b1 100644 --- a/src/Common/libzip/zip_source_file_win32.c +++ b/src/Common/libzip/zip_source_file_win32.c @@ -69,7 +69,7 @@ zip_source_win32handle(zip_t *za, HANDLE h, zip_uint64_t start, zip_int64_t len) ZIP_EXTERN zip_source_t * zip_source_win32handle_create(HANDLE h, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { - if (h == INVALID_HANDLE_VALUE || length < -1) { + if (h == INVALID_HANDLE_VALUE || length < ZIP_LENGTH_UNCHECKED) { zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } diff --git a/src/Common/libzip/zip_source_file_win32_ansi.c b/src/Common/libzip/zip_source_file_win32_ansi.c index 31ea48a4..58034cc2 100644 --- a/src/Common/libzip/zip_source_file_win32_ansi.c +++ b/src/Common/libzip/zip_source_file_win32_ansi.c @@ -65,7 +65,7 @@ zip_source_win32a(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t ZIP_EXTERN zip_source_t * zip_source_win32a_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { - if (fname == NULL || length < -1) { + if (fname == NULL || length < ZIP_LENGTH_UNCHECKED) { zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } diff --git a/src/Common/libzip/zip_source_file_win32_utf16.c b/src/Common/libzip/zip_source_file_win32_utf16.c index b2f23419..8f07d021 100644 --- a/src/Common/libzip/zip_source_file_win32_utf16.c +++ b/src/Common/libzip/zip_source_file_win32_utf16.c @@ -67,7 +67,7 @@ zip_source_win32w(zip_t *za, const wchar_t *fname, zip_uint64_t start, zip_int64 ZIP_EXTERN zip_source_t * zip_source_win32w_create(const wchar_t *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { - if (fname == NULL || length < -1) { + if (fname == NULL || length < ZIP_LENGTH_UNCHECKED) { zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } diff --git a/src/Common/libzip/zip_source_file_win32_utf8.c b/src/Common/libzip/zip_source_file_win32_utf8.c index 687c30f9..d154f97a 100644 --- a/src/Common/libzip/zip_source_file_win32_utf8.c +++ b/src/Common/libzip/zip_source_file_win32_utf8.c @@ -49,7 +49,7 @@ zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length wchar_t *wfname; zip_source_t *source; - if (fname == NULL || length < -1) { + if (fname == NULL || length < ZIP_LENGTH_UNCHECKED) { zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } diff --git a/src/Common/libzip/zip_source_pkware_encode.c b/src/Common/libzip/zip_source_pkware_encode.c index cf2d34c9..d89b9f4e 100644 --- a/src/Common/libzip/zip_source_pkware_encode.c +++ b/src/Common/libzip/zip_source_pkware_encode.c @@ -42,6 +42,8 @@ struct trad_pkware { zip_pkware_keys_t keys; zip_buffer_t *buffer; bool eof; + bool mtime_set; + time_t mtime; zip_error_t error; }; @@ -50,7 +52,7 @@ static int encrypt_header(zip_source_t *, struct trad_pkware *); static zip_int64_t pkware_encrypt(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t); static void trad_pkware_free(struct trad_pkware *); static struct trad_pkware *trad_pkware_new(const char *password, zip_error_t *error); - +static void set_mtime(struct trad_pkware* ctx, zip_stat_t* st); zip_source_t * zip_source_pkware_encode(zip_t *za, zip_source_t *src, zip_uint16_t em, int flags, const char *password) { @@ -81,16 +83,19 @@ zip_source_pkware_encode(zip_t *za, zip_source_t *src, zip_uint16_t em, int flag static int encrypt_header(zip_source_t *src, struct trad_pkware *ctx) { - struct zip_stat st; unsigned short dostime, dosdate; zip_uint8_t *header; - if (zip_source_stat(src, &st) != 0) { - zip_error_set_from_source(&ctx->error, src); - return -1; + if (!ctx->mtime_set) { + struct zip_stat st; + if (zip_source_stat(src, &st) != 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + set_mtime(ctx, &st); } - _zip_u2d_time(st.mtime, &dostime, &dosdate); + _zip_u2d_time(ctx->mtime, &dostime, &dosdate); if ((ctx->buffer = _zip_buffer_new(NULL, ZIP_CRYPTO_PKWARE_HEADERLEN)) == NULL) { zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); @@ -182,6 +187,9 @@ pkware_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length, zip if (st->valid & ZIP_STAT_COMP_SIZE) { st->comp_size += ZIP_CRYPTO_PKWARE_HEADERLEN; } + set_mtime(ctx, st); + st->mtime = ctx->mtime; + st->valid |= ZIP_STAT_MTIME; return 0; } @@ -229,6 +237,8 @@ trad_pkware_new(const char *password, zip_error_t *error) { return NULL; } ctx->buffer = NULL; + ctx->mtime_set = false; + ctx->mtime = 0; zip_error_init(&ctx->error); return ctx; @@ -246,3 +256,16 @@ trad_pkware_free(struct trad_pkware *ctx) { zip_error_fini(&ctx->error); free(ctx); } + + +static void set_mtime(struct trad_pkware* ctx, zip_stat_t* st) { + if (!ctx->mtime_set) { + if (st->valid & ZIP_STAT_MTIME) { + ctx->mtime = st->mtime; + } + else { + time(&ctx->mtime); + } + ctx->mtime_set = true; + } +} diff --git a/src/Common/libzip/zip_source_zip_new.c b/src/Common/libzip/zip_source_zip_new.c index d2d66d4c..ecccdd68 100644 --- a/src/Common/libzip/zip_source_zip_new.c +++ b/src/Common/libzip/zip_source_zip_new.c @@ -53,6 +53,7 @@ ZIP_EXTERN zip_source_t *zip_source_zip_file_create(zip_t *srcza, zip_uint64_t s zip_flags_t stat_flags; zip_int64_t data_len; bool take_ownership = false; + bool empty_data = false; if (srcza == NULL || srcidx >= srcza->nentry || len < -1) { zip_error_set(error, ZIP_ER_INVAL, 0); @@ -147,15 +148,13 @@ ZIP_EXTERN zip_source_t *zip_source_zip_file_create(zip_t *srcza, zip_uint64_t s _zip_file_attributes_from_dirent(&attributes, de); 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; - } + if (needs_decrypt || needs_decompress) { + empty_data = (have_comp_size && st.comp_size == 0); + } + else { + empty_data = (have_size && st.size == 0); } - else if (have_size && st.size == 0) { + if (empty_data) { src = zip_source_buffer_with_attributes_create(NULL, 0, 0, &attributes, error); } else { diff --git a/src/Common/libzip/zipconf.h b/src/Common/libzip/zipconf.h index 2f8106a4..472e06c1 100644 --- a/src/Common/libzip/zipconf.h +++ b/src/Common/libzip/zipconf.h @@ -8,10 +8,10 @@ based on ../cmake-zipconf.h.in. */ -#define LIBZIP_VERSION "1.10.0" +#define LIBZIP_VERSION "1.10.1" #define LIBZIP_VERSION_MAJOR 1 #define LIBZIP_VERSION_MINOR 10 -#define LIBZIP_VERSION_MICRO 0 +#define LIBZIP_VERSION_MICRO 1 /* #undef ZIP_STATIC */ |