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