VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common/libzip/zip_open.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Common/libzip/zip_open.c')
-rw-r--r--src/Common/libzip/zip_open.c127
1 files changed, 68 insertions, 59 deletions
diff --git a/src/Common/libzip/zip_open.c b/src/Common/libzip/zip_open.c
index d6209ee1..f62f95f6 100644
--- a/src/Common/libzip/zip_open.c
+++ b/src/Common/libzip/zip_open.c
@@ -1,6 +1,6 @@
/*
zip_open.c -- open zip archive by name
- Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -17,7 +17,7 @@
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
@@ -88,17 +88,17 @@ zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error)
{
static zip_int64_t needed_support_read = -1;
static zip_int64_t needed_support_write = -1;
-
+
unsigned int flags;
zip_int64_t supported;
exists_t exists;
-
+
if (_flags < 0 || src == NULL) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
}
flags = (unsigned int)_flags;
-
+
supported = zip_source_supports(src);
if (needed_support_read == -1) {
needed_support_read = zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_STAT, -1);
@@ -118,7 +118,7 @@ zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error)
}
exists = _zip_file_exists(src, error);
- switch (exists) {
+ switch (exists) {
case EXISTS_ERROR:
return NULL;
@@ -157,26 +157,13 @@ zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error)
}
}
-ZIP_EXTERN int
-zip_archive_set_tempdir(zip_t *za, const char *tempdir)
+ZIP_EXTERN void
+zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callback)
{
- char *new_tempdir;
-
- if (tempdir) {
- if ((new_tempdir = strdup(tempdir)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_MEMORY, errno);
- return -1;
- }
- }
- else
- new_tempdir = NULL;
-
- free(za->tempdir);
- za->tempdir = new_tempdir;
-
- return 0;
+ za->progress_callback = progress_callback;
}
+
zip_t *
_zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
{
@@ -209,7 +196,7 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
if ((za=_zip_allocate_new(src, flags, error)) == NULL) {
return NULL;
}
-
+
if ((cdir = _zip_find_central_dir(za, len)) == NULL) {
_zip_error_copy(error, &za->error);
/* keep src so discard does not get rid of it */
@@ -233,7 +220,7 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
zip_discard(za);
return NULL;
}
-
+
if (_zip_hash_add(za->names, name, idx, ZIP_FL_UNCHANGED, &za->error) == false) {
if (za->error.zip_err != ZIP_ER_EXISTS || (flags & ZIP_CHECKCONS)) {
_zip_error_copy(error, &za->error);
@@ -244,7 +231,7 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
}
}
}
-
+
za->ch_flags = za->flags;
return za;
@@ -269,7 +256,7 @@ _zip_set_open_error(int *zep, const zip_error_t *err, int ze)
/* _zip_readcdir:
tries to find a valid end-of-central-directory at the beginning of
buf, and then the corresponding central directory entries.
- Returns a struct zip_cdir which contains the central directory
+ Returns a struct zip_cdir which contains the central directory
entries, or NULL if unsuccessful. */
static zip_cdir_t *
@@ -286,7 +273,7 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
zip_error_set(error, ZIP_ER_NOZIP, 0);
return NULL;
}
-
+
/* check for end-of-central-dir magic */
if (memcmp(_zip_buffer_get(buffer, 4), EOCD_MAGIC, 4) != 0) {
zip_error_set(error, ZIP_ER_NOZIP, 0);
@@ -317,10 +304,10 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
if (comment_len || (za->open_flags & ZIP_CHECKCONS)) {
zip_uint64_t tail_len;
-
+
_zip_buffer_set_offset(buffer, eocd_offset + EOCDLEN);
tail_len = _zip_buffer_left(buffer);
-
+
if (tail_len < comment_len || ((za->open_flags & ZIP_CHECKCONS) && tail_len != comment_len)) {
zip_error_set(error, ZIP_ER_INCONS, 0);
_zip_cdir_free(cd);
@@ -339,7 +326,7 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
zip_uint8_t *data;
/* if buffer already read in, use it */
_zip_buffer_set_offset(buffer, cd->offset - buf_offset);
-
+
if ((data = _zip_buffer_get(buffer, cd->size)) == NULL) {
zip_error_set(error, ZIP_ER_INCONS, 0);
_zip_cdir_free(cd);
@@ -353,7 +340,7 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
}
else {
cd_buffer = NULL;
-
+
if (zip_source_seek(za->src, (zip_int64_t)cd->offset, SEEK_SET) < 0) {
_zip_error_set_from_source(error, za->src);
_zip_cdir_free(cd);
@@ -370,9 +357,30 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
left = (zip_uint64_t)cd->size;
i=0;
- while (i<cd->nentry && left > 0) {
+ while (left > 0) {
+ bool grown = false;
zip_int64_t entry_size;
+
+ if (i == cd->nentry) {
+ /* InfoZIP has a hack to avoid using Zip64: it stores nentries % 0x10000 */
+ /* This hack isn't applicable if we're using Zip64, or if there is no central directory entry following. */
+
+ if (cd->is_zip64 || left < CDENTRYSIZE) {
+ break;
+ }
+
+ if (!_zip_cdir_grow(cd, 0x10000, error)) {
+ _zip_cdir_free(cd);
+ _zip_buffer_free(cd_buffer);
+ return NULL;
+ }
+ grown = true;
+ }
+
if ((cd->entry[i].orig=_zip_dirent_new()) == NULL || (entry_size = _zip_dirent_read(cd->entry[i].orig, za->src, cd_buffer, false, error)) < 0) {
+ if (grown && zip_error_code_zip(error) == ZIP_ER_NOZIP) {
+ zip_error_set(error, ZIP_ER_INCONS, 0);
+ }
_zip_cdir_free(cd);
_zip_buffer_free(cd_buffer);
return NULL;
@@ -380,23 +388,23 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
i++;
left -= (zip_uint64_t)entry_size;
}
-
- if (i != cd->nentry) {
+
+ if (i != cd->nentry || left > 0) {
zip_error_set(error, ZIP_ER_INCONS, 0);
_zip_buffer_free(cd_buffer);
_zip_cdir_free(cd);
return NULL;
}
-
+
if (za->open_flags & ZIP_CHECKCONS) {
bool ok;
-
+
if (cd_buffer) {
ok = _zip_buffer_eof(cd_buffer);
}
else {
zip_int64_t offset = zip_source_tell(za->src);
-
+
if (offset < 0) {
_zip_error_set_from_source(error, za->src);
_zip_buffer_free(cd_buffer);
@@ -405,7 +413,7 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
}
ok = ((zip_uint64_t)offset == cd->offset + cd->size);
}
-
+
if (!ok) {
zip_error_set(error, ZIP_ER_INCONS, 0);
_zip_buffer_free(cd_buffer);
@@ -447,7 +455,7 @@ _zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error)
zip_error_set(error, ZIP_ER_NOZIP, 0);
return -1;
}
-
+
j = cd->entry[i].orig->offset + cd->entry[i].orig->comp_size
+ _zip_string_length(cd->entry[i].orig->filename) + LENTRYSIZE;
if (j > max)
@@ -456,27 +464,27 @@ _zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error)
zip_error_set(error, ZIP_ER_NOZIP, 0);
return -1;
}
-
+
if (zip_source_seek(za->src, (zip_int64_t)cd->entry[i].orig->offset, SEEK_SET) < 0) {
_zip_error_set_from_source(error, za->src);
return -1;
}
-
+
if (_zip_dirent_read(&temp, za->src, NULL, true, error) == -1) {
_zip_dirent_finalize(&temp);
return -1;
}
-
+
if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) {
zip_error_set(error, ZIP_ER_INCONS, 0);
_zip_dirent_finalize(&temp);
return -1;
}
-
+
cd->entry[i].orig->extra_fields = _zip_ef_merge(cd->entry[i].orig->extra_fields, temp.extra_fields);
cd->entry[i].orig->local_extra_fields_read = 1;
temp.extra_fields = NULL;
-
+
_zip_dirent_finalize(&temp);
}
@@ -491,7 +499,7 @@ _zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error)
static int
_zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *local)
{
- if ((central->version_needed != local->version_needed)
+ if ((central->version_needed < local->version_needed)
#if 0
/* some zip-files have different values in local
and global headers for the bitflags */
@@ -586,7 +594,7 @@ _zip_find_central_dir(zip_t *za, zip_uint64_t len)
_zip_error_set_from_source(&za->error, za->src);
return NULL;
}
-
+
if ((buffer = _zip_buffer_new_from_source(za->src, buflen, NULL, &za->error)) == NULL) {
return NULL;
}
@@ -607,7 +615,7 @@ _zip_find_central_dir(zip_t *za, zip_uint64_t len)
if (best <= 0) {
best = _zip_checkcons(za, cdir, &error);
}
-
+
a = _zip_checkcons(za, cdirnew, &error);
if (best < a) {
_zip_cdir_free(cdir);
@@ -628,13 +636,13 @@ _zip_find_central_dir(zip_t *za, zip_uint64_t len)
}
cdirnew = NULL;
}
-
+
match++;
_zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer)));
}
_zip_buffer_free(buffer);
-
+
if (best < 0) {
_zip_error_copy(&za->error, &error);
_zip_cdir_free(cdir);
@@ -649,7 +657,7 @@ static 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;
@@ -673,7 +681,7 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags
zip_error_set(error, ZIP_ER_INCONS, 0);
return NULL;
}
-
+
eocd_offset = _zip_buffer_offset(buffer);
_zip_buffer_get(buffer, 4); /* magic already verified */
@@ -700,7 +708,7 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
return NULL;
}
-
+
if (offset+size > buf_offset + eocd_offset) {
/* cdir spans past EOCD record */
zip_error_set(error, ZIP_ER_INCONS, 0);
@@ -715,9 +723,10 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags
if ((cd=_zip_cdir_new(nentry, error)) == NULL)
return NULL;
+ cd->is_zip64 = false;
cd->size = size;
cd->offset = offset;
-
+
return cd;
}
@@ -734,13 +743,13 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
zip_uint32_t num_disks, num_disks64, eocd_disk, eocd_disk64;
eocdloc_offset = _zip_buffer_offset(buffer);
-
+
_zip_buffer_get(buffer, 4); /* magic already verified */
num_disks = _zip_buffer_get_16(buffer);
eocd_disk = _zip_buffer_get_16(buffer);
eocd_offset = _zip_buffer_get_64(buffer);
-
+
if (eocd_offset > ZIP_INT64_MAX || eocd_offset + EOCD64LEN < eocd_offset) {
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
return NULL;
@@ -773,7 +782,7 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
}
return NULL;
}
-
+
size = _zip_buffer_get_64(buffer);
if ((flags & ZIP_CHECKCONS) && size + eocd_offset + 12 != buf_offset + eocdloc_offset) {
@@ -820,7 +829,7 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
size = _zip_buffer_get_64(buffer);
offset = _zip_buffer_get_64(buffer);
-
+
if (!_zip_buffer_ok(buffer)) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
if (free_buffer) {
@@ -845,7 +854,7 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
if ((cd=_zip_cdir_new(nentry, error)) == NULL)
return NULL;
-
+ cd->is_zip64 = true;
cd->size = size;
cd->offset = offset;