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