List Archive

Thread

Thread Index

Message

From: "Jay Freeman (saurik)" <saurik%saurik.com@localhost>
To: libzip-discuss%nih.at@localhost
Subject: [PATCH 3/3] Support zip files with >0xffff entries.
Date: Tue, 16 Aug 2016 01:54:32 -0700

---
 lib/zip_dirent.c             |  6 ++----
 lib/zip_open.c               | 27 +++++++++++++++++++++------
 regress/open_file_count.test |  4 ++--
 3 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/lib/zip_dirent.c b/lib/zip_dirent.c
index 87a34c2..9da573a 100644
--- a/lib/zip_dirent.c
+++ b/lib/zip_dirent.c
@@ -81,10 +81,8 @@ _zip_cdir_new(zip_uint64_t nentry, zip_error_t *error)
        return NULL;
     }
 
-    for (i=0; i<nentry; i++)
-       _zip_entry_init(cd->entries.entry+i);
-
-    cd->entries.nentry = cd->entries.nentry_alloc = nentry;
+    cd->entries.nentry = 0;
+    cd->entries.nentry_alloc = nentry;
     cd->size = cd->offset = 0;
     cd->comment = NULL;
 
diff --git a/lib/zip_open.c b/lib/zip_open.c
index 62ba35a..ffb0088 100644
--- a/lib/zip_open.c
+++ b/lib/zip_open.c
@@ -277,7 +277,8 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, 
zip_uint64_t buf_offset, zip_err
 {
     zip_cdir_t *cd;
     zip_uint16_t comment_len;
-    zip_uint64_t i, left;
+    zip_uint64_t mask, correct, left;
+    zip_int64_t i;
     zip_uint64_t eocd_offset = _zip_buffer_offset(buffer);
     zip_buffer_t *cd_buffer;
 
@@ -296,10 +297,12 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, 
zip_uint64_t buf_offset, zip_err
     if (eocd_offset >= EOCD64LOCLEN && memcmp(_zip_buffer_data(buffer) + 
eocd_offset - EOCD64LOCLEN, EOCD64LOC_MAGIC, 4) == 0) {
         _zip_buffer_set_offset(buffer, eocd_offset - EOCD64LOCLEN);
         cd = _zip_read_eocd64(za->src, buffer, buf_offset, za->flags, error);
+        mask = ~(zip_uint64_t)0;
     }
     else {
         _zip_buffer_set_offset(buffer, eocd_offset);
         cd = _zip_read_eocd(buffer, buf_offset, za->flags, error);
+        mask = (zip_uint64_t)0xffff;
     }
 
     if (cd == NULL)
@@ -368,20 +371,32 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, 
zip_uint64_t buf_offset, zip_err
        }
     }
 
+    correct = cd->entries.nentry_alloc;
     left = (zip_uint64_t)cd->size;
-    i=0;
-    while (i<cd->entries.nentry && left > 0) {
+    while (left > 0) {
         zip_int64_t entry_size;
-       if ((cd->entries.entry[i].orig=_zip_dirent_new()) == NULL || 
(entry_size = _zip_dirent_read(cd->entries.entry[i].orig, za->src, cd_buffer, 
false, error)) < 0) {
+       if ((i=_zip_add_entry(&cd->entries, error)) < 0 || 
(cd->entries.entry[i].orig=_zip_dirent_new()) == NULL) {
            _zip_cdir_free(cd);
             _zip_buffer_free(cd_buffer);
            return NULL;
        }
-       i++;
+
+        if ((entry_size = _zip_dirent_read(cd->entries.entry[i].orig, za->src, 
cd_buffer, false, error)) < 0) {
+            if (zip_error_code_zip(error) != ZIP_ER_NOZIP || (i & mask) != 
correct) {
+                _zip_cdir_free(cd);
+                _zip_buffer_free(cd_buffer);
+                return NULL;
+            }
+
+            _zip_entry_finalize(&cd->entries.entry[i]);
+            cd->entries.nentry--;
+            break;
+       }
+
         left -= (zip_uint64_t)entry_size;
     }
     
-    if (i != cd->entries.nentry) {
+    if ((cd->entries.nentry & mask) != correct) {
         zip_error_set(error, ZIP_ER_INCONS, 0);
         _zip_buffer_free(cd_buffer);
         _zip_cdir_free(cd);
diff --git a/regress/open_file_count.test b/regress/open_file_count.test
index ef7f01c..56f0447 100644
--- a/regress/open_file_count.test
+++ b/regress/open_file_count.test
@@ -7,6 +7,6 @@ file incons-file-count-overflow.zzip 
incons-file-count-overflow.zip incons-file-
 args incons-file-count-high.zzip incons-file-count-low.zzip 
incons-file-count-overflow.zzip
 return 1
 stdout opening 'incons-file-count-high.zzip' returned error 21
-stdout opening 'incons-file-count-low.zzip' succeeded, 2 entries
+stdout opening 'incons-file-count-low.zzip' returned error 21
 stdout opening 'incons-file-count-overflow.zzip' returned error 14
-stderr 2 errors
+stderr 3 errors
-- 
2.6.3

Made by MHonArc.