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