Blame SOURCES/unzip-zipbomb-part6.patch

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