3rdparty: Update libzip to 1.14

This commit is contained in:
JordanTheToaster 2025-07-06 00:53:47 +01:00 committed by lightningterror
parent e76481f454
commit cde548a2f9
24 changed files with 389 additions and 247 deletions

0
.github/workflows/scripts/linux/build-dependencies-qt.sh vendored Normal file → Executable file
View File

View File

@ -196,6 +196,7 @@ add_library(zip STATIC
lib/zip_name_locate.c
lib/zip_new.c
lib/zip_open.c
lib/zip_realloc.c
lib/zip_pkware.c
lib/zip_progress.c
lib/zip_rename.c

View File

@ -34,6 +34,15 @@
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(__has_feature)
#if !__has_feature(nullability)
#define _Nullable
#define _Nonnull
#endif
#else
#define _Nullable
#define _Nonnull
#endif
#ifdef __cplusplus
extern "C" {

View File

@ -44,10 +44,7 @@ _zip_add_entry(zip_t *za) {
zip_uint64_t idx;
if (za->nentry + 1 >= za->nentry_alloc) {
zip_entry_t *rentries;
zip_uint64_t nalloc = za->nentry_alloc;
zip_uint64_t additional_entries = 2 * nalloc;
zip_uint64_t realloc_size;
zip_uint64_t additional_entries = 2 * za->nentry_alloc;
if (additional_entries < 16) {
additional_entries = 16;
@ -55,21 +52,10 @@ _zip_add_entry(zip_t *za) {
else if (additional_entries > 1024) {
additional_entries = 1024;
}
/* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */
nalloc += additional_entries;
realloc_size = sizeof(struct zip_entry) * (size_t)nalloc;
if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
if (!ZIP_REALLOC(za->entry, za->nentry_alloc, additional_entries, &za->error)) {
return -1;
}
rentries = (zip_entry_t *)realloc(za->entry, sizeof(struct zip_entry) * (size_t)nalloc);
if (rentries == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
za->entry = rentries;
za->nentry_alloc = nalloc;
}
idx = za->nentry++;

View File

@ -208,11 +208,11 @@ input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
}
static void
end_of_input(void *ud) {
static bool end_of_input(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
ctx->end_of_input = true;
return ctx->zstr.avail_in != 0;
}

View File

@ -196,11 +196,11 @@ input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
}
static void
end_of_input(void *ud) {
static bool end_of_input(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
ctx->end_of_input = true;
return ctx->zstr.avail_in != 0;
}

View File

@ -302,11 +302,11 @@ input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
}
static void
end_of_input(void *ud) {
static bool end_of_input(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
ctx->end_of_input = true;
return ctx->zstr.avail_in != 0;
}

View File

@ -211,11 +211,11 @@ input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
}
static void
end_of_input(void *ud) {
static bool end_of_input(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
ctx->end_of_input = true;
return ctx->in.pos != ctx->in.size;
}

View File

@ -42,7 +42,7 @@
#endif
static int add_data(zip_t *, zip_source_t *, zip_dirent_t *, zip_uint32_t);
static int add_data(zip_t *, zip_source_t *, zip_dirent_t *);
static int copy_data(zip_t *, zip_uint64_t);
static int copy_source(zip_t *, zip_source_t *, zip_source_t *, zip_int64_t);
static int torrentzip_compare_names(const void *a, const void *b);
@ -195,6 +195,12 @@ zip_close(zip_t *za) {
break;
}
}
else if (entry->orig != NULL) {
if (!_zip_dirent_merge(entry->changes, entry->orig, ZIP_ENTRY_DATA_CHANGED(entry), &za->error)) {
error = 1;
break;
}
}
de = entry->changes;
if (_zip_read_local_ef(za, i) < 0) {
@ -225,7 +231,7 @@ zip_close(zip_t *za) {
}
/* add_data writes dirent */
if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) {
if (add_data(za, zs ? zs : entry->source, de) < 0) {
error = 1;
if (zs)
zip_source_free(zs);
@ -295,8 +301,7 @@ zip_close(zip_t *za) {
}
static int
add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
static int add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
zip_int64_t offstart, offdata, offend, data_length;
zip_stat_t st;
zip_file_attributes_t attributes;
@ -305,19 +310,25 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
int is_zip64;
zip_flags_t flags;
bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
bool dirent_changed;
bool have_dos_time = false;
time_t mtime_before_copy;
if (zip_source_stat(src, &st) < 0) {
zip_error_set_from_source(&za->error, src);
return -1;
}
de->bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR;
if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
st.valid |= ZIP_STAT_COMP_METHOD;
st.comp_method = ZIP_CM_STORE;
}
if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE)
if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE) {
de->comp_method = st.comp_method;
}
else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
st.valid |= ZIP_STAT_COMP_SIZE;
st.comp_size = st.size;
@ -372,14 +383,30 @@ 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);
return -1;
if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
int ret2 = zip_source_get_dos_time(src, &de->last_mod);
if (ret2 < 0) {
zip_error_set_from_source(&za->error, src);
return -1;
}
if (ret2 == 1) {
have_dos_time = true;
}
else {
if (st.valid & ZIP_STAT_MTIME) {
mtime_before_copy = st.mtime;
}
else {
time(&mtime_before_copy);
}
if (_zip_u2d_time(mtime_before_copy, &de->last_mod, &za->error) < 0) {
return -1;
}
}
}
/* as long as we don't support non-seekable output, clear data descriptor bit */
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
if ((is_zip64 = _zip_dirent_write(za, de, flags)) < 0) {
if ((offstart = zip_source_tell_write(za->src)) < 0) {
zip_error_set_from_source(&za->error, za->src);
return -1;
}
@ -485,9 +512,24 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
src_final = src_tmp;
}
if (!ZIP_WANT_TORRENTZIP(za)) {
if (zip_source_get_file_attributes(src_final, &attributes) != 0) {
zip_error_set_from_source(&za->error, src_final);
zip_source_free(src_final);
return -1;
}
_zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0);
}
/* as long as we don't support non-seekable output, clear data descriptor bit */
if ((is_zip64 = _zip_dirent_write(za, de, flags)) < 0) {
zip_source_free(src_final);
return -1;
}
if ((offdata = zip_source_tell_write(za->src)) < 0) {
zip_error_set_from_source(&za->error, za->src);
zip_source_free(src_final);
return -1;
}
@ -498,9 +540,11 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
ret = -1;
}
if (zip_source_get_file_attributes(src_final, &attributes) != 0) {
zip_error_set_from_source(&za->error, src_final);
ret = -1;
if (!ZIP_WANT_TORRENTZIP(za)) {
if (zip_source_get_file_attributes(src_final, &attributes) != 0) {
zip_error_set_from_source(&za->error, src_final);
ret = -1;
}
}
zip_source_free(src_final);
@ -514,57 +558,51 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
return -1;
}
if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
zip_error_set_from_source(&za->error, za->src);
return -1;
}
if ((st.valid & (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) {
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
}
if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
int ret2 = zip_source_get_dos_time(src, &de->last_mod);
if (ret2 < 0) {
zip_error_set_from_source(&za->error, src);
return -1;
}
if (ret2 == 0) {
time_t mtime;
if (st.valid & ZIP_STAT_MTIME) {
mtime = st.mtime;
}
else {
time(&mtime);
}
if (_zip_u2d_time(mtime, &de->last_mod, &za->error) < 0) {
return -1;
}
}
}
dirent_changed = ZIP_CM_ACTUAL(de->comp_method) != st.comp_method || de->crc != st.crc || de->uncomp_size != st.size || de->comp_size != (zip_uint64_t)(offend - offdata);
de->comp_method = st.comp_method;
de->crc = st.crc;
de->uncomp_size = st.size;
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 (!ZIP_WANT_TORRENTZIP(za)) {
dirent_changed |= _zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0);
if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0 && !have_dos_time) {
if (st.valid & ZIP_STAT_MTIME) {
if (st.mtime != mtime_before_copy) {
if (_zip_u2d_time(st.mtime, &de->last_mod, &za->error) < 0) {
return -1;
}
dirent_changed = true;
}
}
}
}
if ((ret = _zip_dirent_write(za, de, flags)) < 0)
return -1;
if (dirent_changed) {
if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
zip_error_set_from_source(&za->error, za->src);
return -1;
}
if (is_zip64 != ret) {
/* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
}
if ((ret = _zip_dirent_write(za, de, flags)) < 0)
return -1;
if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
zip_error_set_from_source(&za->error, za->src);
return -1;
if (is_zip64 != ret) {
/* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
}
if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
zip_error_set_from_source(&za->error, za->src);
return -1;
}
}
if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {

View File

@ -83,32 +83,21 @@ _zip_cdir_new(zip_error_t *error) {
bool
_zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error) {
zip_uint64_t i, new_alloc;
zip_entry_t *new_entry;
zip_uint64_t i;
if (additional_entries == 0) {
return true;
}
new_alloc = cd->nentry_alloc + additional_entries;
if (new_alloc < additional_entries || new_alloc > SIZE_MAX / sizeof(*(cd->entry))) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
if (!ZIP_REALLOC(cd->entry, cd->nentry_alloc, additional_entries, error)) {
return false;
}
if ((new_entry = (zip_entry_t *)realloc(cd->entry, sizeof(*(cd->entry)) * (size_t)new_alloc)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
}
cd->entry = new_entry;
for (i = cd->nentry; i < new_alloc; i++) {
for (i = cd->nentry; i < cd->nentry_alloc; i++) {
_zip_entry_init(cd->entry + i);
}
cd->nentry = cd->nentry_alloc = new_alloc;
cd->nentry = cd->nentry_alloc;
return true;
}
@ -275,6 +264,55 @@ _zip_dirent_free(zip_dirent_t *zde) {
}
bool
_zip_dirent_merge(zip_dirent_t *de, zip_dirent_t *de_orig, bool replacing_data, zip_error_t *error) {
if (!de->cloned) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
return false;
}
if (!(de->changed & ZIP_DIRENT_ATTRIBUTES)) {
de->ext_attrib = de_orig->ext_attrib;
de->int_attrib = de_orig->int_attrib;
}
if (!(de->changed & ZIP_DIRENT_COMMENT)) {
de->comment = de_orig->comment;
}
if (!(de->changed & ZIP_DIRENT_COMP_METHOD)) {
if (replacing_data) {
de->comp_method = ZIP_CM_DEFAULT;
de->compression_level = 0;
}
else {
de->comp_method = de_orig->comp_method;
de->compression_level = de_orig->compression_level;
}
}
if (!(de->changed & ZIP_DIRENT_ENCRYPTION_METHOD)) {
if (replacing_data) {
de->encryption_method = ZIP_EM_NONE;
}
else {
de->encryption_method = de_orig->encryption_method;
}
}
if (!(de->changed & ZIP_DIRENT_EXTRA_FIELD)) {
de->extra_fields = de_orig->extra_fields;
}
if (!(de->changed & ZIP_DIRENT_FILENAME)) {
de->filename = de_orig->filename;
}
if (!(de->changed & ZIP_DIRENT_LAST_MOD)) {
de->last_mod = de_orig->last_mod;
}
if (!(de->changed & ZIP_DIRENT_PASSWORD)) {
de->password = de_orig->password;
}
return true;
}
void
_zip_dirent_init(zip_dirent_t *de) {
de->changed = 0;
@ -968,7 +1006,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
_zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES);
}
else {
_zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method);
_zip_buffer_put_16(buffer, (zip_uint16_t)ZIP_CM_ACTUAL(de->comp_method));
}
if (ZIP_WANT_TORRENTZIP(za)) {
@ -1190,52 +1228,76 @@ _zip_u2d_time(time_t intime, zip_dostime_t *dtime, zip_error_t *ze) {
}
void
_zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64, zip_uint32_t changed) {
bool
_zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64) {
zip_uint16_t length;
bool has_changed = false;
if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) {
zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
de->bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask);
zip_uint16_t bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask);
if (de->bitflags != bitflags) {
de->bitflags = bitflags;
has_changed = true;
}
}
if (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) {
de->int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0);
zip_uint16_t int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0);
if (de->int_attrib != int_attrib) {
de->int_attrib = int_attrib;
has_changed = true;
}
}
/* manually set attributes are preferred over attributes provided by source */
if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES)) {
de->ext_attrib = attributes->external_file_attributes;
if ((de->changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES)) {
if (de->ext_attrib != attributes->external_file_attributes) {
de->ext_attrib = attributes->external_file_attributes;
has_changed = true;
}
}
zip_uint16_t version_needed;
if (de->comp_method == ZIP_CM_LZMA) {
de->version_needed = 63;
version_needed = 63;
}
else if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) {
de->version_needed = 51;
version_needed = 51;
}
else if (de->comp_method == ZIP_CM_BZIP2) {
de->version_needed = 46;
version_needed = 46;
}
else if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
de->version_needed = 45;
version_needed = 45;
}
else if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
de->version_needed = 20;
version_needed = 20;
}
else if ((length = _zip_string_length(de->filename)) > 0 && de->filename->raw[length - 1] == '/') {
de->version_needed = 20;
version_needed = 20;
}
else {
de->version_needed = 10;
version_needed = 10;
}
if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
de->version_needed = ZIP_MAX(de->version_needed, attributes->version_needed);
version_needed = ZIP_MAX(version_needed, attributes->version_needed);
}
de->version_madeby = 63 | (de->version_madeby & 0xff00);
if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM)) {
de->version_madeby = (de->version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8);
if (de->version_needed != version_needed) {
de->version_needed = version_needed;
has_changed = true;
}
zip_int16_t version_madeby = 63 | (de->version_madeby & 0xff00);
if ((de->changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM)) {
version_madeby = (version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8);
}
if (de->version_madeby != version_madeby) {
de->version_madeby = version_madeby;
has_changed = true;
}
return has_changed;
}
@ -1259,13 +1321,36 @@ zip_dirent_torrentzip_normalize(zip_dirent_t *de) {
int
zip_dirent_check_consistency(zip_dirent_t *dirent) {
if (dirent->comp_method == ZIP_CM_STORE && dirent->comp_size != dirent->uncomp_size) {
return ZIP_ER_DETAIL_STORED_SIZE_MISMATCH;
if (dirent->comp_method == ZIP_CM_STORE) {
zip_uint64_t header_size = 0;
switch (dirent->encryption_method) {
case ZIP_EM_NONE:
break;
case ZIP_EM_TRAD_PKWARE:
header_size = 12;
break;
case ZIP_EM_AES_128:
header_size = 20;
break;
case ZIP_EM_AES_192:
header_size = 24;
break;
case ZIP_EM_AES_256:
header_size = 28;
break;
default:
return 0;
}
if (dirent->uncomp_size + header_size < dirent->uncomp_size || dirent->comp_size != dirent->uncomp_size + header_size) {
return ZIP_ER_DETAIL_STORED_SIZE_MISMATCH;
}
}
return 0;
}
time_t zip_dirent_get_last_mod_mtime(zip_dirent_t *de) {
time_t
zip_dirent_get_last_mod_mtime(zip_dirent_t *de) {
if (!de->last_mod_mtime_valid) {
de->last_mod_mtime = _zip_d2u_time(&de->last_mod);
de->last_mod_mtime_valid = true;

View File

@ -41,6 +41,9 @@ ZIP_EXTERN int
zip_fclose(zip_file_t *zf) {
int ret;
if (zf == NULL)
return ZIP_ER_INVAL;
if (zf->src)
zip_source_free(zf->src);

View File

@ -40,7 +40,7 @@
ZIP_EXTERN int
zip_file_set_encryption(zip_t *za, zip_uint64_t idx, zip_uint16_t method, const char *password) {
zip_entry_t *e;
zip_uint16_t old_method;
char *our_password = NULL;
if (idx >= za->nentry) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
@ -63,56 +63,33 @@ zip_file_set_encryption(zip_t *za, zip_uint64_t idx, zip_uint16_t method, const
e = za->entry + idx;
old_method = (e->orig == NULL ? ZIP_EM_NONE : e->orig->encryption_method);
if (method == old_method && password == NULL) {
if (e->changes) {
if (e->changes->changed & ZIP_DIRENT_PASSWORD) {
_zip_crypto_clear(e->changes->password, strlen(e->changes->password));
free(e->changes->password);
e->changes->password = (e->orig == NULL ? NULL : e->orig->password);
}
e->changes->changed &= ~(ZIP_DIRENT_ENCRYPTION_METHOD | ZIP_DIRENT_PASSWORD);
if (e->changes->changed == 0) {
_zip_dirent_free(e->changes);
e->changes = NULL;
}
if (e->changes == NULL) {
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
if (password) {
if ((our_password = strdup(password)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
e->changes->encryption_method = method;
e->changes->changed |= ZIP_DIRENT_ENCRYPTION_METHOD;
if (password) {
e->changes->password = our_password;
e->changes->changed |= ZIP_DIRENT_PASSWORD;
}
else {
char *our_password = NULL;
if (password) {
if ((our_password = strdup(password)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
if (e->changes == NULL) {
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
if (our_password) {
_zip_crypto_clear(our_password, strlen(our_password));
}
free(our_password);
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
e->changes->encryption_method = method;
e->changes->changed |= ZIP_DIRENT_ENCRYPTION_METHOD;
if (password) {
e->changes->password = our_password;
e->changes->changed |= ZIP_DIRENT_PASSWORD;
}
else {
if (e->changes->changed & ZIP_DIRENT_PASSWORD) {
_zip_crypto_clear(e->changes->password, strlen(e->changes->password));
free(e->changes->password);
e->changes->password = e->orig ? e->orig->password : NULL;
e->changes->changed &= ~ZIP_DIRENT_PASSWORD;
}
if (e->changes->changed & ZIP_DIRENT_PASSWORD) {
_zip_crypto_clear(e->changes->password, strlen(e->changes->password));
free(e->changes->password);
e->changes->password = e->orig ? e->orig->password : NULL;
e->changes->changed &= ~ZIP_DIRENT_PASSWORD;
}
}

View File

@ -207,7 +207,7 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) {
if ((cdir = _zip_find_central_dir(za, len)) == NULL) {
_zip_error_copy(error, &za->error);
if (zip_error_code_zip(error) == ZIP_ER_NOZIP) {
if (zip_error_code_zip(&za->error) == ZIP_ER_NOZIP) {
/* not a zip - find out if it's truncated */
if (_is_truncated_zip(src)) {
zip_error_set(error, ZIP_ER_TRUNCATED_ZIP, 0);

62
3rdparty/libzip/lib/zip_realloc.c vendored Normal file
View File

@ -0,0 +1,62 @@
/*
zip_realloc.c -- reallocate with additional elements
Copyright (C) 2009-2025 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 <stdlib.h>
#include "zipint.h"
bool zip_realloc(void **memory, zip_uint64_t *alloced_elements, zip_uint64_t element_size, zip_uint64_t additional_elements, zip_error_t *error) {
zip_uint64_t new_alloced_elements;
void *new_memory;
if (additional_elements == 0) {
return true;
}
new_alloced_elements = *alloced_elements + additional_elements;
if (new_alloced_elements < additional_elements || new_alloced_elements > SIZE_MAX / element_size) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
}
if ((new_memory = realloc(*memory, (size_t)(new_alloced_elements * element_size))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
}
*memory = new_memory;
*alloced_elements = new_alloced_elements;
return true;
}

View File

@ -38,7 +38,6 @@
ZIP_EXTERN int
zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_uint32_t flags) {
zip_entry_t *e;
zip_int32_t old_method;
if (idx >= za->nentry) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
@ -61,35 +60,21 @@ zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_ui
e = za->entry + idx;
old_method = (e->orig == NULL ? ZIP_CM_DEFAULT : e->orig->comp_method);
/* TODO: do we want to recompress if level is set? Only if it's
* different than what bit flags tell us, but those are not
* defined for all compression methods, or not directly mappable
* to levels */
if (method == old_method) {
if (e->changes) {
e->changes->changed &= ~ZIP_DIRENT_COMP_METHOD;
e->changes->compression_level = 0;
if (e->changes->changed == 0) {
_zip_dirent_free(e->changes);
e->changes = NULL;
}
if (e->changes == NULL) {
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
else {
if (e->changes == NULL) {
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
e->changes->comp_method = method;
e->changes->compression_level = (zip_uint16_t)flags;
e->changes->changed |= ZIP_DIRENT_COMP_METHOD;
}
e->changes->comp_method = method;
e->changes->compression_level = (zip_uint16_t)flags;
e->changes->changed |= ZIP_DIRENT_COMP_METHOD;
return 0;
}

View File

@ -340,6 +340,7 @@ buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) {
fragment_offset = offset - buffer->fragment_offsets[fragment];
if (fragment_offset == 0) {
/* We can't be at beginning of fragment zero if offset > 0. */
fragment--;
fragment_offset = buffer->fragments[fragment].length;
}
@ -427,32 +428,23 @@ buffer_free(buffer_t *buffer) {
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 additional_fragments;
zip_uint64_t offset_capacity = buffer->fragments_capacity + 1;
if (capacity < buffer->fragments_capacity) {
if (capacity <= buffer->fragments_capacity) {
return true;
}
zip_uint64_t fragments_size = sizeof(buffer->fragments[0]) * capacity;
zip_uint64_t offsets_size = sizeof(buffer->fragment_offsets[0]) * (capacity + 1);
additional_fragments = capacity - buffer->fragments_capacity;
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);
if (!ZIP_REALLOC(buffer->fragments, buffer->fragments_capacity, additional_fragments, error)) {
return false;
}
if ((fragments = realloc(buffer->fragments, (size_t)fragments_size)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
/* The size of both buffer->fragments and buffer->fragment_offsets is stored in buffer->fragments_capacity, so use a temporary capacity variable here for reallocating buffer->fragment_offsets. */
if (!ZIP_REALLOC(buffer->fragment_offsets, offset_capacity, additional_fragments, error)) {
buffer->fragments_capacity -= additional_fragments;
return false;
}
buffer->fragments = fragments;
if ((offsets = realloc(buffer->fragment_offsets, (size_t)offsets_size)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
}
buffer->fragment_offsets = offsets;
buffer->fragments_capacity = capacity;
return true;
}

View File

@ -44,6 +44,7 @@ struct context {
bool can_store;
bool is_stored; /* only valid if end_of_stream is true */
bool compress;
bool check_consistency;
zip_int32_t method;
zip_uint64_t size;
@ -86,11 +87,10 @@ static size_t implementations_size = sizeof(implementations) / sizeof(implementa
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, zip_uint32_t 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, bool check_consistency);
static zip_int64_t compress_read(zip_source_t *, struct context *, void *, zip_uint64_t);
zip_compression_algorithm_t *
_zip_get_compression_algorithm(zip_int32_t method, bool compress) {
zip_compression_algorithm_t *_zip_get_compression_algorithm(zip_int32_t method, bool compress) {
size_t i;
zip_uint16_t real_method = ZIP_CM_ACTUAL(method);
@ -108,16 +108,14 @@ _zip_get_compression_algorithm(zip_int32_t method, bool compress) {
return NULL;
}
ZIP_EXTERN int
zip_compression_method_supported(zip_int32_t method, int compress) {
ZIP_EXTERN int zip_compression_method_supported(zip_int32_t method, int compress) {
if (method == ZIP_CM_STORE) {
return 1;
}
return _zip_get_compression_algorithm(method, compress) != NULL;
}
zip_source_t *
zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t method, zip_uint32_t compression_flags) {
zip_source_t *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);
}
@ -127,8 +125,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, zip_uint32_t 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) {
struct context *ctx;
zip_source_t *s2;
zip_compression_algorithm_t *algorithm = NULL;
@ -143,7 +140,7 @@ compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool co
return NULL;
}
if ((ctx = context_new(method, compress, compression_flags, algorithm)) == NULL) {
if ((ctx = context_new(method, compress, compression_flags, algorithm, za->open_flags & ZIP_CHECKCONS)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return NULL;
}
@ -157,8 +154,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, zip_uint32_t 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, bool check_consistency) {
struct context *ctx;
if ((ctx = (struct context *)malloc(sizeof(*ctx))) == NULL) {
@ -172,6 +168,7 @@ context_new(zip_int32_t method, bool compress, zip_uint32_t compression_flags, z
ctx->end_of_input = false;
ctx->end_of_stream = false;
ctx->is_stored = false;
ctx->check_consistency = check_consistency;
if ((ctx->ud = ctx->algorithm->allocate(ZIP_CM_ACTUAL(method), compression_flags, &ctx->error)) == NULL) {
zip_error_fini(&ctx->error);
@ -228,7 +225,23 @@ compress_read(zip_source_t *src, struct context *ctx, void *data, zip_uint64_t l
ctx->end_of_stream = true;
if (!ctx->end_of_input) {
/* TODO: garbage after stream, or compression ended before all data read */
n = zip_source_read(src, ctx->buffer, 1);
if (n < 0) {
zip_error_set_from_source(&ctx->error, src);
end = true;
break;
}
else if (n == 0) {
ctx->end_of_input = true;
n = ctx->algorithm->end_of_input(ctx->ud) ? 1 : 0;
}
if (n > 0 && ctx->check_consistency) {
/* garbage after stream, or compression ended before all data read */
zip_error_set(&ctx->error, ZIP_ER_INCONS, ZIP_ER_DETAIL_COMPRESSED_DATA_TRAILING_GARBAGE);
end = true;
break;
}
}
if (ctx->first_read < 0) {

View File

@ -95,9 +95,11 @@ _zip_stdio_op_close(zip_source_file_context_t *ctx) {
zip_int64_t
_zip_stdio_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len) {
size_t i;
#if SIZE_MAX < ZIP_UINT64_MAX
if (len > SIZE_MAX) {
len = SIZE_MAX;
}
#endif
if ((i = fread(buf, 1, (size_t)len, ctx->f)) == 0) {
if (ferror((FILE *)ctx->f)) {

View File

@ -33,13 +33,6 @@
#include "zip_source_file_win32.h"
/* ACL is not available when targeting the games API partition */
#if defined(WINAPI_FAMILY_PARTITION) && defined(WINAPI_PARTITION_GAMES)
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_GAMES)
#define ACL_UNSUPPORTED
#endif
#endif
static zip_int64_t _zip_win32_named_op_commit_write(zip_source_file_context_t *ctx);
static zip_int64_t _zip_win32_named_op_create_temp_output(zip_source_file_context_t *ctx);
static bool _zip_win32_named_op_open(zip_source_file_context_t *ctx);
@ -106,29 +99,24 @@ _zip_win32_named_op_create_temp_output(zip_source_file_context_t *ctx) {
zip_uint32_t value, i;
HANDLE th = INVALID_HANDLE_VALUE;
PSECURITY_DESCRIPTOR psd = NULL;
PSECURITY_ATTRIBUTES psa = NULL;
PSECURITY_DESCRIPTOR psd = NULL;
#ifdef HAVE_GETSECURITYINFO
SECURITY_ATTRIBUTES sa;
SECURITY_INFORMATION si;
DWORD success;
PACL dacl = NULL;
#endif
char *tempname = NULL;
size_t tempname_size = 0;
#ifdef HAVE_GETSECURITYINFO
if ((HANDLE)ctx->f != INVALID_HANDLE_VALUE && GetFileType((HANDLE)ctx->f) == FILE_TYPE_DISK) {
si = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION;
#ifdef ACL_UNSUPPORTED
success = ERROR_NOT_SUPPORTED;
#else
success = GetSecurityInfo((HANDLE)ctx->f, SE_FILE_OBJECT, si, NULL, NULL, &dacl, NULL, &psd);
#endif
if (success == ERROR_SUCCESS) {
if (GetSecurityInfo((HANDLE)ctx->f, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &psd) == ERROR_SUCCESS) {
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = FALSE;
sa.lpSecurityDescriptor = psd;
psa = &sa;
}
}
#endif
#ifndef MS_UWP
value = GetTickCount();

View File

@ -39,8 +39,7 @@ zip_file_attributes_init(zip_file_attributes_t *attributes) {
attributes->version = 1;
}
int
zip_source_get_file_attributes(zip_source_t *src, zip_file_attributes_t *attributes) {
int zip_source_get_file_attributes(zip_source_t *src, zip_file_attributes_t *attributes) {
if (src->source_closed) {
return -1;
}

View File

@ -198,8 +198,10 @@ pkware_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length, zip
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
return -1;
}
attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED;
attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED | ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS;
attributes->version_needed = 20;
attributes->general_purpose_bit_flags = ZIP_GPBF_DATA_DESCRIPTOR;
attributes->general_purpose_bit_mask = ZIP_GPBF_DATA_DESCRIPTOR;
return 0;
}

View File

@ -345,7 +345,7 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou
void
_zip_deregister_source(zip_t *za, zip_source_t *src) {
unsigned int i;
zip_uint64_t i;
for (i = 0; i < za->nopen_source; i++) {
if (za->open_source[i] == src) {
@ -359,18 +359,10 @@ _zip_deregister_source(zip_t *za, zip_source_t *src) {
int
_zip_register_source(zip_t *za, zip_source_t *src) {
zip_source_t **open_source;
if (za->nopen_source + 1 >= za->nopen_source_alloc) {
unsigned int n;
n = za->nopen_source_alloc + 10;
open_source = (zip_source_t **)realloc(za->open_source, n * sizeof(zip_source_t *));
if (open_source == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
if (!ZIP_REALLOC(za->open_source, za->nopen_source_alloc, 10, &za->error)) {
return -1;
}
za->nopen_source_alloc = n;
za->open_source = open_source;
}
za->open_source[za->nopen_source++] = src;

View File

@ -102,11 +102,14 @@
/* according to unzip-6.0's zipinfo.c, this corresponds to a directory with rwx permissions for everyone */
#define ZIP_EXT_ATTRIB_DEFAULT_DIR (0040777u << 16)
#define ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK 0x0836
/* Allowed: Encryption specific bits, data descriptor, compression specific, UTF-8 filename */
#define ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK 0x083e
#define ZIP_MAX(a, b) ((a) > (b) ? (a) : (b))
#define ZIP_MIN(a, b) ((a) < (b) ? (a) : (b))
#define ZIP_REALLOC(memory, alloced_elements, additional_elements, error) zip_realloc((void **)&memory, &alloced_elements, sizeof(*memory), additional_elements, error)
/* This section contains API that won't materialize like this. It's
placed in the internal section, pending cleanup. */
@ -152,7 +155,7 @@ struct zip_compression_algorithm {
bool (*input)(void *ctx, zip_uint8_t *data, zip_uint64_t length);
/* all input data has been provided */
void (*end_of_input)(void *ctx);
bool (*end_of_input)(void *ctx);
/* process input data, writing to data, which has room for length bytes, update length to number of bytes written */
zip_compression_status_t (*process)(void *ctx, zip_uint8_t *data, zip_uint64_t *length);
@ -241,6 +244,7 @@ extern const int _zip_err_details_count;
#define ZIP_ER_DETAIL_EOCD64_LOCATOR_MISMATCH 22 /* G EOCD64 and EOCD64 locator do not match */
#define ZIP_ER_DETAIL_UTF8_FILENAME_MISMATCH 23 /* E UTF-8 filename is ASCII and doesn't match filename */
#define ZIP_ER_DETAIL_UTF8_COMMENT_MISMATCH 24 /* E UTF-8 comment is ASCII and doesn't match comment */
#define ZIP_ER_DETAIL_COMPRESSED_DATA_TRAILING_GARBAGE 25 /* G garbage at end of compressed data */
/* directory entry: general purpose bit flags */
@ -305,8 +309,8 @@ struct zip {
zip_uint64_t nentry_alloc; /* number of entries allocated */
zip_entry_t *entry; /* entries */
unsigned int nopen_source; /* number of open sources using archive */
unsigned int nopen_source_alloc; /* number of sources allocated */
zip_uint64_t nopen_source; /* number of open sources using archive */
zip_uint64_t nopen_source_alloc; /* number of sources allocated */
zip_source_t **open_source; /* open sources using archive */
zip_hash_t *names; /* hash table for name lookup */
@ -552,13 +556,14 @@ zip_int64_t _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint6
time_t _zip_d2u_time(const zip_dostime_t*);
void _zip_deregister_source(zip_t *za, zip_source_t *src);
void _zip_dirent_apply_attributes(zip_dirent_t *, zip_file_attributes_t *, bool, zip_uint32_t);
bool _zip_dirent_apply_attributes(zip_dirent_t *, zip_file_attributes_t *, bool);
int zip_dirent_check_consistency(zip_dirent_t *dirent);
zip_dirent_t *_zip_dirent_clone(const zip_dirent_t *);
void _zip_dirent_free(zip_dirent_t *);
void _zip_dirent_finalize(zip_dirent_t *);
time_t zip_dirent_get_last_mod_mtime(zip_dirent_t *de);
void _zip_dirent_init(zip_dirent_t *);
bool _zip_dirent_merge(zip_dirent_t *de, zip_dirent_t *de_orig, bool replacing_data, zip_error_t *error);
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);
@ -618,6 +623,8 @@ int _zip_progress_start(zip_progress_t *progress);
int _zip_progress_subrange(zip_progress_t *progress, double start, double end);
int _zip_progress_update(zip_progress_t *progress, double value);
bool zip_realloc(void **memory, zip_uint64_t *alloced_elements, zip_uint64_t element_size, zip_uint64_t additional_elements, zip_error_t *error);
/* this symbol is extern so it can be overridden for regression testing */
ZIP_EXTERN bool zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length);
zip_uint32_t zip_random_uint32(void);

View File

@ -86,6 +86,7 @@
<ClCompile Include="lib\zip_name_locate.c" />
<ClCompile Include="lib\zip_new.c" />
<ClCompile Include="lib\zip_open.c" />
<ClCompile Include="lib\zip_realloc.c" />
<ClCompile Include="lib\zip_pkware.c" />
<ClCompile Include="lib\zip_progress.c" />
<ClCompile Include="lib\zip_random_win32.c" />