Blame SOURCES/unzip-zipbomb-part6.patch

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