unzip: sync patches from Fedora etc.

Sync a number of (CVE-related) patches from other distros:

unzip-zipbomb-part{4,5,6}.patch: Fedora
CVE-2021-4217.patch: Archlinux
CVE-2022-0529.patch,CVE-2022-0530.patch: Ubuntu
This commit is contained in:
Albert Schwarzkopf 2022-12-24 15:23:28 +01:00 committed by Leah Neukirchen
parent e839b7bfb6
commit 08746e0218
9 changed files with 288 additions and 1 deletions

View File

@ -0,0 +1,19 @@
diff --git a/process.c b/process.c
index d2a846e..cba2463 100644
--- a/process.c
+++ b/process.c
@@ -2064,10 +2064,14 @@ int getUnicodeData(__G__ ef_buf, ef_len)
G.unipath_checksum = makelong(offset + ef_buf);
offset += 4;
+ if (!G.filename_full) {
+ /* Check if we have a unicode extra section but no filename set */
+ return PK_ERR;
+ }
+
/*
* Compute 32-bit crc
*/
-
chksum = crc32(chksum, (uch *)(G.filename_full),
strlen(G.filename_full));

View File

@ -0,0 +1,37 @@
From: Enrico Zini <enrico@debian.org>
Subject: Fix wide string conversion
Bug-Debian: https://bugs.debian.org/1010355
X-Debian-version: 6.0-27
--- unzip-6.0.orig/process.c
+++ unzip-6.0/process.c
@@ -2511,13 +2511,15 @@ char *wide_to_local_string(wide_string,
char buf[9];
char *buffer = NULL;
char *local_string = NULL;
+ size_t buffer_size;
for (wsize = 0; wide_string[wsize]; wsize++) ;
if (max_bytes < MAX_ESCAPE_BYTES)
max_bytes = MAX_ESCAPE_BYTES;
- if ((buffer = (char *)malloc(wsize * max_bytes + 1)) == NULL) {
+ buffer_size = wsize * max_bytes + 1;
+ if ((buffer = (char *)malloc(buffer_size)) == NULL) {
return NULL;
}
@@ -2556,7 +2558,11 @@ char *wide_to_local_string(wide_string,
/* no MB for this wide */
/* use escape for wide character */
char *escape_string = wide_to_escape_string(wide_string[i]);
- strcat(buffer, escape_string);
+ size_t buffer_len = strlen(buffer);
+ size_t escape_string_len = strlen(escape_string);
+ if (buffer_len + escape_string_len + 1 > buffer_size)
+ escape_string_len = buffer_size - buffer_len - 1;
+ strncat(buffer, escape_string, escape_string_len);
free(escape_string);
}
}

View File

@ -0,0 +1,28 @@
From: Enrico Zini <enrico@debian.org>
Subject: Fix null pointer dereference on invalid UTF-8 input
Bug-Debian: https://bugs.debian.org/1010355
X-Debian-version: 6.0-27
--- unzip-6.0.orig/fileio.c
+++ unzip-6.0/fileio.c
@@ -2364,6 +2364,9 @@ int do_string(__G__ length, option) /*
/* convert UTF-8 to local character set */
fn = utf8_to_local_string(G.unipath_filename,
G.unicode_escape_all);
+ if (fn == NULL)
+ return PK_ERR;
+
/* make sure filename is short enough */
if (strlen(fn) >= FILNAMSIZ) {
fn[FILNAMSIZ - 1] = '\0';
--- unzip-6.0.orig/process.c
+++ unzip-6.0/process.c
@@ -2615,6 +2615,8 @@ char *utf8_to_local_string(utf8_string,
int escape_all;
{
zwchar *wide = utf8_to_wide_string(utf8_string);
+ if (wide == NULL)
+ return NULL;
char *loc = wide_to_local_string(wide, escape_all);
free(wide);
return loc;

View File

@ -27,3 +27,10 @@ unzip-zipbomb-part1.patch
unzip-zipbomb-part2.patch
unzip-zipbomb-part3.patch
unzip-zipbomb-manpage.patch
unzip-zipbomb-part4.patch
unzip-zipbomb-part5.patch
unzip-zipbomb-part6.patch
CVE-2021-4217.patch
CVE-2022-0529.patch
CVE-2022-0530.patch
unzip-6.0-fix-false-overlap-detection-on-32bit-systems.patch

View File

@ -0,0 +1,50 @@
From 13f0260beae851f7d5dd96e9ef757d8d6d7daac1 Mon Sep 17 00:00:00 2001
From: Mark Adler <madler@alumni.caltech.edu>
Date: Sun, 9 Feb 2020 07:20:13 -0800
Subject: [PATCH] Fix false overlapped components detection on 32-bit systems.
32-bit systems with ZIP64_SUPPORT enabled could have different
size types for zoff_t and zusz_t. That resulted in bad parameter
passing to the bound tracking functions, itself due to the lack of
use of C function prototypes in unzip. This commit assures that
parameters are cast properly for those calls.
This problem occurred only for ill-chosen make options, which give
a 32-bit zoff_t. A proper build will result in a zoff_t of 64 bits,
even on 32-bit systems.
---
extract.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/extract.c b/extract.c
index 1b73cb0..d9866f9 100644
--- a/extract.c
+++ b/extract.c
@@ -329,7 +329,7 @@ static ZCONST char Far OverlappedComponents[] =
/* A growable list of spans. */
-typedef zoff_t bound_t;
+typedef zusz_t bound_t;
typedef struct {
bound_t beg; /* start of the span */
bound_t end; /* one past the end of the span */
@@ -518,7 +518,8 @@ int extract_or_test_files(__G) /* return PK-type error code */
return PK_MEM;
}
if ((G.extra_bytes != 0 &&
- cover_add((cover_t *)G.cover, 0, G.extra_bytes) != 0) ||
+ cover_add((cover_t *)G.cover,
+ (bound_t)0, (bound_t)G.extra_bytes) != 0) ||
(G.ecrec.have_ecr64 &&
cover_add((cover_t *)G.cover, G.ecrec.ec64_start,
G.ecrec.ec64_end) != 0) ||
@@ -1216,7 +1217,7 @@ 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 (cover_within((cover_t *)G.cover, (bound_t)request)) {
Info(slide, 0x401, ((char *)slide,
LoadFarString(OverlappedComponents)));
return PK_BOMB;

View File

@ -0,0 +1,25 @@
From 5e2efcd633a4a1fb95a129a75508e7d769e767be Mon Sep 17 00:00:00 2001
From: Mark Adler <madler@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);

View File

@ -0,0 +1,26 @@
From 5c572555cf5d80309a07c30cf7a54b2501493720 Mon Sep 17 00:00:00 2001
From: Mark Adler <madler@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);

View File

@ -0,0 +1,95 @@
From 122050bac16fae82a460ff739fb1ca0f106e9d85 Mon Sep 17 00:00:00 2001
From: Mark Adler <madler@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

View File

@ -1,7 +1,7 @@
# Template file for 'unzip'
pkgname=unzip
version=6.0
revision=14
revision=15
makedepends="bzip2-devel"
short_desc="List, test and extract compressed files in a ZIP archive"
maintainer="Enno Boland <gottox@voidlinux.org>"