Blame SOURCES/unzip-zipbomb-part4.patch

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