a2a4f62
From 122050bac16fae82a460ff739fb1ca0f106e9d85 Mon Sep 17 00:00:00 2001
a2a4f62
From: Mark Adler <madler@alumni.caltech.edu>
a2a4f62
Date: Sat, 2 Jan 2021 13:09:34 -0800
a2a4f62
Subject: [PATCH] Determine Zip64 status entry-by-entry instead of for entire
a2a4f62
 file.
a2a4f62
a2a4f62
Fixes a bug for zip files with mixed Zip64 and not Zip64 entries,
a2a4f62
which resulted in an incorrect data descriptor length. The bug is
a2a4f62
seen when a Zip64 entry precedes a non-Zip64 entry, in which case
a2a4f62
the data descriptor would have been assumed to be larger than it
a2a4f62
is, resulting in an incorrect bomb warning due to a perceived
a2a4f62
overlap with the next entry. This commit determines and saves the
a2a4f62
Zip64 status for each entry based on the central directory, and
a2a4f62
then computes the length of each data descriptor accordingly.
a2a4f62
---
a2a4f62
 extract.c | 5 +++--
a2a4f62
 globals.h | 2 --
a2a4f62
 process.c | 4 +---
a2a4f62
 unzpriv.h | 1 +
a2a4f62
 4 files changed, 5 insertions(+), 7 deletions(-)
a2a4f62
a2a4f62
diff --git a/extract.c b/extract.c
a2a4f62
index 504afd6..878817d 100644
a2a4f62
--- a/extract.c
a2a4f62
+++ b/extract.c
a2a4f62
@@ -658,6 +658,7 @@ int extract_or_test_files(__G)    /* return PK-type error code */
a2a4f62
                     break;
a2a4f62
                 }
a2a4f62
             }
a2a4f62
+            G.pInfo->zip64 = FALSE;
a2a4f62
             if ((error = do_string(__G__ G.crec.extra_field_length,
a2a4f62
                 EXTRA_FIELD)) != 0)
a2a4f62
             {
a2a4f62
@@ -2187,12 +2188,12 @@ static int extract_or_test_member(__G)    /* return PK-type error code */
a2a4f62
              (clen == SIG &&                    /* if not SIG, no signature */
a2a4f62
               ((G.lrec.csize & LOW) != SIG ||   /* if not SIG, have signature */
a2a4f62
                (ulen == SIG &&                  /* if not SIG, no signature */
a2a4f62
-                (G.zip64 ? G.lrec.csize >> 32 : G.lrec.ucsize) != SIG
a2a4f62
+                (G.pInfo->zip64 ? G.lrec.csize >> 32 : G.lrec.ucsize) != SIG
a2a4f62
                                                 /* if not SIG, have signature */
a2a4f62
                 )))))
a2a4f62
                    /* skip four more bytes to account for signature */
a2a4f62
                    shy += 4 - readbuf((char *)buf, 4);
a2a4f62
-        if (G.zip64)
a2a4f62
+        if (G.pInfo->zip64)
a2a4f62
             shy += 8 - readbuf((char *)buf, 8); /* skip eight more for ZIP64 */
a2a4f62
         if (shy)
a2a4f62
             error = PK_ERR;
a2a4f62
diff --git a/globals.h b/globals.h
a2a4f62
index f9c6daf..a883c90 100644
a2a4f62
--- a/globals.h
a2a4f62
+++ b/globals.h
a2a4f62
@@ -261,8 +261,6 @@ typedef struct Globals {
a2a4f62
     ecdir_rec       ecrec;         /* used in unzip.c, extract.c */
a2a4f62
     z_stat   statbuf;              /* used by main, mapname, check_for_newer */
a2a4f62
 
a2a4f62
-    int zip64;                     /* true if Zip64 info in extra field */
a2a4f62
-
a2a4f62
     int      mem_mode;
a2a4f62
     uch      *outbufptr;           /* extract.c static */
a2a4f62
     ulg      outsize;              /* extract.c static */
a2a4f62
diff --git a/process.c b/process.c
a2a4f62
index d75d405..d643c6f 100644
a2a4f62
--- a/process.c
a2a4f62
+++ b/process.c
a2a4f62
@@ -1903,8 +1903,6 @@ int getZip64Data(__G__ ef_buf, ef_len)
a2a4f62
 #define Z64FLGS 0xffff
a2a4f62
 #define Z64FLGL 0xffffffff
a2a4f62
 
a2a4f62
-    G.zip64 = FALSE;
a2a4f62
-
a2a4f62
     if (ef_len == 0 || ef_buf == NULL)
a2a4f62
         return PK_COOL;
a2a4f62
 
a2a4f62
@@ -1943,7 +1941,7 @@ int getZip64Data(__G__ ef_buf, ef_len)
a2a4f62
           break;                /* Expect only one EF_PKSZ64 block. */
a2a4f62
 #endif /* 0 */
a2a4f62
 
a2a4f62
-          G.zip64 = TRUE;
a2a4f62
+          G.pInfo->zip64 = TRUE;
a2a4f62
         }
a2a4f62
 
a2a4f62
         /* Skip this extra field block. */
a2a4f62
diff --git a/unzpriv.h b/unzpriv.h
a2a4f62
index 09f288e..75b3359 100644
a2a4f62
--- a/unzpriv.h
a2a4f62
+++ b/unzpriv.h
a2a4f62
@@ -2034,6 +2034,7 @@ typedef struct min_info {
a2a4f62
 #ifdef UNICODE_SUPPORT
a2a4f62
     unsigned GPFIsUTF8: 1;   /* crec gen_purpose_flag UTF-8 bit 11 is set */
a2a4f62
 #endif
a2a4f62
+    unsigned zip64: 1;       /* true if entry has Zip64 extra block */
a2a4f62
 #ifndef SFX
a2a4f62
     char Far *cfilname;      /* central header version of filename */
a2a4f62
 #endif