[packages/unzip] more fixes from fedora; rel 6

atler atler at pld-linux.org
Sat May 21 21:02:20 CEST 2022


commit 419004324676b3f8dffec0154370cb7c167545e7
Author: Jan Palus <atler at pld-linux.org>
Date:   Sat May 21 20:59:38 2022 +0200

    more fixes from fedora; rel 6

 unzip-zipbomb-manpage.patch |   2 +-
 unzip-zipbomb-part4.patch   |  25 ++++++
 unzip-zipbomb-part5.patch   |  26 ++++++
 unzip-zipbomb-part6.patch   |  95 ++++++++++++++++++++
 unzip-zipbomb-switch.patch  | 215 ++++++++++++++++++++++++++++++++++++++++++++
 unzip.spec                  |  10 ++-
 6 files changed, 371 insertions(+), 2 deletions(-)
---
diff --git a/unzip.spec b/unzip.spec
index e12f409..07a85f3 100644
--- a/unzip.spec
+++ b/unzip.spec
@@ -13,7 +13,7 @@ Summary(tr.UTF-8):	pkzip ve benzeri programların ürettiği zip arşivlerini a
 Summary(uk.UTF-8):	Розпаковувач файлів .zip
 Name:		unzip
 Version:	6.00
-Release:	5
+Release:	6
 License:	distributable
 Group:		Applications/Archiving
 Source0:	ftp://ftp.info-zip.org/pub/infozip/src/%{name}60.tgz
@@ -79,6 +79,10 @@ Patch26: unzip-zipbomb-part1.patch
 Patch27: unzip-zipbomb-part2.patch
 Patch28: unzip-zipbomb-part3.patch
 Patch29: unzip-zipbomb-manpage.patch
+Patch30: unzip-zipbomb-part4.patch
+Patch31: unzip-zipbomb-part5.patch
+Patch32: unzip-zipbomb-part6.patch
+Patch33: unzip-zipbomb-switch.patch
 URL:		http://www.info-zip.org/
 BuildRoot:	%{tmpdir}/%{name}-%{version}-root-%(id -u -n)
 
@@ -183,6 +187,10 @@ PKZIP та PKUNZIP від PKWARE для MS-DOS, але в багатьох ви
 %patch27 -p1
 %patch28 -p1
 %patch29 -p1
+%patch30 -p1
+%patch31 -p1
+%patch32 -p1
+%patch33 -p1
 
 %build
 # IZ_HAVE_UXUIDGID is needed for right functionality of unzip -X
diff --git a/unzip-zipbomb-manpage.patch b/unzip-zipbomb-manpage.patch
index cdeeea5..bcee827 100644
--- a/unzip-zipbomb-manpage.patch
+++ b/unzip-zipbomb-manpage.patch
@@ -16,7 +16,7 @@ index 21816d1..4d66073 100644
  .IP 11
  no matching files were found.
 +.IP 12
-+invalid zip file with overlapped components (possible zip bomb).
++invalid zip file with overlapped components (possible zip-bomb). The zip-bomb checks can be disabled by using the UNZIP_DISABLE_ZIPBOMB_DETECTION=TRUE environment variable.
  .IP 50
  the disk is (or was) full during extraction.
  .IP 51
diff --git a/unzip-zipbomb-part4.patch b/unzip-zipbomb-part4.patch
new file mode 100644
index 0000000..beffa2c
--- /dev/null
+++ b/unzip-zipbomb-part4.patch
@@ -0,0 +1,25 @@
+From 5e2efcd633a4a1fb95a129a75508e7d769e767be Mon Sep 17 00:00:00 2001
+From: Mark Adler <madler at alumni.caltech.edu>
+Date: Sun, 9 Feb 2020 20:36:28 -0800
+Subject: [PATCH] Fix bug in UZbunzip2() that incorrectly updated G.incnt.
+
+The update assumed a full buffer, which is not always full. This
+could result in a false overlapped element detection when a small
+bzip2-compressed file was unzipped. This commit remedies that.
+---
+ extract.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/extract.c b/extract.c
+index d9866f9..0cb7bfc 100644
+--- a/extract.c
++++ b/extract.c
+@@ -3010,7 +3010,7 @@ __GDEF
+ #endif
+ 
+     G.inptr = (uch *)bstrm.next_in;
+-    G.incnt = (G.inbuf + INBUFSIZ) - G.inptr;  /* reset for other routines */
++    G.incnt -= G.inptr - G.inbuf;       /* reset for other routines */
+ 
+ uzbunzip_cleanup_exit:
+     err = BZ2_bzDecompressEnd(&bstrm);
diff --git a/unzip-zipbomb-part5.patch b/unzip-zipbomb-part5.patch
new file mode 100644
index 0000000..ca6a43a
--- /dev/null
+++ b/unzip-zipbomb-part5.patch
@@ -0,0 +1,26 @@
+From 5c572555cf5d80309a07c30cf7a54b2501493720 Mon Sep 17 00:00:00 2001
+From: Mark Adler <madler at alumni.caltech.edu>
+Date: Sun, 9 Feb 2020 21:39:09 -0800
+Subject: [PATCH] Fix bug in UZinflate() that incorrectly updated G.incnt.
+
+The update assumed a full buffer, which is not always full. This
+could result in a false overlapped element detection when a small
+deflate-compressed file was unzipped using an old zlib. This
+commit remedies that.
+---
+ inflate.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/inflate.c b/inflate.c
+index 2f5a015..70e3cc0 100644
+--- a/inflate.c
++++ b/inflate.c
+@@ -700,7 +700,7 @@ int UZinflate(__G__ is_defl64)
+       G.dstrm.total_out));
+ 
+     G.inptr = (uch *)G.dstrm.next_in;
+-    G.incnt = (G.inbuf + INBUFSIZ) - G.inptr;  /* reset for other routines */
++    G.incnt -= G.inptr - G.inbuf;       /* reset for other routines */
+ 
+ uzinflate_cleanup_exit:
+     err = inflateReset(&G.dstrm);
diff --git a/unzip-zipbomb-part6.patch b/unzip-zipbomb-part6.patch
new file mode 100644
index 0000000..3dce6e3
--- /dev/null
+++ b/unzip-zipbomb-part6.patch
@@ -0,0 +1,95 @@
+From 122050bac16fae82a460ff739fb1ca0f106e9d85 Mon Sep 17 00:00:00 2001
+From: Mark Adler <madler at alumni.caltech.edu>
+Date: Sat, 2 Jan 2021 13:09:34 -0800
+Subject: [PATCH] Determine Zip64 status entry-by-entry instead of for entire
+ file.
+
+Fixes a bug for zip files with mixed Zip64 and not Zip64 entries,
+which resulted in an incorrect data descriptor length. The bug is
+seen when a Zip64 entry precedes a non-Zip64 entry, in which case
+the data descriptor would have been assumed to be larger than it
+is, resulting in an incorrect bomb warning due to a perceived
+overlap with the next entry. This commit determines and saves the
+Zip64 status for each entry based on the central directory, and
+then computes the length of each data descriptor accordingly.
+---
+ extract.c | 5 +++--
+ globals.h | 2 --
+ process.c | 4 +---
+ unzpriv.h | 1 +
+ 4 files changed, 5 insertions(+), 7 deletions(-)
+
+diff --git a/extract.c b/extract.c
+index 504afd6..878817d 100644
+--- a/extract.c
++++ b/extract.c
+@@ -658,6 +658,7 @@ int extract_or_test_files(__G)    /* return PK-type error code */
+                     break;
+                 }
+             }
++            G.pInfo->zip64 = FALSE;
+             if ((error = do_string(__G__ G.crec.extra_field_length,
+                 EXTRA_FIELD)) != 0)
+             {
+@@ -2187,12 +2188,12 @@ static int extract_or_test_member(__G)    /* return PK-type error code */
+              (clen == SIG &&                    /* if not SIG, no signature */
+               ((G.lrec.csize & LOW) != SIG ||   /* if not SIG, have signature */
+                (ulen == SIG &&                  /* if not SIG, no signature */
+-                (G.zip64 ? G.lrec.csize >> 32 : G.lrec.ucsize) != SIG
++                (G.pInfo->zip64 ? G.lrec.csize >> 32 : G.lrec.ucsize) != SIG
+                                                 /* if not SIG, have signature */
+                 )))))
+                    /* skip four more bytes to account for signature */
+                    shy += 4 - readbuf((char *)buf, 4);
+-        if (G.zip64)
++        if (G.pInfo->zip64)
+             shy += 8 - readbuf((char *)buf, 8); /* skip eight more for ZIP64 */
+         if (shy)
+             error = PK_ERR;
+diff --git a/globals.h b/globals.h
+index f9c6daf..a883c90 100644
+--- a/globals.h
++++ b/globals.h
+@@ -261,8 +261,6 @@ typedef struct Globals {
+     ecdir_rec       ecrec;         /* used in unzip.c, extract.c */
+     z_stat   statbuf;              /* used by main, mapname, check_for_newer */
+ 
+-    int zip64;                     /* true if Zip64 info in extra field */
+-
+     int      mem_mode;
+     uch      *outbufptr;           /* extract.c static */
+     ulg      outsize;              /* extract.c static */
+diff --git a/process.c b/process.c
+index d75d405..d643c6f 100644
+--- a/process.c
++++ b/process.c
+@@ -1903,8 +1903,6 @@ int getZip64Data(__G__ ef_buf, ef_len)
+ #define Z64FLGS 0xffff
+ #define Z64FLGL 0xffffffff
+ 
+-    G.zip64 = FALSE;
+-
+     if (ef_len == 0 || ef_buf == NULL)
+         return PK_COOL;
+ 
+@@ -1943,7 +1941,7 @@ int getZip64Data(__G__ ef_buf, ef_len)
+           break;                /* Expect only one EF_PKSZ64 block. */
+ #endif /* 0 */
+ 
+-          G.zip64 = TRUE;
++          G.pInfo->zip64 = TRUE;
+         }
+ 
+         /* Skip this extra field block. */
+diff --git a/unzpriv.h b/unzpriv.h
+index 09f288e..75b3359 100644
+--- a/unzpriv.h
++++ b/unzpriv.h
+@@ -2034,6 +2034,7 @@ typedef struct min_info {
+ #ifdef UNICODE_SUPPORT
+     unsigned GPFIsUTF8: 1;   /* crec gen_purpose_flag UTF-8 bit 11 is set */
+ #endif
++    unsigned zip64: 1;       /* true if entry has Zip64 extra block */
+ #ifndef SFX
+     char Far *cfilname;      /* central header version of filename */
+ #endif
diff --git a/unzip-zipbomb-switch.patch b/unzip-zipbomb-switch.patch
new file mode 100644
index 0000000..c6d33c0
--- /dev/null
+++ b/unzip-zipbomb-switch.patch
@@ -0,0 +1,215 @@
+From 5b44c818b96193b3e240f38f61985fa2bc780eb7 Mon Sep 17 00:00:00 2001
+From: Jakub Martisko <jamartis at redhat.com>
+Date: Tue, 30 Nov 2021 15:42:17 +0100
+Subject: [PATCH] Add an option to disable the zipbomb detection
+
+This can be done by settting a newly introduced environment variable
+UNZIP_DISABLE_ZIPBOMB_DETECTION to {TRUE,True,true}. If the variable is unset, or
+set to any other value the zipbomb detection is left enabled.
+
+Example:
+	UNZIP_DISABLE_ZIPBOMB_DETECTION=True unzip ./zbsm.zip -d ./test
+---
+ extract.c | 85 ++++++++++++++++++++++++++++++-------------------------
+ unzip.c   | 15 ++++++++--
+ unzip.h   |  1 +
+ 3 files changed, 60 insertions(+), 41 deletions(-)
+
+diff --git a/extract.c b/extract.c
+index 878817d..3e58071 100644
+--- a/extract.c
++++ b/extract.c
+@@ -322,7 +322,8 @@ static ZCONST char Far BadExtraFieldCRC[] =
+ static ZCONST char Far NotEnoughMemCover[] =
+   "error: not enough memory for bomb detection\n";
+ static ZCONST char Far OverlappedComponents[] =
+-  "error: invalid zip file with overlapped components (possible zip bomb)\n";
++  "error: invalid zip file with overlapped components (possible zip bomb)\n \
++To unzip the file anyway, rerun the command with UNZIP_DISABLE_ZIPBOMB_DETECTION=TRUE environmnent variable\n";
+ 
+ 
+ 
+@@ -502,35 +503,37 @@ int extract_or_test_files(__G)    /* return PK-type error code */
+        the end of central directory record (including the Zip64 end of central
+        directory locator, if present), and the Zip64 end of central directory
+        record, if present. */
+-    if (G.cover == NULL) {
++    if (uO.zipbomb == TRUE) {
++      if (G.cover == NULL) {
+         G.cover = malloc(sizeof(cover_t));
+         if (G.cover == NULL) {
+-            Info(slide, 0x401, ((char *)slide,
+-              LoadFarString(NotEnoughMemCover)));
+-            return PK_MEM;
++            Info(slide, 0x401, ((char *)slide,
++              LoadFarString(NotEnoughMemCover)));
++            return PK_MEM;
+         }
+         ((cover_t *)G.cover)->span = NULL;
+         ((cover_t *)G.cover)->max = 0;
+-    }
+-    ((cover_t *)G.cover)->num = 0;
+-    if (cover_add((cover_t *)G.cover,
+-                  G.extra_bytes + G.ecrec.offset_start_central_directory,
+-                  G.extra_bytes + G.ecrec.offset_start_central_directory +
+-                  G.ecrec.size_central_directory) != 0) {
++    }
++    ((cover_t *)G.cover)->num = 0;
++    if (cover_add((cover_t *)G.cover,
++                  G.extra_bytes + G.ecrec.offset_start_central_directory,
++                  G.extra_bytes + G.ecrec.offset_start_central_directory +
++                  G.ecrec.size_central_directory) != 0) {
+         Info(slide, 0x401, ((char *)slide,
+-          LoadFarString(NotEnoughMemCover)));
++          LoadFarString(NotEnoughMemCover)));
+         return PK_MEM;
+-    }
+-    if ((G.extra_bytes != 0 &&
+-         cover_add((cover_t *)G.cover, 0, G.extra_bytes) != 0) ||
+-        (G.ecrec.have_ecr64 &&
+-         cover_add((cover_t *)G.cover, G.ecrec.ec64_start,
+-                   G.ecrec.ec64_end) != 0) ||
+-        cover_add((cover_t *)G.cover, G.ecrec.ec_start,
+-                  G.ecrec.ec_end) != 0) {
++    }
++    if ((G.extra_bytes != 0 &&
++         cover_add((cover_t *)G.cover, 0, G.extra_bytes) != 0) ||
++        (G.ecrec.have_ecr64 &&
++         cover_add((cover_t *)G.cover, G.ecrec.ec64_start,
++                   G.ecrec.ec64_end) != 0) ||
++        cover_add((cover_t *)G.cover, G.ecrec.ec_start,
++                  G.ecrec.ec_end) != 0) {
+         Info(slide, 0x401, ((char *)slide,
+-          LoadFarString(OverlappedComponents)));
++          LoadFarString(OverlappedComponents)));
+         return PK_BOMB;
++      }
+     }
+ 
+ /*---------------------------------------------------------------------------
+@@ -1222,10 +1225,12 @@ static int extract_or_test_entrylist(__G__ numchunk,
+ 
+         /* seek_zipf(__G__ pInfo->offset);  */
+         request = G.pInfo->offset + G.extra_bytes;
+-        if (cover_within((cover_t *)G.cover, request)) {
++        if (uO.zipbomb == TRUE) {
++          if (cover_within((cover_t *)G.cover, request)) {
+             Info(slide, 0x401, ((char *)slide,
+-              LoadFarString(OverlappedComponents)));
++              LoadFarString(OverlappedComponents)));
+             return PK_BOMB;
++          }
+         }
+         inbuf_offset = request % INBUFSIZ;
+         bufstart = request - inbuf_offset;
+@@ -1758,17 +1763,19 @@ reprompt:
+             return IZ_CTRLC;        /* cancel operation by user request */
+         }
+ #endif
+-        error = cover_add((cover_t *)G.cover, request,
+-                          G.cur_zipfile_bufstart + (G.inptr - G.inbuf));
+-        if (error < 0) {
++        if (uO.zipbomb == TRUE) {
++          error = cover_add((cover_t *)G.cover, request,
++                            G.cur_zipfile_bufstart + (G.inptr - G.inbuf));
++          if (error < 0) {
+             Info(slide, 0x401, ((char *)slide,
+-              LoadFarString(NotEnoughMemCover)));
++                                LoadFarString(NotEnoughMemCover)));
+             return PK_MEM;
+-        }
+-        if (error != 0) {
++          }
++          if (error != 0) {
+             Info(slide, 0x401, ((char *)slide,
+-              LoadFarString(OverlappedComponents)));
++                                LoadFarString(OverlappedComponents)));
+             return PK_BOMB;
++          }
+         }
+ #ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */
+         UserStop();
+@@ -2171,8 +2178,8 @@ static int extract_or_test_member(__G)    /* return PK-type error code */
+     }
+ 
+     undefer_input(__G);
+-
+-    if ((G.lrec.general_purpose_bit_flag & 8) != 0) {
++    if (uO.zipbomb == TRUE) {
++      if ((G.lrec.general_purpose_bit_flag & 8) != 0) {
+         /* skip over data descriptor (harder than it sounds, due to signature
+          * ambiguity)
+          */
+@@ -2189,16 +2196,16 @@ static int extract_or_test_member(__G)    /* return PK-type error code */
+               ((G.lrec.csize & LOW) != SIG ||   /* if not SIG, have signature */
+                (ulen == SIG &&                  /* if not SIG, no signature */
+                 (G.pInfo->zip64 ? G.lrec.csize >> 32 : G.lrec.ucsize) != SIG
+-                                                /* if not SIG, have signature */
++                /* if not SIG, have signature */
+                 )))))
+-                   /* skip four more bytes to account for signature */
+-                   shy += 4 - readbuf((char *)buf, 4);
++          /* skip four more bytes to account for signature */
++          shy += 4 - readbuf((char *)buf, 4);
+         if (G.pInfo->zip64)
+-            shy += 8 - readbuf((char *)buf, 8); /* skip eight more for ZIP64 */
++          shy += 8 - readbuf((char *)buf, 8); /* skip eight more for ZIP64 */
+         if (shy)
+-            error = PK_ERR;
++          error = PK_ERR;
++      }
+     }
+-
+     return error;
+ 
+ } /* end function extract_or_test_member() */
+diff --git a/unzip.c b/unzip.c
+index 8dbfc95..abb3644 100644
+--- a/unzip.c
++++ b/unzip.c
+@@ -1329,10 +1329,9 @@ int uz_opts(__G__ pargc, pargv)
+     int *pargc;
+     char ***pargv;
+ {
+-    char **argv, *s;
++    char **argv, *s, *zipbomb_envar;
+     int argc, c, error=FALSE, negative=0, showhelp=0;
+ 
+-
+     argc = *pargc;
+     argv = *pargv;
+ 
+@@ -1923,6 +1922,18 @@ opts_done:  /* yes, very ugly...but only used by UnZipSFX with -x xlist */
+     else
+         G.extract_flag = TRUE;
+ 
++    /* Disable the zipbomb detection, this is the only option set only via the shell variables but it should at least not clash with something in the future. */
++    zipbomb_envar = getenv("UNZIP_DISABLE_ZIPBOMB_DETECTION");
++    uO.zipbomb = TRUE;
++    if (zipbomb_envar != NULL) {
++      /* strcasecmp might be a better approach here but it is POSIX-only */
++      if ((strcmp ("TRUE", zipbomb_envar) == 0)
++       || (strcmp ("True", zipbomb_envar) == 0)
++       || (strcmp ("true",zipbomb_envar) == 0)) {
++        uO.zipbomb = FALSE;
++      }
++    }
++
+     *pargc = argc;
+     *pargv = argv;
+     return PK_OK;
+diff --git a/unzip.h b/unzip.h
+index ed24a5b..e7665e8 100644
+--- a/unzip.h
++++ b/unzip.h
+@@ -559,6 +559,7 @@ typedef struct _UzpOpts {
+ #ifdef UNIX
+     int cflxflag;       /* -^: allow control chars in extracted filenames */
+ #endif
++  int zipbomb;
+ #endif /* !FUNZIP */
+ } UzpOpts;
+ 
+-- 
+2.33.0
+
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/unzip.git/commitdiff/f31014087fd7576b4ccef3b2d4cb1652b2255e23



More information about the pld-cvs-commit mailing list