unzip: add

This commit is contained in:
git-bruh 2022-09-18 13:04:10 +05:30
parent a00d9d30ed
commit 4441f7a572
No known key found for this signature in database
36 changed files with 3130 additions and 0 deletions

20
extra/unzip/build Executable file
View File

@ -0,0 +1,20 @@
#!/bin/sh -e
while read -r p; do
patch -p1 < "$p"
done < series
CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=64 -DWILD_STOP_AT_DIR -DLARGE_FILE_SUPPORT \
-DUNICODE_SUPPORT -DUNICODE_WCHAR -DUTF8_MAYBE_NATIVE \
-DNO_LCHMOD -LDDATE_FORMAT=DF_YMD -DUSE_BZIP2 -DNATIVE"
make \
D_USE_BZ2=-DUSE_BZIP2 L_BZ2=-lbz2 \
LF2="$LDFLAGS" CF="$CFLAGS $CPPFLAGS -I." \
prefix=/usr \
-f unix/Makefile unzips
make \
prefix="$1/usr" \
MANDIR="$1/usr/share/man/man1" \
-f unix/Makefile install

32
extra/unzip/checksums Normal file
View File

@ -0,0 +1,32 @@
036d96991646d0449ed0aa952e4fbe21b476ce994abc276e49d30e686708bd37
7d8e5c77ad99f9bf56d4cbf224b5635367feb44f81745dec84b44365f8f5eb16
b610136ede8b09c68677bae0cd305df9562eac2ffe6c2c0d901034cc23ec4753
866b8fc05731e4cf72f948c9540c3eb8b2372bf320442456b5b3ae9b74f0827c
b990d8d8d8e02777999484a132170666ea736a865f9ad81da651dc63725475ff
e64c9ddb38c2e7d08bdb80c597f32ee960e18fbe8cb982e444b1ece03ac95cec
74bc961e8013a4058687a3730590a709b7889203beb74a4a8369ba0301bef0e2
41aeebdb356cb6ffa7c0cd168aab63ece586dc03c533e1f720f98422951d79b2
357bc39af42a256084ba69a020c21ebc97429378c23bd5b8c7f22f02d0c68e63
10754a10be46ee8e7b9f84935e7f2087a99abd0a00dff77f97181c8fd71e0eef
a6920a9181d80c6c91a4a0ad57f811768b6f736464ebbf918862f65c7846b894
337131428f491b7030f96ee5b8ef3d8f5963730d1619b2754c624f4616d79adb
64f64985270e026c01d2c19c6b66c218cf5bcfc7cf3d4a44e601fad41975ec73
b7a14c33db93d1e5b4fc6ce113b4b99ff7a81ed56f46c87e001f22ec085e0273
aced0f27191a67f9b8b3fdc5995938a64fd87cea64a0bbba2106e06137ef91c2
47e9deff12845e71de98cd19506a51c21d756a61bb67c0b17e77b84bdbe9fb84
2c55be12907c42a454b91f53de92470d4f5d52e9ba7b0eef79684bd58efd4a1e
3fc23fa7d46846a7089810c2926b3c3e2b3115d623765331876707e5e9d78041
8d9426bdd98cbba00c2d2e36c1dae17da069e6c85bf35811a434a8cbe704e6f4
b6f64d7b57e74ceaa794dd13a6937f063ec915343f3d5d88b0f81c919e7bf171
0ecfe243aa6cc29eaf742d682d515f3ba7d6d7593e7a60b62678a26021126e50
251d5755ffb1e9701434c545fcda0fbfc2a16372f9d807fd07606b1364a1b55b
c9a863e570bdaf2637c43bf1bba3d97808a1b0504d85418f6a8550ac286788f2
fde8f9d6dbc5e9dc59f4497de8e4e313fd74318eaf5f33421acd74442fd10706
ea04cfc8b7ca3b3c03117da0d891870b8c542d26188ef5593fd7e479f4f29f4e
da042334a1ae4a37ea0317ff27cee9eadd0af1529bd8391cde34467a377a4068
6ebd984bef988e620d75dcd6da99ef057cf420701f5230e6c7c883d3a3bc72e1
cb88ba5a2c9bdffd5867206a48841f638e2a7970e88cc009b90202bdca988b8b
4e5a081aa8d0ad9aa5ceeda9eaeefbb6a7e7666d6b7a5b81cb0a61a3ff99a942
24582ff3dcd926d1a46caf8506f76999d2525dd66e36f50b25dca50799695f12
f88b9d4119a1e256f3335a2d2c142dd95d13d7c5f9e5ecd4371e547249f3557c
ee9e26018190a515572b66a26118916843aa1002131a86b5c52769dc663b7acb

1
extra/unzip/depends Normal file
View File

@ -0,0 +1 @@
bzip2

View File

@ -0,0 +1,39 @@
From 754137e70cf58a64ad524b704a86b651ba0cde07 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Wed, 14 Dec 2016 16:30:36 +0100
Subject: [PATCH] Fix CVE-2016-9844 (rhbz#1404283)
Fixes buffer overflow in zipinfo in similar way like fix for
CVE-2014-9913 provided by upstream.
---
zipinfo.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/zipinfo.c b/zipinfo.c
index c03620e..accca2a 100644
--- a/zipinfo.c
+++ b/zipinfo.c
@@ -1984,7 +1984,19 @@ static int zi_short(__G) /* return PK-type error code */
ush dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3);
methbuf[3] = dtype[dnum];
} else if (methnum >= NUM_METHODS) { /* unknown */
- sprintf(&methbuf[1], "%03u", G.crec.compression_method);
+ /* 2016-12-05 SMS.
+ * https://launchpad.net/bugs/1643750
+ * Unexpectedly large compression methods overflow
+ * &methbuf[]. Use the old, three-digit decimal format
+ * for values which fit. Otherwise, sacrifice the "u",
+ * and use four-digit hexadecimal.
+ */
+ if (G.crec.compression_method <= 999) {
+ sprintf( &methbuf[ 1], "%03u", G.crec.compression_method);
+ } else {
+ sprintf( &methbuf[ 0], "%04X", G.crec.compression_method);
+ }
+
}
for (k = 0; k < 15; ++k)
--
2.5.5

View File

@ -0,0 +1,30 @@
unzip-6.0-bzip2-configure.patch
unzip-6.0-exec-shield.patch
unzip-6.0-close.patch
unzip-6.0-attribs-overflow.patch
unzip-6.0-configure.patch
unzip-6.0-manpage-fix.patch
unzip-6.0-fix-recmatch.patch
unzip-6.0-symlink.patch
unzip-6.0-caseinsensitive.patch
unzip-6.0-format-secure.patch
unzip-6.0-valgrind.patch
unzip-6.0-x-option.patch
unzip-6.0-overflow.patch
unzip-6.0-cve-2014-8139.patch
unzip-6.0-cve-2014-8140.patch
unzip-6.0-cve-2014-8141.patch
unzip-6.0-overflow-long-fsize.patch
unzip-6.0-heap-overflow-infloop.patch
unzip-6.0-alt-iconv-utf8.patch
unzip-6.0-alt-iconv-utf8-print.patch
0001-Fix-CVE-2016-9844-rhbz-1404283.patch
unzip-6.0-timestamp.patch
unzip-6.0-cve-2018-1000035-heap-based-overflow.patch
unzip-6.0-cve-2018-18384.patch
unzip-6.0-COVSCAN-fix-unterminated-string.patch
unzip-zipbomb-part1.patch
unzip-zipbomb-part2.patch
unzip-zipbomb-part3.patch
unzip-zipbomb-manpage.patch
unzip-6.0_CVE-2021-4217.patch

View File

@ -0,0 +1,131 @@
From 06d1b08aef94984256cad3c5a54cedb10295681f Mon Sep 17 00:00:00 2001
From: Jakub Martisko <jamartis@redhat.com>
Date: Thu, 8 Nov 2018 09:31:18 +0100
Subject: [PATCH] Possible unterminated string fix
---
unix/unix.c | 4 +++-
unix/unxcfg.h | 2 +-
unzip.c | 12 ++++++++----
zipinfo.c | 12 ++++++++----
4 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/unix/unix.c b/unix/unix.c
index 59b622d..cd57f80 100644
--- a/unix/unix.c
+++ b/unix/unix.c
@@ -1945,7 +1945,9 @@ void init_conversion_charsets()
for(i = 0; i < sizeof(dos_charset_map)/sizeof(CHARSET_MAP); i++)
if(!strcasecmp(local_charset, dos_charset_map[i].local_charset)) {
strncpy(OEM_CP, dos_charset_map[i].archive_charset,
- sizeof(OEM_CP));
+ MAX_CP_NAME - 1);
+
+ OEM_CP[MAX_CP_NAME - 1] = '\0';
break;
}
}
diff --git a/unix/unxcfg.h b/unix/unxcfg.h
index 8729de2..9ee8cfe 100644
--- a/unix/unxcfg.h
+++ b/unix/unxcfg.h
@@ -228,7 +228,7 @@ typedef struct stat z_stat;
/* and notfirstcall are used by do_wild(). */
-#define MAX_CP_NAME 25
+#define MAX_CP_NAME 25 + 1
#ifdef SETLOCALE
# undef SETLOCALE
diff --git a/unzip.c b/unzip.c
index 2d94a38..a485f2b 100644
--- a/unzip.c
+++ b/unzip.c
@@ -1561,7 +1561,8 @@ int uz_opts(__G__ pargc, pargv)
"error: a valid character encoding should follow the -I argument"));
return(PK_PARAM);
}
- strncpy(ISO_CP, s, sizeof(ISO_CP));
+ strncpy(ISO_CP, s, MAX_CP_NAME - 1);
+ ISO_CP[MAX_CP_NAME - 1] = '\0';
} else { /* -I charset */
++argv;
if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
@@ -1570,7 +1571,8 @@ int uz_opts(__G__ pargc, pargv)
return(PK_PARAM);
}
s = *argv;
- strncpy(ISO_CP, s, sizeof(ISO_CP));
+ strncpy(ISO_CP, s, MAX_CP_NAME - 1);
+ ISO_CP[MAX_CP_NAME - 1] = '\0';
}
while(*(++s)); /* No params straight after charset name */
}
@@ -1665,7 +1667,8 @@ int uz_opts(__G__ pargc, pargv)
"error: a valid character encoding should follow the -I argument"));
return(PK_PARAM);
}
- strncpy(OEM_CP, s, sizeof(OEM_CP));
+ strncpy(OEM_CP, s, MAX_CP_NAME - 1);
+ OEM_CP[MAX_CP_NAME - 1] = '\0';
} else { /* -O charset */
++argv;
if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
@@ -1674,7 +1677,8 @@ int uz_opts(__G__ pargc, pargv)
return(PK_PARAM);
}
s = *argv;
- strncpy(OEM_CP, s, sizeof(OEM_CP));
+ strncpy(OEM_CP, s, MAX_CP_NAME - 1);
+ OEM_CP[MAX_CP_NAME - 1] = '\0';
}
while(*(++s)); /* No params straight after charset name */
}
diff --git a/zipinfo.c b/zipinfo.c
index accca2a..cb7e08d 100644
--- a/zipinfo.c
+++ b/zipinfo.c
@@ -519,7 +519,8 @@ int zi_opts(__G__ pargc, pargv)
"error: a valid character encoding should follow the -I argument"));
return(PK_PARAM);
}
- strncpy(ISO_CP, s, sizeof(ISO_CP));
+ strncpy(ISO_CP, s, MAX_CP_NAME - 1);
+ ISO_CP[MAX_CP_NAME - 1] = '\0';
} else { /* -I charset */
++argv;
if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
@@ -528,7 +529,8 @@ int zi_opts(__G__ pargc, pargv)
return(PK_PARAM);
}
s = *argv;
- strncpy(ISO_CP, s, sizeof(ISO_CP));
+ strncpy(ISO_CP, s, MAX_CP_NAME - 1);
+ ISO_CP[MAX_CP_NAME - 1] = '\0';
}
while(*(++s)); /* No params straight after charset name */
}
@@ -568,7 +570,8 @@ int zi_opts(__G__ pargc, pargv)
"error: a valid character encoding should follow the -I argument"));
return(PK_PARAM);
}
- strncpy(OEM_CP, s, sizeof(OEM_CP));
+ strncpy(OEM_CP, s, MAX_CP_NAME - 1);
+ OEM_CP[MAX_CP_NAME - 1] = '\0';
} else { /* -O charset */
++argv;
if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
@@ -577,7 +580,8 @@ int zi_opts(__G__ pargc, pargv)
return(PK_PARAM);
}
s = *argv;
- strncpy(OEM_CP, s, sizeof(OEM_CP));
+ strncpy(OEM_CP, s, MAX_CP_NAME - 1);
+ OEM_CP[MAX_CP_NAME - 1] = '\0';
}
while(*(++s)); /* No params straight after charset name */
}
--
2.14.5

View File

@ -0,0 +1,381 @@
From ca0212ba19b64488b9e8459a762c11ecd6e7d0bd Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Tue, 24 Nov 2015 17:56:11 +0100
Subject: [PATCH] print correctly non-ascii filenames
---
extract.c | 289 ++++++++++++++++++++++++++++++++++++++++++++++++--------------
unzpriv.h | 7 ++
2 files changed, 233 insertions(+), 63 deletions(-)
diff --git a/extract.c b/extract.c
index 0ee4e93..741b7e0 100644
--- a/extract.c
+++ b/extract.c
@@ -2648,8 +2648,21 @@ static void set_deferred_symlink(__G__ slnk_entry)
} /* end function set_deferred_symlink() */
#endif /* SYMLINKS */
+/*
+ * If Unicode is supported, assume we have what we need to do this
+ * check using wide characters, avoiding MBCS issues.
+ */
-
+#ifndef UZ_FNFILTER_REPLACECHAR
+ /* A convenient choice for the replacement of unprintable char codes is
+ * the "single char wildcard", as this character is quite unlikely to
+ * appear in filenames by itself. The following default definition
+ * sets the replacement char to a question mark as the most common
+ * "single char wildcard"; this setting should be overridden in the
+ * appropiate system-specific configuration header when needed.
+ */
+# define UZ_FNFILTER_REPLACECHAR '?'
+#endif
/*************************/
/* Function fnfilter() */ /* here instead of in list.c for SFX */
@@ -2661,48 +2674,168 @@ char *fnfilter(raw, space, size) /* convert name to safely printable form */
extent size;
{
#ifndef NATIVE /* ASCII: filter ANSI escape codes, etc. */
- ZCONST uch *r=(ZCONST uch *)raw;
+ ZCONST uch *r; // =(ZCONST uch *)raw;
uch *s=space;
uch *slim=NULL;
uch *se=NULL;
int have_overflow = FALSE;
- if (size > 0) {
- slim = space + size
-#ifdef _MBCS
- - (MB_CUR_MAX - 1)
-#endif
- - 4;
+# if defined( UNICODE_SUPPORT) && defined( _MBCS)
+/* If Unicode support is enabled, and we have multi-byte characters,
+ * then do the isprint() checks by first converting to wide characters
+ * and checking those. This avoids our having to parse multi-byte
+ * characters for ourselves. After the wide-char replacements have been
+ * made, the wide string is converted back to the local character set.
+ */
+ wchar_t *wstring; /* wchar_t version of raw */
+ size_t wslen; /* length of wstring */
+ wchar_t *wostring; /* wchar_t version of output string */
+ size_t woslen; /* length of wostring */
+ char *newraw; /* new raw */
+
+ /* 2012-11-06 SMS.
+ * Changed to check the value returned by mbstowcs(), and bypass the
+ * Unicode processing if it fails. This seems to fix a problem
+ * reported in the SourceForge forum, but it's not clear that we
+ * should be doing any Unicode processing without some evidence that
+ * the name actually is Unicode. (Check bit 11 in the flags before
+ * coming here?)
+ * http://sourceforge.net/p/infozip/bugs/40/
+ */
+
+ if (MB_CUR_MAX <= 1)
+ {
+ /* There's no point to converting multi-byte chars if there are
+ * no multi-byte chars.
+ */
+ wslen = (size_t)-1;
}
- while (*r) {
- if (size > 0 && s >= slim && se == NULL) {
- se = s;
+ else
+ {
+ /* Get Unicode wide character count (for storage allocation). */
+ wslen = mbstowcs( NULL, raw, 0);
+ }
+
+ if (wslen != (size_t)-1)
+ {
+ /* Apparently valid Unicode. Allocate wide-char storage. */
+ wstring = (wchar_t *)malloc((wslen + 1) * sizeof(wchar_t));
+ if (wstring == NULL) {
+ strcpy( (char *)space, raw);
+ return (char *)space;
}
-#ifdef QDOS
- if (qlflag & 2) {
- if (*r == '/' || *r == '.') {
+ wostring = (wchar_t *)malloc(2 * (wslen + 1) * sizeof(wchar_t));
+ if (wostring == NULL) {
+ free(wstring);
+ strcpy( (char *)space, raw);
+ return (char *)space;
+ }
+
+ /* Convert the multi-byte Unicode to wide chars. */
+ wslen = mbstowcs(wstring, raw, wslen + 1);
+
+ /* Filter the wide-character string. */
+ fnfilterw( wstring, wostring, (2 * (wslen + 1) * sizeof(wchar_t)));
+
+ /* Convert filtered wide chars back to multi-byte. */
+ woslen = wcstombs( NULL, wostring, 0);
+ if ((newraw = malloc(woslen + 1)) == NULL) {
+ free(wstring);
+ free(wostring);
+ strcpy( (char *)space, raw);
+ return (char *)space;
+ }
+ woslen = wcstombs( newraw, wostring, (woslen * MB_CUR_MAX) + 1);
+
+ if (size > 0) {
+ slim = space + size - 4;
+ }
+ r = (ZCONST uch *)newraw;
+ while (*r) {
+ if (size > 0 && s >= slim && se == NULL) {
+ se = s;
+ }
+# ifdef QDOS
+ if (qlflag & 2) {
+ if (*r == '/' || *r == '.') {
+ if (se != NULL && (s > (space + (size-3)))) {
+ have_overflow = TRUE;
+ break;
+ }
+ ++r;
+ *s++ = '_';
+ continue;
+ }
+ } else
+# endif
+ {
if (se != NULL && (s > (space + (size-3)))) {
have_overflow = TRUE;
break;
}
- ++r;
- *s++ = '_';
- continue;
+ *s++ = *r++;
}
- } else
+ }
+ if (have_overflow) {
+ strcpy((char *)se, "...");
+ } else {
+ *s = '\0';
+ }
+
+ free(wstring);
+ free(wostring);
+ free(newraw);
+ }
+ else
+# endif /* defined( UNICODE_SUPPORT) && defined( _MBCS) */
+ {
+ /* No Unicode support, or apparently invalid Unicode. */
+ r = (ZCONST uch *)raw;
+
+ if (size > 0) {
+ slim = space + size
+#ifdef _MBCS
+ - (MB_CUR_MAX - 1)
+#endif
+ - 4;
+ }
+ while (*r) {
+ if (size > 0 && s >= slim && se == NULL) {
+ se = s;
+ }
+#ifdef QDOS
+ if (qlflag & 2) {
+ if (*r == '/' || *r == '.') {
+ if (se != NULL && (s > (space + (size-3)))) {
+ have_overflow = TRUE;
+ break;
+ }
+ ++r;
+ *s++ = '_';
+ continue;
+ }
+ } else
#endif
#ifdef HAVE_WORKING_ISPRINT
-# ifndef UZ_FNFILTER_REPLACECHAR
- /* A convenient choice for the replacement of unprintable char codes is
- * the "single char wildcard", as this character is quite unlikely to
- * appear in filenames by itself. The following default definition
- * sets the replacement char to a question mark as the most common
- * "single char wildcard"; this setting should be overridden in the
- * appropiate system-specific configuration header when needed.
- */
-# define UZ_FNFILTER_REPLACECHAR '?'
-# endif
- if (!isprint(*r)) {
+ if (!isprint(*r)) {
+ if (*r < 32) {
+ /* ASCII control codes are escaped as "^{letter}". */
+ if (se != NULL && (s > (space + (size-4)))) {
+ have_overflow = TRUE;
+ break;
+ }
+ *s++ = '^', *s++ = (uch)(64 + *r++);
+ } else {
+ /* Other unprintable codes are replaced by the
+ * placeholder character. */
+ if (se != NULL && (s > (space + (size-3)))) {
+ have_overflow = TRUE;
+ break;
+ }
+ *s++ = UZ_FNFILTER_REPLACECHAR;
+ INCSTR(r);
+ }
+#else /* !HAVE_WORKING_ISPRINT */
if (*r < 32) {
/* ASCII control codes are escaped as "^{letter}". */
if (se != NULL && (s > (space + (size-4)))) {
@@ -2710,47 +2843,30 @@ char *fnfilter(raw, space, size) /* convert name to safely printable form */
break;
}
*s++ = '^', *s++ = (uch)(64 + *r++);
+#endif /* ?HAVE_WORKING_ISPRINT */
} else {
- /* Other unprintable codes are replaced by the
- * placeholder character. */
+#ifdef _MBCS
+ unsigned i = CLEN(r);
+ if (se != NULL && (s > (space + (size-i-2)))) {
+ have_overflow = TRUE;
+ break;
+ }
+ for (; i > 0; i--)
+ *s++ = *r++;
+#else
if (se != NULL && (s > (space + (size-3)))) {
have_overflow = TRUE;
break;
}
- *s++ = UZ_FNFILTER_REPLACECHAR;
- INCSTR(r);
- }
-#else /* !HAVE_WORKING_ISPRINT */
- if (*r < 32) {
- /* ASCII control codes are escaped as "^{letter}". */
- if (se != NULL && (s > (space + (size-4)))) {
- have_overflow = TRUE;
- break;
- }
- *s++ = '^', *s++ = (uch)(64 + *r++);
-#endif /* ?HAVE_WORKING_ISPRINT */
- } else {
-#ifdef _MBCS
- unsigned i = CLEN(r);
- if (se != NULL && (s > (space + (size-i-2)))) {
- have_overflow = TRUE;
- break;
- }
- for (; i > 0; i--)
*s++ = *r++;
-#else
- if (se != NULL && (s > (space + (size-3)))) {
- have_overflow = TRUE;
- break;
- }
- *s++ = *r++;
#endif
- }
- }
- if (have_overflow) {
- strcpy((char *)se, "...");
- } else {
- *s = '\0';
+ }
+ }
+ if (have_overflow) {
+ strcpy((char *)se, "...");
+ } else {
+ *s = '\0';
+ }
}
#ifdef WINDLL
@@ -2772,6 +2888,53 @@ char *fnfilter(raw, space, size) /* convert name to safely printable form */
} /* end function fnfilter() */
+#if defined( UNICODE_SUPPORT) && defined( _MBCS)
+
+/****************************/
+/* Function fnfilter[w]() */ /* (Here instead of in list.c for SFX.) */
+/****************************/
+
+/* fnfilterw() - Convert wide name to safely printable form. */
+
+/* fnfilterw() - Convert wide-character name to safely printable form. */
+
+wchar_t *fnfilterw( src, dst, siz)
+ ZCONST wchar_t *src; /* Pointer to source char (string). */
+ wchar_t *dst; /* Pointer to destination char (string). */
+ extent siz; /* Not used (!). */
+{
+ wchar_t *dsx = dst;
+
+ /* Filter the wide chars. */
+ while (*src)
+ {
+ if (iswprint( *src))
+ {
+ /* Printable code. Copy it. */
+ *dst++ = *src;
+ }
+ else
+ {
+ /* Unprintable code. Substitute something printable for it. */
+ if (*src < 32)
+ {
+ /* Replace ASCII control code with "^{letter}". */
+ *dst++ = (wchar_t)'^';
+ *dst++ = (wchar_t)(64 + *src);
+ }
+ else
+ {
+ /* Replace other unprintable code with the placeholder. */
+ *dst++ = (wchar_t)UZ_FNFILTER_REPLACECHAR;
+ }
+ }
+ src++;
+ }
+ *dst = (wchar_t)0; /* NUL-terminate the destination string. */
+ return dsx;
+} /* fnfilterw(). */
+
+#endif /* defined( UNICODE_SUPPORT) && defined( _MBCS) */
#ifdef SET_DIR_ATTRIB
diff --git a/unzpriv.h b/unzpriv.h
index 22d3923..e48a652 100644
--- a/unzpriv.h
+++ b/unzpriv.h
@@ -1212,6 +1212,7 @@
# ifdef UNICODE_WCHAR
# if !(defined(_WIN32_WCE) || defined(POCKET_UNZIP))
# include <wchar.h>
+# include <wctype.h>
# endif
# endif
# ifndef _MBCS /* no need to include <locale.h> twice, see below */
@@ -2410,6 +2411,12 @@ int memflush OF((__GPRO__ ZCONST uch *rawbuf, ulg size));
char *fnfilter OF((ZCONST char *raw, uch *space,
extent size));
+# if defined( UNICODE_SUPPORT) && defined( _MBCS)
+wchar_t *fnfilterw OF((ZCONST wchar_t *src, wchar_t *dst,
+ extent siz));
+#endif
+
+
/*---------------------------------------------------------------------------
Decompression functions:
---------------------------------------------------------------------------*/
--
2.4.3

View File

@ -0,0 +1,398 @@
From: Giovanni Scafora <giovanni.archlinux.org>
Subject: unzip files encoded with non-latin, non-unicode file names
Last-Update: 2015-02-11
Updated 2015-02-11 by Marc Deslauriers <marc.deslauriers@canonical.com>
to fix buffer overflow in charset_to_intern()
Index: unzip-6.0/unix/unix.c
===================================================================
--- unzip-6.0.orig/unix/unix.c 2015-02-11 08:46:43.675324290 -0500
+++ unzip-6.0/unix/unix.c 2015-02-11 09:18:04.902081319 -0500
@@ -30,6 +30,9 @@
#define UNZIP_INTERNAL
#include "unzip.h"
+#include <iconv.h>
+#include <langinfo.h>
+
#ifdef SCO_XENIX
# define SYSNDIR
#else /* SCO Unix, AIX, DNIX, TI SysV, Coherent 4.x, ... */
@@ -1874,3 +1877,102 @@
}
}
#endif /* QLZIP */
+
+
+typedef struct {
+ char *local_charset;
+ char *archive_charset;
+} CHARSET_MAP;
+
+/* A mapping of local <-> archive charsets used by default to convert filenames
+ * of DOS/Windows Zip archives. Currently very basic. */
+static CHARSET_MAP dos_charset_map[] = {
+ { "ANSI_X3.4-1968", "CP850" },
+ { "ISO-8859-1", "CP850" },
+ { "CP1252", "CP850" },
+ { "UTF-8", "CP866" },
+ { "KOI8-R", "CP866" },
+ { "KOI8-U", "CP866" },
+ { "ISO-8859-5", "CP866" }
+};
+
+char OEM_CP[MAX_CP_NAME] = "";
+char ISO_CP[MAX_CP_NAME] = "";
+
+/* Try to guess the default value of OEM_CP based on the current locale.
+ * ISO_CP is left alone for now. */
+void init_conversion_charsets()
+{
+ const char *local_charset;
+ int i;
+
+ /* Make a guess only if OEM_CP not already set. */
+ if(*OEM_CP == '\0') {
+ local_charset = nl_langinfo(CODESET);
+ for(i = 0; i < sizeof(dos_charset_map)/sizeof(CHARSET_MAP); i++)
+ if(!strcasecmp(local_charset, dos_charset_map[i].local_charset)) {
+ strncpy(OEM_CP, dos_charset_map[i].archive_charset,
+ sizeof(OEM_CP));
+ break;
+ }
+ }
+}
+
+/* Convert a string from one encoding to the current locale using iconv().
+ * Be as non-intrusive as possible. If error is encountered during covertion
+ * just leave the string intact. */
+static void charset_to_intern(char *string, char *from_charset)
+{
+ iconv_t cd;
+ char *s,*d, *buf;
+ size_t slen, dlen, buflen;
+ const char *local_charset;
+
+ if(*from_charset == '\0')
+ return;
+
+ buf = NULL;
+ local_charset = nl_langinfo(CODESET);
+
+ if((cd = iconv_open(local_charset, from_charset)) == (iconv_t)-1)
+ return;
+
+ slen = strlen(string);
+ s = string;
+
+ /* Make sure OUTBUFSIZ + 1 never ends up smaller than FILNAMSIZ
+ * as this function also gets called with G.outbuf in fileio.c
+ */
+ buflen = FILNAMSIZ;
+ if (OUTBUFSIZ + 1 < FILNAMSIZ)
+ {
+ buflen = OUTBUFSIZ + 1;
+ }
+
+ d = buf = malloc(buflen);
+ if(!d)
+ goto cleanup;
+
+ bzero(buf,buflen);
+ dlen = buflen - 1;
+
+ if(iconv(cd, &s, &slen, &d, &dlen) == (size_t)-1)
+ goto cleanup;
+ strncpy(string, buf, buflen);
+
+ cleanup:
+ free(buf);
+ iconv_close(cd);
+}
+
+/* Convert a string from OEM_CP to the current locale charset. */
+inline void oem_intern(char *string)
+{
+ charset_to_intern(string, OEM_CP);
+}
+
+/* Convert a string from ISO_CP to the current locale charset. */
+inline void iso_intern(char *string)
+{
+ charset_to_intern(string, ISO_CP);
+}
Index: unzip-6.0/unix/unxcfg.h
===================================================================
--- unzip-6.0.orig/unix/unxcfg.h 2015-02-11 08:46:43.675324290 -0500
+++ unzip-6.0/unix/unxcfg.h 2015-02-11 08:46:43.671324260 -0500
@@ -228,4 +228,30 @@
/* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */
/* and notfirstcall are used by do_wild(). */
+
+#define MAX_CP_NAME 25
+
+#ifdef SETLOCALE
+# undef SETLOCALE
+#endif
+#define SETLOCALE(category, locale) setlocale(category, locale)
+#include <locale.h>
+
+#ifdef _ISO_INTERN
+# undef _ISO_INTERN
+#endif
+#define _ISO_INTERN(str1) iso_intern(str1)
+
+#ifdef _OEM_INTERN
+# undef _OEM_INTERN
+#endif
+#ifndef IZ_OEM2ISO_ARRAY
+# define IZ_OEM2ISO_ARRAY
+#endif
+#define _OEM_INTERN(str1) oem_intern(str1)
+
+void iso_intern(char *);
+void oem_intern(char *);
+void init_conversion_charsets(void);
+
#endif /* !__unxcfg_h */
Index: unzip-6.0/unzip.c
===================================================================
--- unzip-6.0.orig/unzip.c 2015-02-11 08:46:43.675324290 -0500
+++ unzip-6.0/unzip.c 2015-02-11 08:46:43.675324290 -0500
@@ -327,11 +327,21 @@
-2 just filenames but allow -h/-t/-z -l long Unix \"ls -l\" format\n\
-v verbose, multi-page format\n";
+#ifndef UNIX
static ZCONST char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\
-h print header line -t print totals for listed files or for all\n\
-z print zipfile comment -T print file times in sortable decimal format\
\n -C be case-insensitive %s\
-x exclude filenames that follow from listing\n";
+#else /* UNIX */
+static ZCONST char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\
+ -h print header line -t print totals for listed files or for all\n\
+ -z print zipfile comment %c-T%c print file times in sortable decimal format\
+\n %c-C%c be case-insensitive %s\
+ -x exclude filenames that follow from listing\n\
+ -O CHARSET specify a character encoding for DOS, Windows and OS/2 archives\n\
+ -I CHARSET specify a character encoding for UNIX and other archives\n";
+#endif /* !UNIX */
#ifdef MORE
static ZCONST char Far ZipInfoUsageLine4[] =
" -M page output through built-in \"more\"\n";
@@ -664,6 +674,17 @@
-U use escapes for all non-ASCII Unicode -UU ignore any Unicode fields\n\
-C match filenames case-insensitively -L make (some) names \
lowercase\n %-42s -V retain VMS version numbers\n%s";
+#elif (defined UNIX)
+static ZCONST char Far UnzipUsageLine4[] = "\
+modifiers:\n\
+ -n never overwrite existing files -q quiet mode (-qq => quieter)\n\
+ -o overwrite files WITHOUT prompting -a auto-convert any text files\n\
+ -j junk paths (do not make directories) -aa treat ALL files as text\n\
+ -U use escapes for all non-ASCII Unicode -UU ignore any Unicode fields\n\
+ -C match filenames case-insensitively -L make (some) names \
+lowercase\n %-42s -V retain VMS version numbers\n%s\
+ -O CHARSET specify a character encoding for DOS, Windows and OS/2 archives\n\
+ -I CHARSET specify a character encoding for UNIX and other archives\n\n";
#else /* !VMS */
static ZCONST char Far UnzipUsageLine4[] = "\
modifiers:\n\
@@ -802,6 +823,10 @@
#endif /* UNICODE_SUPPORT */
+#ifdef UNIX
+ init_conversion_charsets();
+#endif
+
#if (defined(__IBMC__) && defined(__DEBUG_ALLOC__))
extern void DebugMalloc(void);
@@ -1335,6 +1360,11 @@
argc = *pargc;
argv = *pargv;
+#ifdef UNIX
+ extern char OEM_CP[MAX_CP_NAME];
+ extern char ISO_CP[MAX_CP_NAME];
+#endif
+
while (++argv, (--argc > 0 && *argv != NULL && **argv == '-')) {
s = *argv + 1;
while ((c = *s++) != 0) { /* "!= 0": prevent Turbo C warning */
@@ -1516,6 +1546,35 @@
}
break;
#endif /* MACOS */
+#ifdef UNIX
+ case ('I'):
+ if (negative) {
+ Info(slide, 0x401, ((char *)slide,
+ "error: encodings can't be negated"));
+ return(PK_PARAM);
+ } else {
+ if(*s) { /* Handle the -Icharset case */
+ /* Assume that charsets can't start with a dash to spot arguments misuse */
+ if(*s == '-') {
+ Info(slide, 0x401, ((char *)slide,
+ "error: a valid character encoding should follow the -I argument"));
+ return(PK_PARAM);
+ }
+ strncpy(ISO_CP, s, sizeof(ISO_CP));
+ } else { /* -I charset */
+ ++argv;
+ if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
+ Info(slide, 0x401, ((char *)slide,
+ "error: a valid character encoding should follow the -I argument"));
+ return(PK_PARAM);
+ }
+ s = *argv;
+ strncpy(ISO_CP, s, sizeof(ISO_CP));
+ }
+ while(*(++s)); /* No params straight after charset name */
+ }
+ break;
+#endif /* ?UNIX */
case ('j'): /* junk pathnames/directory structure */
if (negative)
uO.jflag = FALSE, negative = 0;
@@ -1591,6 +1650,35 @@
} else
++uO.overwrite_all;
break;
+#ifdef UNIX
+ case ('O'):
+ if (negative) {
+ Info(slide, 0x401, ((char *)slide,
+ "error: encodings can't be negated"));
+ return(PK_PARAM);
+ } else {
+ if(*s) { /* Handle the -Ocharset case */
+ /* Assume that charsets can't start with a dash to spot arguments misuse */
+ if(*s == '-') {
+ Info(slide, 0x401, ((char *)slide,
+ "error: a valid character encoding should follow the -I argument"));
+ return(PK_PARAM);
+ }
+ strncpy(OEM_CP, s, sizeof(OEM_CP));
+ } else { /* -O charset */
+ ++argv;
+ if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
+ Info(slide, 0x401, ((char *)slide,
+ "error: a valid character encoding should follow the -O argument"));
+ return(PK_PARAM);
+ }
+ s = *argv;
+ strncpy(OEM_CP, s, sizeof(OEM_CP));
+ }
+ while(*(++s)); /* No params straight after charset name */
+ }
+ break;
+#endif /* ?UNIX */
case ('p'): /* pipes: extract to stdout, no messages */
if (negative) {
uO.cflag = FALSE;
Index: unzip-6.0/unzpriv.h
===================================================================
--- unzip-6.0.orig/unzpriv.h 2015-02-11 08:46:43.675324290 -0500
+++ unzip-6.0/unzpriv.h 2015-02-11 08:46:43.675324290 -0500
@@ -3008,7 +3008,7 @@
!(((islochdr) || (isuxatt)) && \
((hostver) == 25 || (hostver) == 26 || (hostver) == 40))) || \
(hostnum) == FS_HPFS_ || \
- ((hostnum) == FS_NTFS_ && (hostver) == 50)) { \
+ ((hostnum) == FS_NTFS_ /* && (hostver) == 50 */ )) { \
_OEM_INTERN((string)); \
} else { \
_ISO_INTERN((string)); \
Index: unzip-6.0/zipinfo.c
===================================================================
--- unzip-6.0.orig/zipinfo.c 2015-02-11 08:46:43.675324290 -0500
+++ unzip-6.0/zipinfo.c 2015-02-11 08:46:43.675324290 -0500
@@ -457,6 +457,10 @@
int tflag_slm=TRUE, tflag_2v=FALSE;
int explicit_h=FALSE, explicit_t=FALSE;
+#ifdef UNIX
+ extern char OEM_CP[MAX_CP_NAME];
+ extern char ISO_CP[MAX_CP_NAME];
+#endif
#ifdef MACOS
uO.lflag = LFLAG; /* reset default on each call */
@@ -501,6 +505,35 @@
uO.lflag = 0;
}
break;
+#ifdef UNIX
+ case ('I'):
+ if (negative) {
+ Info(slide, 0x401, ((char *)slide,
+ "error: encodings can't be negated"));
+ return(PK_PARAM);
+ } else {
+ if(*s) { /* Handle the -Icharset case */
+ /* Assume that charsets can't start with a dash to spot arguments misuse */
+ if(*s == '-') {
+ Info(slide, 0x401, ((char *)slide,
+ "error: a valid character encoding should follow the -I argument"));
+ return(PK_PARAM);
+ }
+ strncpy(ISO_CP, s, sizeof(ISO_CP));
+ } else { /* -I charset */
+ ++argv;
+ if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
+ Info(slide, 0x401, ((char *)slide,
+ "error: a valid character encoding should follow the -I argument"));
+ return(PK_PARAM);
+ }
+ s = *argv;
+ strncpy(ISO_CP, s, sizeof(ISO_CP));
+ }
+ while(*(++s)); /* No params straight after charset name */
+ }
+ break;
+#endif /* ?UNIX */
case 'l': /* longer form of "ls -l" type listing */
if (negative)
uO.lflag = -2, negative = 0;
@@ -521,6 +554,35 @@
G.M_flag = TRUE;
break;
#endif
+#ifdef UNIX
+ case ('O'):
+ if (negative) {
+ Info(slide, 0x401, ((char *)slide,
+ "error: encodings can't be negated"));
+ return(PK_PARAM);
+ } else {
+ if(*s) { /* Handle the -Ocharset case */
+ /* Assume that charsets can't start with a dash to spot arguments misuse */
+ if(*s == '-') {
+ Info(slide, 0x401, ((char *)slide,
+ "error: a valid character encoding should follow the -I argument"));
+ return(PK_PARAM);
+ }
+ strncpy(OEM_CP, s, sizeof(OEM_CP));
+ } else { /* -O charset */
+ ++argv;
+ if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
+ Info(slide, 0x401, ((char *)slide,
+ "error: a valid character encoding should follow the -O argument"));
+ return(PK_PARAM);
+ }
+ s = *argv;
+ strncpy(OEM_CP, s, sizeof(OEM_CP));
+ }
+ while(*(++s)); /* No params straight after charset name */
+ }
+ break;
+#endif /* ?UNIX */
case 's': /* default: shorter "ls -l" type listing */
if (negative)
uO.lflag = -2, negative = 0;

View File

@ -0,0 +1,12 @@
diff -up unzip60/zipinfo.c.attribs-overflow unzip60/zipinfo.c
--- unzip60/zipinfo.c.attribs-overflow 2009-11-30 09:55:39.000000000 +0100
+++ unzip60/zipinfo.c 2009-11-30 09:56:42.844263244 +0100
@@ -1881,7 +1881,7 @@ static int zi_short(__G) /* return PK-
#endif
int k, error, error_in_archive=PK_COOL;
unsigned hostnum, hostver, methid, methnum, xattr;
- char *p, workspace[12], attribs[16];
+ char *p, workspace[12], attribs[17];
char methbuf[5];
static ZCONST char dtype[5]="NXFS"; /* normal, maximum, fast, superfast */
static ZCONST char Far os[NUM_HOSTS+1][4] = {

View File

@ -0,0 +1,30 @@
diff -up unzip60/unix/configure.bzip2-configure unzip60/unix/configure
--- unzip60/unix/configure.bzip2-configure 2009-04-16 21:25:12.000000000 +0200
+++ unzip60/unix/configure 2009-11-18 11:22:14.598389194 +0100
@@ -640,7 +640,24 @@ else
D_USE_BZ2="-DUSE_BZIP2"
L_BZ2="${BZLF} -lbz2"
else
- echo "-- bzip2 sources not found - no bzip2 support"
+ echo " Check if OS already has bzip2 library installed"
+ cat > conftest.c << _EOF_
+#include "bzlib.h"
+int main()
+{
+ bz_stream strm;
+ BZ2_bzCompressEnd(&strm);
+ return 0;
+}
+_EOF_
+ $CC $CFLAGS -o conftest conftest.c -lbz2 > /dev/null 2>/dev/null
+ if test $? -eq 0; then
+ echo "-- OS supports bzip2 - linking in bzip2"
+ D_USE_BZ2="-DUSE_BZIP2"
+ L_BZ2="${BZLF} -lbz2"
+ else
+ echo "-- Either bzlib.h or libbz2.a not found - no bzip2"
+ fi
fi
fi

View File

@ -0,0 +1,131 @@
diff --git a/match.c b/match.c
index 6cd656f..4e569f5 100644
--- a/match.c
+++ b/match.c
@@ -190,10 +190,10 @@ char *___tmp_ptr;
#endif
-static int recmatch(p, s, cs)
+static int recmatch(p, s, ci)
ZCONST char *p; /* sh pattern to match */
ZCONST char *s; /* string to match it to */
-int cs; /* flag: force case-sensitive matching */
+int ci; /* flag: force case-insensitive matching */
/* Recursively compare the sh pattern p with the string s and return 1 if
they match, and 0 or 2 if they don't or if there is a syntax error in the
pattern. This routine recurses on itself no deeper than the number of
@@ -214,7 +214,7 @@ int cs; /* flag: force case-sensitive matching */
if (CLEN(p) == 2) {
if (CLEN(s) == 2) {
return (*p == *s && *(p+1) == *(s+1)) ?
- recmatch(p + 2, s + 2, cs) : 0;
+ recmatch(p + 2, s + 2, ci) : 0;
} else {
return 0;
}
@@ -230,9 +230,9 @@ int cs; /* flag: force case-sensitive matching */
/* '?' (or '%' or '#') matches any character (but not an empty string) */
if (c == WILDCHR_SINGLE) {
if (wild_stop_at_dir)
- return (*s && *s != DIRSEP_CHR) ? recmatch(p, s + CLEN(s), cs) : 0;
+ return (*s && *s != DIRSEP_CHR) ? recmatch(p, s + CLEN(s), ci) : 0;
else
- return *s ? recmatch(p, s + CLEN(s), cs) : 0;
+ return *s ? recmatch(p, s + CLEN(s), ci) : 0;
}
/* WILDCHR_MULTI ('*') matches any number of characters, including zero */
@@ -253,14 +253,14 @@ int cs; /* flag: force case-sensitive matching */
# endif /* ?AMIGA */
/* Single WILDCHR_MULTI ('*'): this doesn't match slashes */
for (; *s && *s != DIRSEP_CHR; INCSTR(s))
- if ((c = recmatch(p, s, cs)) != 0)
+ if ((c = recmatch(p, s, ci)) != 0)
return c;
/* end of pattern: matched if at end of string, else continue */
if (*p == 0)
return (*s == 0);
/* continue to match if at DIRSEP_CHR in pattern, else give up */
return (*p == DIRSEP_CHR || (*p == '\\' && p[1] == DIRSEP_CHR))
- ? recmatch(p, s, cs) : 2;
+ ? recmatch(p, s, ci) : 2;
}
/* Two consecutive WILDCHR_MULTI ("**"): this matches DIRSEP_CHR ('/') */
p++; /* move p past the second WILDCHR_MULTI */
@@ -308,17 +308,17 @@ int cs; /* flag: force case-sensitive matching */
*/
if (q != srest)
return 0;
- return ((cs ? strcmp(p, q) : namecmp(p, q)) == 0);
+ return ((!ci ? strcmp(p, q) : namecmp(p, q)) == 0);
}
#else /* !_MBCS */
- return ((cs ? strcmp(p, srest) : namecmp(p, srest)) == 0);
+ return ((!ci ? strcmp(p, srest) : namecmp(p, srest)) == 0);
#endif /* ?_MBCS */
}
else
{
/* pattern contains more wildcards, continue with recursion... */
for (; *s; INCSTR(s))
- if ((c = recmatch(p, s, cs)) != 0)
+ if ((c = recmatch(p, s, ci)) != 0)
return c;
return 2; /* 2 means give up--shmatch will return false */
}
@@ -353,17 +353,17 @@ int cs; /* flag: force case-sensitive matching */
c = *(p-1);
else
{
- uch cc = (cs ? (uch)*s : case_map((uch)*s));
+ uch cc = (!ci ? (uch)*s : to_up((uch)*s));
uch uc = (uch) c;
if (*(p+1) != '-')
for (uc = uc ? uc : (uch)*p; uc <= (uch)*p; uc++)
/* compare range */
- if ((cs ? uc : case_map(uc)) == cc)
- return r ? 0 : recmatch(q + CLEN(q), s + CLEN(s), cs);
+ if ((!ci ? uc : to_up(uc)) == cc)
+ return r ? 0 : recmatch(q + CLEN(q), s + CLEN(s), ci);
c = e = 0; /* clear range, escape flags */
}
}
- return r ? recmatch(q + CLEN(q), s + CLEN(s), cs) : 0;
+ return r ? recmatch(q + CLEN(q), s + CLEN(s), ci) : 0;
/* bracket match failed */
}
#endif /* !VMS */
@@ -382,18 +382,18 @@ int cs; /* flag: force case-sensitive matching */
{
/* Match "...]" with "]". Continue after "]" in both. */
if ((*(p+ 2* CLEN( p)) == ']') && (*s == ']'))
- return recmatch( (p+ 3* CLEN( p)), (s+ CLEN( s)), cs);
+ return recmatch( (p+ 3* CLEN( p)), (s+ CLEN( s)), ci);
/* Else, look for a reduced match in s, until "]" in or end of s. */
for (; *s && (*s != ']'); INCSTR(s))
if (*s == '.')
/* If reduced match, then continue after "..." in p, "." in s. */
- if ((c = recmatch( (p+ CLEN( p)), s, cs)) != 0)
+ if ((c = recmatch( (p+ CLEN( p)), s, ci)) != 0)
return (int)c;
/* Match "...]" with "]". Continue after "]" in both. */
if ((*(p+ 2* CLEN( p)) == ']') && (*s == ']'))
- return recmatch( (p+ 3* CLEN( p)), (s+ CLEN( s)), cs);
+ return recmatch( (p+ 3* CLEN( p)), (s+ CLEN( s)), ci);
/* No reduced match. Quit. */
return 2;
@@ -402,8 +402,8 @@ int cs; /* flag: force case-sensitive matching */
#endif /* def VMS */
/* Just a character--compare it */
- return (cs ? c == *s : case_map((uch)c) == case_map((uch)*s)) ?
- recmatch(p, s + CLEN(s), cs) : 0;
+ return (!ci ? c == *s : to_up((uch)c) == to_up((uch)*s)) ?
+ recmatch(p, s + CLEN(s), ci) : 0;
}

View File

@ -0,0 +1,176 @@
diff -up unzip60/extract.c.close unzip60/extract.c
--- unzip60/extract.c.close 2009-03-14 02:32:52.000000000 +0100
+++ unzip60/extract.c 2009-11-19 08:17:23.481263496 +0100
@@ -1924,24 +1924,21 @@ static int extract_or_test_member(__G)
#ifdef VMS /* VMS: required even for stdout! (final flush) */
if (!uO.tflag) /* don't close NULL file */
- close_outfile(__G);
+ error = close_outfile(__G);
#else
#ifdef DLL
if (!uO.tflag && (!uO.cflag || G.redirect_data)) {
if (G.redirect_data)
FINISH_REDIRECT();
else
- close_outfile(__G);
+ error = close_outfile(__G);
}
#else
if (!uO.tflag && !uO.cflag) /* don't close NULL file or stdout */
- close_outfile(__G);
+ error = close_outfile(__G);
#endif
#endif /* VMS */
- /* GRR: CONVERT close_outfile() TO NON-VOID: CHECK FOR ERRORS! */
-
-
if (G.disk_full) { /* set by flush() */
if (G.disk_full > 1) {
#if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK))
diff -up unzip60/unix/unix.c.close unzip60/unix/unix.c
--- unzip60/unix/unix.c.close 2009-01-24 00:31:26.000000000 +0100
+++ unzip60/unix/unix.c 2009-11-19 08:33:25.568389171 +0100
@@ -1096,10 +1096,41 @@ static int get_extattribs(__G__ pzt, z_u
#ifndef MTS
/****************************/
+/* Function CloseError() */
+/***************************/
+
+int CloseError(__G)
+ __GDEF
+{
+ int errval = PK_OK;
+
+ if (fclose(G.outfile) < 0) {
+ switch (errno) {
+ case ENOSPC:
+ /* Do we need this on fileio.c? */
+ Info(slide, 0x4a1, ((char *)slide, "%s: write error (disk full?). Continue? (y/n/^C) ",
+ FnFilter1(G.filename)));
+ fgets(G.answerbuf, 9, stdin);
+ if (*G.answerbuf == 'y') /* stop writing to this file */
+ G.disk_full = 1; /* pass to next */
+ else
+ G.disk_full = 2; /* no: exit program */
+
+ errval = PK_DISK;
+ break;
+
+ default:
+ errval = PK_WARN;
+ }
+ }
+ return errval;
+} /* End of CloseError() */
+
+/****************************/
/* Function close_outfile() */
/****************************/
-void close_outfile(__G) /* GRR: change to return PK-style warning level */
+int close_outfile(__G)
__GDEF
{
union {
@@ -1108,6 +1139,7 @@ void close_outfile(__G) /* GRR: chang
} zt;
ulg z_uidgid[2];
int have_uidgid_flg;
+ int errval = PK_OK;
have_uidgid_flg = get_extattribs(__G__ &(zt.t3), z_uidgid);
@@ -1141,16 +1173,16 @@ void close_outfile(__G) /* GRR: chang
Info(slide, 0x201, ((char *)slide,
"warning: symbolic link (%s) failed: mem alloc overflow\n",
FnFilter1(G.filename)));
- fclose(G.outfile);
- return;
+ errval = CloseError(G.outfile, G.filename);
+ return errval ? errval : PK_WARN;
}
if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) {
Info(slide, 0x201, ((char *)slide,
"warning: symbolic link (%s) failed: no mem\n",
FnFilter1(G.filename)));
- fclose(G.outfile);
- return;
+ errval = CloseError(G.outfile, G.filename);
+ return errval ? errval : PK_WARN;
}
slnk_entry->next = NULL;
slnk_entry->targetlen = ucsize;
@@ -1174,10 +1206,10 @@ void close_outfile(__G) /* GRR: chang
"warning: symbolic link (%s) failed\n",
FnFilter1(G.filename)));
free(slnk_entry);
- fclose(G.outfile);
- return;
+ errval = CloseError(G.outfile, G.filename);
+ return errval ? errval : PK_WARN;
}
- fclose(G.outfile); /* close "link" file for good... */
+ errval = CloseError(G.outfile, G.filename); /* close "link" file for good... */
slnk_entry->target[ucsize] = '\0';
if (QCOND2)
Info(slide, 0, ((char *)slide, "-> %s ",
@@ -1188,7 +1220,7 @@ void close_outfile(__G) /* GRR: chang
else
G.slink_head = slnk_entry;
G.slink_last = slnk_entry;
- return;
+ return errval;
}
#endif /* SYMLINKS */
@@ -1201,7 +1233,7 @@ void close_outfile(__G) /* GRR: chang
#endif
#if (defined(NO_FCHOWN))
- fclose(G.outfile);
+ errval = CloseError(G.outfile, G.filename);
#endif
/* if -X option was specified and we have UID/GID info, restore it */
@@ -1227,7 +1259,7 @@ void close_outfile(__G) /* GRR: chang
}
#if (!defined(NO_FCHOWN) && defined(NO_FCHMOD))
- fclose(G.outfile);
+ errval = CloseError(G.outfile, G.filename);
#endif
#if (!defined(NO_FCHOWN) && !defined(NO_FCHMOD))
@@ -1239,7 +1271,7 @@ void close_outfile(__G) /* GRR: chang
if (fchmod(fileno(G.outfile), filtattr(__G__ G.pInfo->file_attr)))
perror("fchmod (file attributes) error");
- fclose(G.outfile);
+ errval = CloseError(G.outfile, G.filename);
#endif /* !NO_FCHOWN && !NO_FCHMOD */
/* skip restoring time stamps on user's request */
@@ -1267,6 +1299,7 @@ void close_outfile(__G) /* GRR: chang
#endif
#endif /* NO_FCHOWN || NO_FCHMOD */
+ return errval;
} /* end function close_outfile() */
#endif /* !MTS */
diff -up unzip60/unzpriv.h.close unzip60/unzpriv.h
--- unzip60/unzpriv.h.close 2009-04-20 01:59:26.000000000 +0200
+++ unzip60/unzpriv.h 2009-11-19 08:19:08.610388618 +0100
@@ -2604,7 +2604,7 @@ char *GetLoadPath OF((__GPRO));
int SetFileSize OF((FILE *file, zusz_t filesize)); /* local */
#endif
#ifndef MTS /* macro in MTS */
- void close_outfile OF((__GPRO)); /* local */
+ int close_outfile OF((__GPRO)); /* local */
#endif
#ifdef SET_SYMLINK_ATTRIBS
int set_symlnk_attribs OF((__GPRO__ slinkentry *slnk_entry)); /* local */

View File

@ -0,0 +1,12 @@
diff -up unzip60/unix/configure.nostrip unzip60/unix/configure
--- unzip60/unix/configure.nostrip 2009-11-30 10:18:09.000000000 +0100
+++ unzip60/unix/configure 2009-11-30 10:21:08.354264213 +0100
@@ -17,7 +17,7 @@ CFLAGSR=${CFLAGS}
IZ_BZIP2=${3}
CFLAGS="${CFLAGS} -I. -DUNIX"
LFLAGS1=""
-LFLAGS2="-s"
+LFLAGS2="${LFLAGS2}"
LN="ln -s"
CFLAGS_OPT=''

View File

@ -0,0 +1,79 @@
diff --git a/extract.c b/extract.c
index 9ef80b3..c741b5f 100644
--- a/extract.c
+++ b/extract.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
+ Copyright (c) 1990-2014 Info-ZIP. All rights reserved.
See the accompanying file LICENSE, version 2009-Jan-02 or later
(the contents of which are also included in unzip.h) for terms of use.
@@ -298,6 +298,8 @@ char ZCONST Far TruncNTSD[] =
#ifndef SFX
static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \
EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n";
+ static ZCONST char Far TooSmallEBlength[] = "bad extra-field entry:\n \
+ EF block length (%u bytes) invalid (< %d)\n";
static ZCONST char Far InvalidComprDataEAs[] =
" invalid compressed data for EAs\n";
# if (defined(WIN32) && defined(NTSD_EAS))
@@ -2020,7 +2022,8 @@ static int TestExtraField(__G__ ef, ef_len)
ebID = makeword(ef);
ebLen = (unsigned)makeword(ef+EB_LEN);
- if (ebLen > (ef_len - EB_HEADSIZE)) {
+ if (ebLen > (ef_len - EB_HEADSIZE))
+ {
/* Discovered some extra field inconsistency! */
if (uO.qflag)
Info(slide, 1, ((char *)slide, "%-22s ",
@@ -2155,11 +2158,29 @@ static int TestExtraField(__G__ ef, ef_len)
}
break;
case EF_PKVMS:
- if (makelong(ef+EB_HEADSIZE) !=
- crc32(CRCVAL_INITIAL, ef+(EB_HEADSIZE+4),
- (extent)(ebLen-4)))
- Info(slide, 1, ((char *)slide,
- LoadFarString(BadCRC_EAs)));
+ /* 2015-01-30 SMS. Added sufficient-bytes test/message
+ * here. (Removed defective ebLen test above.)
+ *
+ * If sufficient bytes (EB_PKVMS_MINLEN) are available,
+ * then compare the stored CRC value with the calculated
+ * CRC for the remainder of the data (and complain about
+ * a mismatch).
+ */
+ if (ebLen < EB_PKVMS_MINLEN)
+ {
+ /* Insufficient bytes available. */
+ Info( slide, 1,
+ ((char *)slide, LoadFarString( TooSmallEBlength),
+ ebLen, EB_PKVMS_MINLEN));
+ }
+ else if (makelong(ef+ EB_HEADSIZE) !=
+ crc32(CRCVAL_INITIAL,
+ (ef+ EB_HEADSIZE+ EB_PKVMS_MINLEN),
+ (extent)(ebLen- EB_PKVMS_MINLEN)))
+ {
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(BadCRC_EAs)));
+ }
break;
case EF_PKW32:
case EF_PKUNIX:
diff --git a/unzpriv.h b/unzpriv.h
index 005cee0..5c83a6e 100644
--- a/unzpriv.h
+++ b/unzpriv.h
@@ -1806,6 +1806,8 @@
#define EB_NTSD_VERSION 4 /* offset of NTSD version byte */
#define EB_NTSD_MAX_VER (0) /* maximum version # we know how to handle */
+#define EB_PKVMS_MINLEN 4 /* minimum data length of PKVMS extra block */
+
#define EB_ASI_CRC32 0 /* offset of ASI Unix field's crc32 checksum */
#define EB_ASI_MODE 4 /* offset of ASI Unix permission mode field */

View File

@ -0,0 +1,25 @@
diff --git a/extract.c b/extract.c
index c741b5f..e4a4c7b 100644
--- a/extract.c
+++ b/extract.c
@@ -2240,10 +2240,17 @@ static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)
if (compr_offset < 4) /* field is not compressed: */
return PK_OK; /* do nothing and signal OK */
+ /* Return no/bad-data error status if any problem is found:
+ * 1. eb_size is too small to hold the uncompressed size
+ * (eb_ucsize). (Else extract eb_ucsize.)
+ * 2. eb_ucsize is zero (invalid). 2014-12-04 SMS.
+ * 3. eb_ucsize is positive, but eb_size is too small to hold
+ * the compressed data header.
+ */
if ((eb_size < (EB_UCSIZE_P + 4)) ||
- ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L &&
- eb_size <= (compr_offset + EB_CMPRHEADLEN)))
- return IZ_EF_TRUNC; /* no compressed data! */
+ ((eb_ucsize = makelong( eb+ (EB_HEADSIZE+ EB_UCSIZE_P))) == 0L) ||
+ ((eb_ucsize > 0L) && (eb_size <= (compr_offset + EB_CMPRHEADLEN))))
+ return IZ_EF_TRUNC; /* no/bad compressed data! */
method = makeword(eb + (EB_HEADSIZE + compr_offset));
if ((method == STORED) && (eb_size != compr_offset + EB_CMPRHEADLEN + eb_ucsize))

View File

@ -0,0 +1,138 @@
diff --git a/fileio.c b/fileio.c
index 03fc4be..2a61a30 100644
--- a/fileio.c
+++ b/fileio.c
@@ -176,6 +176,8 @@ static ZCONST char Far FilenameTooLongTrunc[] =
#endif
static ZCONST char Far ExtraFieldTooLong[] =
"warning: extra field too long (%d). Ignoring...\n";
+static ZCONST char Far ExtraFieldCorrupt[] =
+ "warning: extra field (type: 0x%04x) corrupt. Continuing...\n";
#ifdef WINDLL
static ZCONST char Far DiskFullQuery[] =
@@ -2300,7 +2302,13 @@ int do_string(__G__ length, option) /* return PK-type error code */
length = length2;
}
/* Looks like here is where extra fields are read */
- getZip64Data(__G__ G.extra_field, length);
+ if (getZip64Data(__G__ G.extra_field, length) != PK_COOL)
+ {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString( ExtraFieldCorrupt), EF_PKSZ64));
+ error = PK_WARN;
+ }
+
#ifdef UNICODE_SUPPORT
G.unipath_filename = NULL;
if (G.UzO.U_flag < 2) {
diff --git a/process.c b/process.c
index be6e006..0d57ab4 100644
--- a/process.c
+++ b/process.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
+ Copyright (c) 1990-2014 Info-ZIP. All rights reserved.
See the accompanying file LICENSE, version 2009-Jan-02 or later
(the contents of which are also included in unzip.h) for terms of use.
@@ -1894,48 +1894,83 @@ int getZip64Data(__G__ ef_buf, ef_len)
and a 4-byte version of disk start number.
Sets both local header and central header fields. Not terribly clever,
but it means that this procedure is only called in one place.
+
+ 2014-12-05 SMS.
+ Added checks to ensure that enough data are available before calling
+ makeint64() or makelong(). Replaced various sizeof() values with
+ simple ("4" or "8") constants. (The Zip64 structures do not depend
+ on our variable sizes.) Error handling is crude, but we should now
+ stay within the buffer.
---------------------------------------------------------------------------*/
+#define Z64FLGS 0xffff
+#define Z64FLGL 0xffffffff
+
if (ef_len == 0 || ef_buf == NULL)
return PK_COOL;
Trace((stderr,"\ngetZip64Data: scanning extra field of length %u\n",
ef_len));
- while (ef_len >= EB_HEADSIZE) {
+ while (ef_len >= EB_HEADSIZE)
+ {
eb_id = makeword(EB_ID + ef_buf);
eb_len = makeword(EB_LEN + ef_buf);
- if (eb_len > (ef_len - EB_HEADSIZE)) {
- /* discovered some extra field inconsistency! */
+ if (eb_len > (ef_len - EB_HEADSIZE))
+ {
+ /* Extra block length exceeds remaining extra field length. */
Trace((stderr,
"getZip64Data: block length %u > rest ef_size %u\n", eb_len,
ef_len - EB_HEADSIZE));
break;
}
- if (eb_id == EF_PKSZ64) {
+ if (eb_id == EF_PKSZ64)
+ {
int offset = EB_HEADSIZE;
- if (G.crec.ucsize == 0xffffffff || G.lrec.ucsize == 0xffffffff){
- G.lrec.ucsize = G.crec.ucsize = makeint64(offset + ef_buf);
- offset += sizeof(G.crec.ucsize);
+ if ((G.crec.ucsize == Z64FLGL) || (G.lrec.ucsize == Z64FLGL))
+ {
+ if (offset+ 8 > ef_len)
+ return PK_ERR;
+
+ G.crec.ucsize = G.lrec.ucsize = makeint64(offset + ef_buf);
+ offset += 8;
}
- if (G.crec.csize == 0xffffffff || G.lrec.csize == 0xffffffff){
- G.csize = G.lrec.csize = G.crec.csize = makeint64(offset + ef_buf);
- offset += sizeof(G.crec.csize);
+
+ if ((G.crec.csize == Z64FLGL) || (G.lrec.csize == Z64FLGL))
+ {
+ if (offset+ 8 > ef_len)
+ return PK_ERR;
+
+ G.csize = G.crec.csize = G.lrec.csize = makeint64(offset + ef_buf);
+ offset += 8;
}
- if (G.crec.relative_offset_local_header == 0xffffffff){
+
+ if (G.crec.relative_offset_local_header == Z64FLGL)
+ {
+ if (offset+ 8 > ef_len)
+ return PK_ERR;
+
G.crec.relative_offset_local_header = makeint64(offset + ef_buf);
- offset += sizeof(G.crec.relative_offset_local_header);
+ offset += 8;
}
- if (G.crec.disk_number_start == 0xffff){
+
+ if (G.crec.disk_number_start == Z64FLGS)
+ {
+ if (offset+ 4 > ef_len)
+ return PK_ERR;
+
G.crec.disk_number_start = (zuvl_t)makelong(offset + ef_buf);
- offset += sizeof(G.crec.disk_number_start);
+ offset += 4;
}
+#if 0
+ break; /* Expect only one EF_PKSZ64 block. */
+#endif /* 0 */
}
- /* Skip this extra field block */
+ /* Skip this extra field block. */
ef_buf += (eb_len + EB_HEADSIZE);
ef_len -= (eb_len + EB_HEADSIZE);
}

View File

@ -0,0 +1,34 @@
--- a/fileio.c 2014-12-05 05:06:05 -0600
+++ b/fileio.c 2017-11-14 01:06:28 -0600
@@ -1,5 +1,5 @@
/*
- Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
+ Copyright (c) 1990-2017 Info-ZIP. All rights reserved.
See the accompanying file LICENSE, version 2009-Jan-02 or later
(the contents of which are also included in unzip.h) for terms of use.
@@ -1582,6 +1582,8 @@
int r = IZ_PW_ENTERED;
char *m;
char *prompt;
+ char *ep;
+ char *zp;
#ifndef REENTRANT
/* tell picky compilers to shut up about "unused variable" warnings */
@@ -1590,9 +1592,12 @@
if (*rcnt == 0) { /* First call for current entry */
*rcnt = 2;
- if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) {
- sprintf(prompt, LoadFarString(PasswPrompt),
- FnFilter1(zfn), FnFilter2(efn));
+ zp = FnFilter1( zfn);
+ ep = FnFilter2( efn);
+ prompt = (char *)malloc( /* Slightly too long (2* "%s"). */
+ sizeof( PasswPrompt)+ strlen( zp)+ strlen( ep));
+ if (prompt != (char *)NULL) {
+ sprintf(prompt, LoadFarString(PasswPrompt), zp, ep);
m = prompt;
} else
m = (char *)LoadFarString(PasswPrompt2);

View File

@ -0,0 +1,35 @@
--- unzip60/list.c
+++ unzip60/list.c
@@ -97,7 +97,7 @@ int list_files(__G) /* return PK-type
{
int do_this_file=FALSE, cfactor, error, error_in_archive=PK_COOL;
#ifndef WINDLL
- char sgn, cfactorstr[13];
+ char sgn, cfactorstr[1+10+1+1]; /* <sgn><int>%NUL */
int longhdr=(uO.vflag>1);
#endif
int date_format;
@@ -389,9 +389,9 @@ int list_files(__G) /* return PK-type
}
#else /* !WINDLL */
if (cfactor == 100)
- sprintf(cfactorstr, LoadFarString(CompFactor100));
+ snprintf(cfactorstr, sizeof(cfactorstr), LoadFarString(CompFactor100));
else
- sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
+ snprintf(cfactorstr, sizeof(cfactorstr), LoadFarString(CompFactorStr), sgn, cfactor);
if (longhdr)
Info(slide, 0, ((char *)slide, LoadFarString(LongHdrStats),
FmZofft(G.crec.ucsize, "8", "u"), methbuf,
@@ -471,9 +471,9 @@ int list_files(__G) /* return PK-type
#else /* !WINDLL */
if (cfactor == 100)
- sprintf(cfactorstr, LoadFarString(CompFactor100));
+ snprintf(cfactorstr, sizeof(cfactorstr), LoadFarString(CompFactor100));
else
- sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
+ snprintf(cfactorstr, sizeof(cfactorstr), LoadFarString(CompFactorStr), sgn, cfactor);
if (longhdr) {
Info(slide, 0, ((char *)slide, LoadFarString(LongFileTrailer),
FmZofft(tot_ucsize, "8", "u"), FmZofft(tot_csize, "8", "u"),

View File

@ -0,0 +1,10 @@
diff -up unzip60/crc_i386.S.exec-shield unzip60/crc_i386.S
--- unzip60/crc_i386.S.exec-shield 2007-01-07 06:02:58.000000000 +0100
+++ unzip60/crc_i386.S 2009-11-18 11:16:39.630389312 +0100
@@ -302,3 +302,6 @@ _crc32: /* ulg c
#endif /* i386 || _i386 || _I386 || __i386 */
#endif /* !USE_ZLIB && !CRC_TABLE_ONLY */
+
+.section .note.GNU-stack, "", @progbits
+.previous

View File

@ -0,0 +1,477 @@
diff -up unzip60/match.c.recmatch unzip60/match.c
--- unzip60/match.c.recmatch 2005-08-14 13:00:36.000000000 -0400
+++ unzip60/match.c 2013-05-28 10:29:57.949077543 -0400
@@ -27,16 +27,14 @@
---------------------------------------------------------------------------
- Copyright on recmatch() from Zip's util.c (although recmatch() was almost
- certainly written by Mark Adler...ask me how I can tell :-) ):
+ Copyright on recmatch() from Zip's util.c
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
- Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly,
- Kai Uwe Rommel and Igor Mandrichenko.
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
- Permission is granted to any individual or institution to use, copy,
- or redistribute this software so long as all of the original files are
- included unmodified, that it is not sold for profit, and that this copy-
- right notice is retained.
---------------------------------------------------------------------------
@@ -53,7 +51,7 @@
A set is composed of characters or ranges; a range looks like ``character
hyphen character'' (as in 0-9 or A-Z). [0-9a-zA-Z_] is the minimal set of
- characters allowed in the [..] pattern construct. Other characters are
+ characters ALlowed in the [..] pattern construct. Other characters are
allowed (i.e., 8-bit characters) if your system will support them.
To suppress the special syntactic significance of any of ``[]*?!^-\'', in-
@@ -101,8 +99,32 @@
# define WILDCHAR '?'
# define BEG_RANGE '['
# define END_RANGE ']'
+# define WILDCHR_SINGLE '?'
+# define DIRSEP_CHR '/'
+# define WILDCHR_MULTI '*'
#endif
+#ifdef WILD_STOP_AT_DIR
+ int wild_stop_at_dir = 1; /* default wildcards do not include / in matches */
+#else
+ int wild_stop_at_dir = 0; /* default wildcards do include / in matches */
+#endif
+
+
+
+/*
+ * case mapping functions. case_map is used to ignore case in comparisons,
+ * to_up is used to force upper case even on Unix (for dosify option).
+ */
+#ifdef USE_CASE_MAP
+# define case_map(c) upper[(c) & 0xff]
+# define to_up(c) upper[(c) & 0xff]
+#else
+# define case_map(c) (c)
+# define to_up(c) ((c) >= 'a' && (c) <= 'z' ? (c)-'a'+'A' : (c))
+#endif /* USE_CASE_MAP */
+
+
#if 0 /* GRR: add this to unzip.h someday... */
#if !(defined(MSDOS) && defined(DOSWILD))
#ifdef WILD_STOP_AT_DIR
@@ -114,8 +136,8 @@ int recmatch OF((ZCONST uch *pattern, ZC
int ignore_case __WDLPRO));
#endif
#endif /* 0 */
-static int recmatch OF((ZCONST uch *pattern, ZCONST uch *string,
- int ignore_case __WDLPRO));
+static int recmatch OF((ZCONST char *, ZCONST char *,
+ int));
static char *isshexp OF((ZCONST char *p));
static int namecmp OF((ZCONST char *s1, ZCONST char *s2));
@@ -154,192 +176,240 @@ int match(string, pattern, ignore_case _
}
dospattern[j-1] = '\0'; /* nuke the end "." */
}
- j = recmatch((uch *)dospattern, (uch *)string, ignore_case __WDL);
+ j = recmatch(dospattern, string, ignore_case);
free(dospattern);
return j == 1;
} else
#endif /* MSDOS && DOSWILD */
- return recmatch((uch *)pattern, (uch *)string, ignore_case __WDL) == 1;
+ return recmatch(pattern, string, ignore_case) == 1;
}
+#ifdef _MBCS
+
+char *___tmp_ptr;
+#endif
-static int recmatch(p, s, ic __WDL)
- ZCONST uch *p; /* sh pattern to match */
- ZCONST uch *s; /* string to which to match it */
- int ic; /* true for case insensitivity */
- __WDLDEF /* directory sepchar for WildStopAtDir mode, or 0 */
+static int recmatch(p, s, cs)
+ZCONST char *p; /* sh pattern to match */
+ZCONST char *s; /* string to match it to */
+int cs; /* flag: force case-sensitive matching */
/* Recursively compare the sh pattern p with the string s and return 1 if
- * they match, and 0 or 2 if they don't or if there is a syntax error in the
- * pattern. This routine recurses on itself no more deeply than the number
- * of characters in the pattern. */
+ they match, and 0 or 2 if they don't or if there is a syntax error in the
+ pattern. This routine recurses on itself no deeper than the number of
+ characters in the pattern. */
{
- unsigned int c; /* pattern char or start of range in [-] loop */
+ int c; /* pattern char or start of range in [-] loop */
+ /* Get first character, the pattern for new recmatch calls follows */
+ /* borrowed from Zip's global.c */
+ int no_wild = 0;
+ int allow_regex=1;
+ /* This fix provided by akt@m5.dion.ne.jp for Japanese.
+ See 21 July 2006 mail.
+ It only applies when p is pointing to a doublebyte character and
+ things like / and wildcards are not doublebyte. This probably
+ should not be needed. */
- /* Get first character, the pattern for new recmatch calls follows */
- c = *p; INCSTR(p);
+#ifdef _MBCS
+ if (CLEN(p) == 2) {
+ if (CLEN(s) == 2) {
+ return (*p == *s && *(p+1) == *(s+1)) ?
+ recmatch(p + 2, s + 2, cs) : 0;
+ } else {
+ return 0;
+ }
+ }
+#endif /* ?_MBCS */
- /* If that was the end of the pattern, match if string empty too */
- if (c == 0)
- return *s == 0;
+ c = *POSTINCSTR(p);
- /* '?' (or '%') matches any character (but not an empty string). */
- if (c == WILDCHAR)
-#ifdef WILD_STOP_AT_DIR
- /* If uO.W_flag is non-zero, it won't match '/' */
- return (*s && (!sepc || *s != (uch)sepc))
- ? recmatch(p, s + CLEN(s), ic, sepc) : 0;
-#else
- return *s ? recmatch(p, s + CLEN(s), ic) : 0;
-#endif
+ /* If that was the end of the pattern, match if string empty too */
+ if (c == 0)
+ return *s == 0;
+
+ /* '?' (or '%' or '#') matches any character (but not an empty string) */
+ if (c == WILDCHR_SINGLE) {
+ if (wild_stop_at_dir)
+ return (*s && *s != DIRSEP_CHR) ? recmatch(p, s + CLEN(s), cs) : 0;
+ else
+ return *s ? recmatch(p, s + CLEN(s), cs) : 0;
+ }
- /* '*' matches any number of characters, including zero */
+ /* WILDCHR_MULTI ('*') matches any number of characters, including zero */
#ifdef AMIGA
- if (c == '#' && *p == '?') /* "#?" is Amiga-ese for "*" */
- c = '*', p++;
+ if (!no_wild && c == '#' && *p == '?') /* "#?" is Amiga-ese for "*" */
+ c = WILDCHR_MULTI, p++;
#endif /* AMIGA */
- if (c == '*') {
-#ifdef WILD_STOP_AT_DIR
- if (sepc) {
- /* check for single "*" or double "**" */
-# ifdef AMIGA
- if ((c = p[0]) == '#' && p[1] == '?') /* "#?" is Amiga-ese for "*" */
- c = '*', p++;
- if (c != '*') {
-# else /* !AMIGA */
- if (*p != '*') {
-# endif /* ?AMIGA */
- /* single "*": this doesn't match the dirsep character */
- for (; *s && *s != (uch)sepc; INCSTR(s))
- if ((c = recmatch(p, s, ic, sepc)) != 0)
- return (int)c;
- /* end of pattern: matched if at end of string, else continue */
- if (*p == '\0')
- return (*s == 0);
- /* continue to match if at sepc in pattern, else give up */
- return (*p == (uch)sepc || (*p == '\\' && p[1] == (uch)sepc))
- ? recmatch(p, s, ic, sepc) : 2;
- }
- /* "**": this matches slashes */
- ++p; /* move p behind the second '*' */
- /* and continue with the non-W_flag code variant */
- }
-#endif /* WILD_STOP_AT_DIR */
+ if (!no_wild && c == WILDCHR_MULTI)
+ {
+ if (wild_stop_at_dir) {
+ /* Check for an immediately following WILDCHR_MULTI */
+# ifdef AMIGA
+ if ((c = p[0]) == '#' && p[1] == '?') /* "#?" is Amiga-ese for "*" */
+ c = WILDCHR_MULTI, p++;
+ if (c != WILDCHR_MULTI) {
+# else /* !AMIGA */
+ if (*p != WILDCHR_MULTI) {
+# endif /* ?AMIGA */
+ /* Single WILDCHR_MULTI ('*'): this doesn't match slashes */
+ for (; *s && *s != DIRSEP_CHR; INCSTR(s))
+ if ((c = recmatch(p, s, cs)) != 0)
+ return c;
+ /* end of pattern: matched if at end of string, else continue */
if (*p == 0)
- return 1;
- if (isshexp((ZCONST char *)p) == NULL) {
- /* Optimization for rest of pattern being a literal string:
- * If there are no other shell expression chars in the rest
- * of the pattern behind the multi-char wildcard, then just
- * compare the literal string tail.
- */
- ZCONST uch *srest;
-
- srest = s + (strlen((ZCONST char *)s) - strlen((ZCONST char *)p));
- if (srest - s < 0)
- /* remaining literal string from pattern is longer than rest
- * of test string, there can't be a match
- */
- return 0;
- else
- /* compare the remaining literal pattern string with the last
- * bytes of the test string to check for a match
- */
+ return (*s == 0);
+ /* continue to match if at DIRSEP_CHR in pattern, else give up */
+ return (*p == DIRSEP_CHR || (*p == '\\' && p[1] == DIRSEP_CHR))
+ ? recmatch(p, s, cs) : 2;
+ }
+ /* Two consecutive WILDCHR_MULTI ("**"): this matches DIRSEP_CHR ('/') */
+ p++; /* move p past the second WILDCHR_MULTI */
+ /* continue with the normal non-WILD_STOP_AT_DIR code */
+ } /* wild_stop_at_dir */
+
+ /* Not wild_stop_at_dir */
+ if (*p == 0)
+ return 1;
+ if (!isshexp((char *)p))
+ {
+ /* optimization for rest of pattern being a literal string */
+
+ /* optimization to handle patterns like *.txt */
+ /* if the first char in the pattern is '*' and there */
+ /* are no other shell expression chars, i.e. a literal string */
+ /* then just compare the literal string at the end */
+
+ ZCONST char *srest;
+
+ srest = s + (strlen(s) - strlen(p));
+ if (srest - s < 0)
+ /* remaining literal string from pattern is longer than rest of
+ test string, there can't be a match
+ */
+ return 0;
+ else
+ /* compare the remaining literal pattern string with the last bytes
+ of the test string to check for a match */
#ifdef _MBCS
- {
- ZCONST uch *q = s;
+ {
+ ZCONST char *q = s;
- /* MBCS-aware code must not scan backwards into a string from
- * the end.
- * So, we have to move forward by character from our well-known
- * character position s in the test string until we have
- * advanced to the srest position.
- */
- while (q < srest)
- INCSTR(q);
- /* In case the byte *srest is a trailing byte of a multibyte
- * character in the test string s, we have actually advanced
- * past the position (srest).
- * For this case, the match has failed!
- */
- if (q != srest)
- return 0;
- return ((ic
- ? namecmp((ZCONST char *)p, (ZCONST char *)q)
- : strcmp((ZCONST char *)p, (ZCONST char *)q)
- ) == 0);
- }
+ /* MBCS-aware code must not scan backwards into a string from
+ * the end.
+ * So, we have to move forward by character from our well-known
+ * character position s in the test string until we have advanced
+ * to the srest position.
+ */
+ while (q < srest)
+ INCSTR(q);
+ /* In case the byte *srest is a trailing byte of a multibyte
+ * character, we have actually advanced past the position (srest).
+ * For this case, the match has failed!
+ */
+ if (q != srest)
+ return 0;
+ return ((cs ? strcmp(p, q) : namecmp(p, q)) == 0);
+ }
#else /* !_MBCS */
- return ((ic
- ? namecmp((ZCONST char *)p, (ZCONST char *)srest)
- : strcmp((ZCONST char *)p, (ZCONST char *)srest)
- ) == 0);
+ return ((cs ? strcmp(p, srest) : namecmp(p, srest)) == 0);
#endif /* ?_MBCS */
- } else {
- /* pattern contains more wildcards, continue with recursion... */
- for (; *s; INCSTR(s))
- if ((c = recmatch(p, s, ic __WDL)) != 0)
- return (int)c;
- return 2; /* 2 means give up--match will return false */
- }
}
-
- /* Parse and process the list of characters and ranges in brackets */
- if (c == BEG_RANGE) {
- int e; /* flag true if next char to be taken literally */
- ZCONST uch *q; /* pointer to end of [-] group */
- int r; /* flag true to match anything but the range */
-
- if (*s == 0) /* need a character to match */
- return 0;
- p += (r = (*p == '!' || *p == '^')); /* see if reverse */
- for (q = p, e = 0; *q; INCSTR(q)) /* find closing bracket */
- if (e)
- e = 0;
- else
- if (*q == '\\') /* GRR: change to ^ for MS-DOS, OS/2? */
- e = 1;
- else if (*q == END_RANGE)
- break;
- if (*q != END_RANGE) /* nothing matches if bad syntax */
- return 0;
- for (c = 0, e = (*p == '-'); p < q; INCSTR(p)) {
- /* go through the list */
- if (!e && *p == '\\') /* set escape flag if \ */
- e = 1;
- else if (!e && *p == '-') /* set start of range if - */
- c = *(p-1);
- else {
- unsigned int cc = Case(*s);
-
- if (*(p+1) != '-')
- for (c = c ? c : *p; c <= *p; c++) /* compare range */
- if ((unsigned)Case(c) == cc) /* typecast for MSC bug */
- return r ? 0 : recmatch(q + 1, s + 1, ic __WDL);
- c = e = 0; /* clear range, escape flags */
- }
- }
- return r ? recmatch(q + CLEN(q), s + CLEN(s), ic __WDL) : 0;
- /* bracket match failed */
+ else
+ {
+ /* pattern contains more wildcards, continue with recursion... */
+ for (; *s; INCSTR(s))
+ if ((c = recmatch(p, s, cs)) != 0)
+ return c;
+ return 2; /* 2 means give up--shmatch will return false */
}
+ }
- /* if escape ('\\'), just compare next character */
- if (c == '\\' && (c = *p++) == 0) /* if \ at end, then syntax error */
- return 0;
+#ifndef VMS /* No bracket matching in VMS */
+ /* Parse and process the list of characters and ranges in brackets */
+ if (!no_wild && allow_regex && c == '[')
+ {
+ int e; /* flag true if next char to be taken literally */
+ ZCONST char *q; /* pointer to end of [-] group */
+ int r; /* flag true to match anything but the range */
+
+ if (*s == 0) /* need a character to match */
+ return 0;
+ p += (r = (*p == '!' || *p == '^')); /* see if reverse */
+ for (q = p, e = 0; *q; q++) /* find closing bracket */
+ if (e)
+ e = 0;
+ else
+ if (*q == '\\')
+ e = 1;
+ else if (*q == ']')
+ break;
+ if (*q != ']') /* nothing matches if bad syntax */
+ return 0;
+ for (c = 0, e = *p == '-'; p < q; p++) /* go through the list */
+ {
+ if (e == 0 && *p == '\\') /* set escape flag if \ */
+ e = 1;
+ else if (e == 0 && *p == '-') /* set start of range if - */
+ c = *(p-1);
+ else
+ {
+ uch cc = (cs ? (uch)*s : case_map((uch)*s));
+ uch uc = (uch) c;
+ if (*(p+1) != '-')
+ for (uc = uc ? uc : (uch)*p; uc <= (uch)*p; uc++)
+ /* compare range */
+ if ((cs ? uc : case_map(uc)) == cc)
+ return r ? 0 : recmatch(q + CLEN(q), s + CLEN(s), cs);
+ c = e = 0; /* clear range, escape flags */
+ }
+ }
+ return r ? recmatch(q + CLEN(q), s + CLEN(s), cs) : 0;
+ /* bracket match failed */
+ }
+#endif /* !VMS */
- /* just a character--compare it */
-#ifdef QDOS
- return QMatch(Case((uch)c), Case(*s)) ?
- recmatch(p, s + CLEN(s), ic __WDL) : 0;
-#else
- return Case((uch)c) == Case(*s) ?
- recmatch(p, s + CLEN(s), ic __WDL) : 0;
-#endif
+ /* If escape ('\'), just compare next character */
+ if (!no_wild && c == '\\')
+ if ((c = *p++) == '\0') /* if \ at end, then syntax error */
+ return 0;
+
+#ifdef VMS
+ /* 2005-11-06 SMS.
+ Handle "..." wildcard in p with "." or "]" in s.
+ */
+ if ((c == '.') && (*p == '.') && (*(p+ CLEN( p)) == '.') &&
+ ((*s == '.') || (*s == ']')))
+ {
+ /* Match "...]" with "]". Continue after "]" in both. */
+ if ((*(p+ 2* CLEN( p)) == ']') && (*s == ']'))
+ return recmatch( (p+ 3* CLEN( p)), (s+ CLEN( s)), cs);
+
+ /* Else, look for a reduced match in s, until "]" in or end of s. */
+ for (; *s && (*s != ']'); INCSTR(s))
+ if (*s == '.')
+ /* If reduced match, then continue after "..." in p, "." in s. */
+ if ((c = recmatch( (p+ CLEN( p)), s, cs)) != 0)
+ return (int)c;
+
+ /* Match "...]" with "]". Continue after "]" in both. */
+ if ((*(p+ 2* CLEN( p)) == ']') && (*s == ']'))
+ return recmatch( (p+ 3* CLEN( p)), (s+ CLEN( s)), cs);
+
+ /* No reduced match. Quit. */
+ return 2;
+ }
+
+#endif /* def VMS */
+
+ /* Just a character--compare it */
+ return (cs ? c == *s : case_map((uch)c) == case_map((uch)*s)) ?
+ recmatch(p, s + CLEN(s), cs) : 0;
+}
-} /* end function recmatch() */
+/*************************************************************************************************/
static char *isshexp(p)
ZCONST char *p;
/* If p is a sh expression, a pointer to the first special character is

View File

@ -0,0 +1,90 @@
diff --git a/extract.c b/extract.c
index eeb2f57..a0a4929 100644
--- a/extract.c
+++ b/extract.c
@@ -472,8 +472,8 @@ int extract_or_test_files(__G) /* return PK-type error code */
*/
Info(slide, 0x401, ((char *)slide,
LoadFarString(CentSigMsg), j + blknum*DIR_BLKSIZ + 1));
- Info(slide, 0x401, ((char *)slide,
- LoadFarString(ReportMsg)));
+ Info(slide, 0x401,
+ ((char *)slide,"%s", LoadFarString(ReportMsg)));
error_in_archive = PK_BADERR;
}
reached_end = TRUE; /* ...so no more left to do */
@@ -752,8 +752,8 @@ int extract_or_test_files(__G) /* return PK-type error code */
#ifndef SFX
if (no_endsig_found) { /* just to make sure */
- Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
- Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
+ Info(slide, 0x401, ((char *)slide,"%s", LoadFarString(EndSigMsg)));
+ Info(slide, 0x401, ((char *)slide,"%s", LoadFarString(ReportMsg)));
if (!error_in_archive) /* don't overwrite stronger error */
error_in_archive = PK_WARN;
}
diff --git a/list.c b/list.c
index 15e0011..f7359c3 100644
--- a/list.c
+++ b/list.c
@@ -181,7 +181,7 @@ int list_files(__G) /* return PK-type error code */
Info(slide, 0x401,
((char *)slide, LoadFarString(CentSigMsg), j));
Info(slide, 0x401,
- ((char *)slide, LoadFarString(ReportMsg)));
+ ((char *)slide,"%s", LoadFarString(ReportMsg)));
return PK_BADERR; /* sig not found */
}
}
@@ -507,7 +507,8 @@ int list_files(__G) /* return PK-type error code */
&& (!G.ecrec.is_zip64_archive)
&& (memcmp(G.sig, end_central_sig, 4) != 0)
) { /* just to make sure again */
- Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
+ Info(slide, 0x401,
+ ((char *)slide,"%s", LoadFarString(EndSigMsg)));
error_in_archive = PK_WARN; /* didn't find sig */
}
@@ -591,7 +592,7 @@ int get_time_stamp(__G__ last_modtime, nmember) /* return PK-type error code */
Info(slide, 0x401,
((char *)slide, LoadFarString(CentSigMsg), j));
Info(slide, 0x401,
- ((char *)slide, LoadFarString(ReportMsg)));
+ ((char *)slide,"%s", LoadFarString(ReportMsg)));
return PK_BADERR; /* sig not found */
}
}
@@ -674,7 +675,7 @@ int get_time_stamp(__G__ last_modtime, nmember) /* return PK-type error code */
---------------------------------------------------------------------------*/
if (memcmp(G.sig, end_central_sig, 4)) { /* just to make sure again */
- Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
+ Info(slide, 0x401, ((char *)slide,"%s", LoadFarString(EndSigMsg)));
error_in_archive = PK_WARN;
}
if (*nmember == 0L && error_in_archive <= PK_WARN)
diff --git a/zipinfo.c b/zipinfo.c
index 6e22cc8..ac5c61b 100644
--- a/zipinfo.c
+++ b/zipinfo.c
@@ -771,7 +771,7 @@ int zipinfo(__G) /* return PK-type error code */
Info(slide, 0x401,
((char *)slide, LoadFarString(CentSigMsg), j));
Info(slide, 0x401,
- ((char *)slide, LoadFarString(ReportMsg)));
+ ((char *)slide,"%s", LoadFarString(ReportMsg)));
error_in_archive = PK_BADERR; /* sig not found */
break;
}
@@ -960,7 +960,8 @@ int zipinfo(__G) /* return PK-type error code */
&& (!G.ecrec.is_zip64_archive)
&& (memcmp(G.sig, end_central_sig, 4) != 0)
) { /* just to make sure again */
- Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
+ Info(slide, 0x401,
+ ((char *)slide,"%s", LoadFarString(EndSigMsg)));
error_in_archive = PK_WARN; /* didn't find sig */
}

View File

@ -0,0 +1,104 @@
From bdd4a0cecd745cb4825e4508b5bdf2579731086a Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Mon, 14 Sep 2015 18:23:17 +0200
Subject: [PATCH 1/3] upstream fix for heap overflow
https://bugzilla.redhat.com/attachment.cgi?id=1073002
---
crypt.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/crypt.c b/crypt.c
index 784e411..a8975f2 100644
--- a/crypt.c
+++ b/crypt.c
@@ -465,7 +465,17 @@ int decrypt(__G__ passwrd)
GLOBAL(pInfo->encrypted) = FALSE;
defer_leftover_input(__G);
for (n = 0; n < RAND_HEAD_LEN; n++) {
- b = NEXTBYTE;
+ /* 2012-11-23 SMS. (OUSPG report.)
+ * Quit early if compressed size < HEAD_LEN. The resulting
+ * error message ("unable to get password") could be improved,
+ * but it's better than trying to read nonexistent data, and
+ * then continuing with a negative G.csize. (See
+ * fileio.c:readbyte()).
+ */
+ if ((b = NEXTBYTE) == (ush)EOF)
+ {
+ return PK_ERR;
+ }
h[n] = (uch)b;
Trace((stdout, " (%02x)", h[n]));
}
--
2.4.6
From 4b48844661ff9569f2ecf582a387d46a5775b5d8 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Mon, 14 Sep 2015 18:24:56 +0200
Subject: [PATCH 2/3] fix infinite loop when extracting empty bzip2 data
Bug: https://sourceforge.net/p/infozip/patches/23/
---
extract.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/extract.c b/extract.c
index 7134bfe..29db027 100644
--- a/extract.c
+++ b/extract.c
@@ -2733,6 +2733,12 @@ __GDEF
int repeated_buf_err;
bz_stream bstrm;
+ if (G.incnt <= 0 && G.csize <= 0L) {
+ /* avoid an infinite loop */
+ Trace((stderr, "UZbunzip2() got empty input\n"));
+ return 2;
+ }
+
#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
if (G.redirect_slide)
wsize = G.redirect_size, redirSlide = G.redirect_buffer;
--
2.4.6
From bd150334fb4084f5555a6be26b015a0671cb5b74 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Tue, 22 Sep 2015 18:52:23 +0200
Subject: [PATCH 3/3] extract: prevent unsigned overflow on invalid input
Suggested-by: Stefan Cornelius
---
extract.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/extract.c b/extract.c
index 29db027..b9ae667 100644
--- a/extract.c
+++ b/extract.c
@@ -1257,8 +1257,17 @@ static int extract_or_test_entrylist(__G__ numchunk,
if (G.lrec.compression_method == STORED) {
zusz_t csiz_decrypted = G.lrec.csize;
- if (G.pInfo->encrypted)
+ if (G.pInfo->encrypted) {
+ if (csiz_decrypted < 12) {
+ /* handle the error now to prevent unsigned overflow */
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarStringSmall(ErrUnzipNoFile),
+ LoadFarString(InvalidComprData),
+ LoadFarStringSmall2(Inflate)));
+ return PK_ERR;
+ }
csiz_decrypted -= 12;
+ }
if (G.lrec.ucsize != csiz_decrypted) {
Info(slide, 0x401, ((char *)slide,
LoadFarStringSmall2(WrnStorUCSizCSizDiff),
--
2.5.2

View File

@ -0,0 +1,11 @@
--- unzip60/man/unzip.1 2011-01-11 11:59:59.000000000 +0000
+++ unzip60/man/unzip.1 2011-02-05 18:45:55.000000000 +0000
@@ -424,7 +424,7 @@
.\" Amiga support possible eventually, but not yet
[MS-DOS, OS/2, NT] restore the volume label if the extraction medium is
removable (e.g., a diskette). Doubling the option (\fB\-$$\fP) allows fixed
-media (hard disks) to be labelled as well. By default, volume labels are
+media (hard disks) to be labeled as well. By default, volume labels are
ignored.
.IP \fB\-/\fP\ \fIextensions\fP
[Acorn only] overrides the extension list supplied by Unzip$Ext environment

View File

@ -0,0 +1,34 @@
diff --git a/list.c b/list.c
index f7359c3..4c3d703 100644
--- a/list.c
+++ b/list.c
@@ -97,7 +97,7 @@ int list_files(__G) /* return PK-type error code */
{
int do_this_file=FALSE, cfactor, error, error_in_archive=PK_COOL;
#ifndef WINDLL
- char sgn, cfactorstr[10];
+ char sgn, cfactorstr[13];
int longhdr=(uO.vflag>1);
#endif
int date_format;
@@ -339,7 +339,19 @@ int list_files(__G) /* return PK-type error code */
G.crec.compression_method == ENHDEFLATED) {
methbuf[5] = dtype[(G.crec.general_purpose_bit_flag>>1) & 3];
} else if (methnum >= NUM_METHODS) {
- sprintf(&methbuf[4], "%03u", G.crec.compression_method);
+ /* 2013-02-26 SMS.
+ * http://sourceforge.net/tracker/?func=detail
+ * &aid=2861648&group_id=118012&atid=679786
+ * Unexpectedly large compression methods overflow
+ * &methbuf[]. Use the old, three-digit decimal format
+ * for values which fit. Otherwise, sacrifice the
+ * colon, and use four-digit hexadecimal.
+ */
+ if (G.crec.compression_method <= 999) {
+ sprintf( &methbuf[ 4], "%03u", G.crec.compression_method);
+ } else {
+ sprintf( &methbuf[ 3], "%04X", G.crec.compression_method);
+ }
}
#if 0 /* GRR/Euro: add this? */

View File

@ -0,0 +1,25 @@
diff --git a/extract.c b/extract.c
index a0a4929..9ef80b3 100644
--- a/extract.c
+++ b/extract.c
@@ -2214,6 +2214,7 @@ static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)
ulg eb_ucsize;
uch *eb_ucptr;
int r;
+ ush method;
if (compr_offset < 4) /* field is not compressed: */
return PK_OK; /* do nothing and signal OK */
@@ -2223,6 +2224,12 @@ static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)
eb_size <= (compr_offset + EB_CMPRHEADLEN)))
return IZ_EF_TRUNC; /* no compressed data! */
+ method = makeword(eb + (EB_HEADSIZE + compr_offset));
+ if ((method == STORED) && (eb_size != compr_offset + EB_CMPRHEADLEN + eb_ucsize))
+ return PK_ERR; /* compressed & uncompressed
+ * should match in STORED
+ * method */
+
if (
#ifdef INT_16BIT
(((ulg)(extent)eb_ucsize) != eb_ucsize) ||

View File

@ -0,0 +1,17 @@
diff --git a/process.c b/process.c
index 1e9a1e1..905732b 100644
--- a/process.c
+++ b/process.c
@@ -1751,6 +1751,12 @@ int process_cdir_file_hdr(__G) /* return PK-type error code */
= (G.crec.general_purpose_bit_flag & (1 << 11)) == (1 << 11);
#endif
+#ifdef SYMLINKS
+ /* Initialize the symlink flag, may be set by the platform-specific
+ mapattr function. */
+ G.pInfo->symlink = 0;
+#endif
+
return PK_COOL;
} /* end function process_cdir_file_hdr() */

View File

@ -0,0 +1,41 @@
From: "Steven M. Schweda" <sms@antinode.info>
Subject: Do not ignore extra fields containing Unix Timestamps
Bug-Debian: https://bugs.debian.org/842993
X-Debian-version: 6.0-21
--- a/process.c
+++ b/process.c
@@ -2914,10 +2914,13 @@
break;
case EF_IZUNIX2:
- if (have_new_type_eb == 0) {
- flags &= ~0x0ff; /* ignore any previous IZUNIX field */
+ if (have_new_type_eb == 0) { /* (< 1) */
have_new_type_eb = 1;
}
+ if (have_new_type_eb <= 1) {
+ /* Ignore any prior (EF_IZUNIX/EF_PKUNIX) UID/GID. */
+ flags &= 0x0ff;
+ }
#ifdef IZ_HAVE_UXUIDGID
if (have_new_type_eb > 1)
break; /* IZUNIX3 overrides IZUNIX2 e.f. block ! */
@@ -2933,6 +2936,8 @@
/* new 3rd generation Unix ef */
have_new_type_eb = 2;
+ /* Ignore any prior EF_IZUNIX/EF_PKUNIX/EF_IZUNIX2 UID/GID. */
+ flags &= 0x0ff;
/*
Version 1 byte version of this extra field, currently 1
UIDSize 1 byte Size of UID field
@@ -2953,8 +2958,6 @@
uid_size = *((EB_HEADSIZE + 1) + ef_buf);
gid_size = *((EB_HEADSIZE + uid_size + 2) + ef_buf);
- flags &= ~0x0ff; /* ignore any previous UNIX field */
-
if ( read_ux3_value((EB_HEADSIZE + 2) + ef_buf,
uid_size, &z_uidgid[0])
&&

View File

@ -0,0 +1,26 @@
diff --git a/fileio.c b/fileio.c
index ba0a1d0..03fc4be 100644
--- a/fileio.c
+++ b/fileio.c
@@ -2006,6 +2006,7 @@ int do_string(__G__ length, option) /* return PK-type error code */
unsigned comment_bytes_left;
unsigned int block_len;
int error=PK_OK;
+ unsigned int length2;
#ifdef AMIGA
char tmp_fnote[2 * AMIGA_FILENOTELEN]; /* extra room for squozen chars */
#endif
@@ -2292,8 +2293,12 @@ int do_string(__G__ length, option) /* return PK-type error code */
seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes +
(G.inptr-G.inbuf) + length);
} else {
- if (readbuf(__G__ (char *)G.extra_field, length) == 0)
+ if ((length2 = readbuf(__G__ (char *)G.extra_field, length)) == 0)
return PK_EOF;
+ if(length2 < length) {
+ memset (__G__ (char *)G.extra_field+length2, 0 , length-length2);
+ length = length2;
+ }
/* Looks like here is where extra fields are read */
getZip64Data(__G__ G.extra_field, length);
#ifdef UNICODE_SUPPORT

View File

@ -0,0 +1,28 @@
--- ./process.c.orig 2009-03-06 02:25:10.000000000 +0100
+++ ./process.c
@@ -2901,9 +2901,9 @@
*/
#ifdef IZ_HAVE_UXUIDGID
- if (eb_len >= EB_UX3_MINLEN
- && z_uidgid != NULL
- && (*((EB_HEADSIZE + 0) + ef_buf) == 1)
+ if ((eb_len >= EB_UX3_MINLEN)
+ && (z_uidgid != NULL)
+ && ((*((EB_HEADSIZE + 0) + ef_buf) == 1)))
/* only know about version 1 */
{
uch uid_size;
@@ -2915,10 +2915,10 @@
flags &= ~0x0ff; /* ignore any previous UNIX field */
if ( read_ux3_value((EB_HEADSIZE + 2) + ef_buf,
- uid_size, z_uidgid[0])
+ uid_size, &z_uidgid[0])
&&
read_ux3_value((EB_HEADSIZE + uid_size + 3) + ef_buf,
- gid_size, z_uidgid[1]) )
+ gid_size, &z_uidgid[1]) )
{
flags |= EB_UX2_VALID; /* signal success */
}

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,25 @@
From 6fe72291a5563cdbcd2bdd87e36528537b7cdcfb Mon Sep 17 00:00:00 2001
From: Jakub Martisko <jamartis@redhat.com>
Date: Mon, 18 Nov 2019 14:17:46 +0100
Subject: [PATCH] update the man page
---
man/unzip.1 | 2 ++
1 file changed, 2 insertions(+)
diff --git a/man/unzip.1 b/man/unzip.1
index 21816d1..4d66073 100644
--- a/man/unzip.1
+++ b/man/unzip.1
@@ -850,6 +850,8 @@ the specified zipfiles were not found.
invalid options were specified on the command line.
.IP 11
no matching files were found.
+.IP 12
+invalid zip file with overlapped components (possible zip bomb).
.IP 50
the disk is (or was) full during extraction.
.IP 51
--
2.23.0

View File

@ -0,0 +1,25 @@
From 41beb477c5744bc396fa1162ee0c14218ec12213 Mon Sep 17 00:00:00 2001
From: Mark Adler <madler@alumni.caltech.edu>
Date: Mon, 27 May 2019 08:20:32 -0700
Subject: [PATCH] Fix bug in undefer_input() that misplaced the input state.
---
fileio.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/fileio.c b/fileio.c
index c042987..bc00d74 100644
--- a/fileio.c
+++ b/fileio.c
@@ -530,8 +530,10 @@ void undefer_input(__G)
* This condition was checked when G.incnt_leftover was set > 0 in
* defer_leftover_input(), and it is NOT allowed to touch G.csize
* before calling undefer_input() when (G.incnt_leftover > 0)
- * (single exception: see read_byte()'s "G.csize <= 0" handling) !!
+ * (single exception: see readbyte()'s "G.csize <= 0" handling) !!
*/
+ if (G.csize < 0L)
+ G.csize = 0L;
G.incnt = G.incnt_leftover + (int)G.csize;
G.inptr = G.inptr_leftover - (int)G.csize;
G.incnt_leftover = 0;

View File

@ -0,0 +1,349 @@
From 47b3ceae397d21bf822bc2ac73052a4b1daf8e1c Mon Sep 17 00:00:00 2001
From: Mark Adler <madler@alumni.caltech.edu>
Date: Tue, 11 Jun 2019 22:01:18 -0700
Subject: [PATCH] Detect and reject a zip bomb using overlapped entries.
This detects an invalid zip file that has at least one entry that
overlaps with another entry or with the central directory to the
end of the file. A Fifield zip bomb uses overlapped local entries
to vastly increase the potential inflation ratio. Such an invalid
zip file is rejected.
See https://www.bamsoftware.com/hacks/zipbomb/ for David Fifield's
analysis, construction, and examples of such zip bombs.
The detection maintains a list of covered spans of the zip files
so far, where the central directory to the end of the file and any
bytes preceding the first entry at zip file offset zero are
considered covered initially. Then as each entry is decompressed
or tested, it is considered covered. When a new entry is about to
be processed, its initial offset is checked to see if it is
contained by a covered span. If so, the zip file is rejected as
invalid.
This commit depends on a preceding commit: "Fix bug in
undefer_input() that misplaced the input state."
---
extract.c | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
globals.c | 1 +
globals.h | 3 +
process.c | 11 ++++
unzip.h | 1 +
5 files changed, 205 insertions(+), 1 deletion(-)
diff --git a/extract.c b/extract.c
index 1acd769..0973a33 100644
--- a/extract.c
+++ b/extract.c
@@ -319,6 +319,125 @@ static ZCONST char Far UnsupportedExtraField[] =
"\nerror: unsupported extra-field compression type (%u)--skipping\n";
static ZCONST char Far BadExtraFieldCRC[] =
"error [%s]: bad extra-field CRC %08lx (should be %08lx)\n";
+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";
+
+
+
+
+
+/* A growable list of spans. */
+typedef zoff_t bound_t;
+typedef struct {
+ bound_t beg; /* start of the span */
+ bound_t end; /* one past the end of the span */
+} span_t;
+typedef struct {
+ span_t *span; /* allocated, distinct, and sorted list of spans */
+ size_t num; /* number of spans in the list */
+ size_t max; /* allocated number of spans (num <= max) */
+} cover_t;
+
+/*
+ * Return the index of the first span in cover whose beg is greater than val.
+ * If there is no such span, then cover->num is returned.
+ */
+static size_t cover_find(cover, val)
+ cover_t *cover;
+ bound_t val;
+{
+ size_t lo = 0, hi = cover->num;
+ while (lo < hi) {
+ size_t mid = (lo + hi) >> 1;
+ if (val < cover->span[mid].beg)
+ hi = mid;
+ else
+ lo = mid + 1;
+ }
+ return hi;
+}
+
+/* Return true if val lies within any one of the spans in cover. */
+static int cover_within(cover, val)
+ cover_t *cover;
+ bound_t val;
+{
+ size_t pos = cover_find(cover, val);
+ return pos > 0 && val < cover->span[pos - 1].end;
+}
+
+/*
+ * Add a new span to the list, but only if the new span does not overlap any
+ * spans already in the list. The new span covers the values beg..end-1. beg
+ * must be less than end.
+ *
+ * Keep the list sorted and merge adjacent spans. Grow the allocated space for
+ * the list as needed. On success, 0 is returned. If the new span overlaps any
+ * existing spans, then 1 is returned and the new span is not added to the
+ * list. If the new span is invalid because beg is greater than or equal to
+ * end, then -1 is returned. If the list needs to be grown but the memory
+ * allocation fails, then -2 is returned.
+ */
+static int cover_add(cover, beg, end)
+ cover_t *cover;
+ bound_t beg;
+ bound_t end;
+{
+ size_t pos;
+ int prec, foll;
+
+ if (beg >= end)
+ /* The new span is invalid. */
+ return -1;
+
+ /* Find where the new span should go, and make sure that it does not
+ overlap with any existing spans. */
+ pos = cover_find(cover, beg);
+ if ((pos > 0 && beg < cover->span[pos - 1].end) ||
+ (pos < cover->num && end > cover->span[pos].beg))
+ return 1;
+
+ /* Check for adjacencies. */
+ prec = pos > 0 && beg == cover->span[pos - 1].end;
+ foll = pos < cover->num && end == cover->span[pos].beg;
+ if (prec && foll) {
+ /* The new span connects the preceding and following spans. Merge the
+ following span into the preceding span, and delete the following
+ span. */
+ cover->span[pos - 1].end = cover->span[pos].end;
+ cover->num--;
+ memmove(cover->span + pos, cover->span + pos + 1,
+ (cover->num - pos) * sizeof(span_t));
+ }
+ else if (prec)
+ /* The new span is adjacent only to the preceding span. Extend the end
+ of the preceding span. */
+ cover->span[pos - 1].end = end;
+ else if (foll)
+ /* The new span is adjacent only to the following span. Extend the
+ beginning of the following span. */
+ cover->span[pos].beg = beg;
+ else {
+ /* The new span has gaps between both the preceding and the following
+ spans. Assure that there is room and insert the span. */
+ if (cover->num == cover->max) {
+ size_t max = cover->max == 0 ? 16 : cover->max << 1;
+ span_t *span = realloc(cover->span, max * sizeof(span_t));
+ if (span == NULL)
+ return -2;
+ cover->span = span;
+ cover->max = max;
+ }
+ memmove(cover->span + pos + 1, cover->span + pos,
+ (cover->num - pos) * sizeof(span_t));
+ cover->num++;
+ cover->span[pos].beg = beg;
+ cover->span[pos].end = end;
+ }
+ return 0;
+}
@@ -374,6 +493,29 @@ int extract_or_test_files(__G) /* return PK-type error code */
}
#endif /* !SFX || SFX_EXDIR */
+ /* One more: initialize cover structure for bomb detection. Start with a
+ span that covers the central directory though the end of the file. */
+ if (G.cover == NULL) {
+ G.cover = malloc(sizeof(cover_t));
+ if (G.cover == NULL) {
+ 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 ((G.extra_bytes != 0 &&
+ cover_add((cover_t *)G.cover, 0, G.extra_bytes) != 0) ||
+ cover_add((cover_t *)G.cover,
+ G.extra_bytes + G.ecrec.offset_start_central_directory,
+ G.ziplen) != 0) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(NotEnoughMemCover)));
+ return PK_MEM;
+ }
+
/*---------------------------------------------------------------------------
The basic idea of this function is as follows. Since the central di-
rectory lies at the end of the zipfile and the member files lie at the
@@ -591,7 +733,8 @@ int extract_or_test_files(__G) /* return PK-type error code */
if (error > error_in_archive)
error_in_archive = error;
/* ...and keep going (unless disk full or user break) */
- if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {
+ if (G.disk_full > 1 || error_in_archive == IZ_CTRLC ||
+ error == PK_BOMB) {
/* clear reached_end to signal premature stop ... */
reached_end = FALSE;
/* ... and cancel scanning the central directory */
@@ -1060,6 +1203,11 @@ 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)) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(OverlappedComponents)));
+ return PK_BOMB;
+ }
inbuf_offset = request % INBUFSIZ;
bufstart = request - inbuf_offset;
@@ -1591,6 +1739,18 @@ static int extract_or_test_entrylist(__G__ numchunk,
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) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(NotEnoughMemCover)));
+ return PK_MEM;
+ }
+ if (error != 0) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(OverlappedComponents)));
+ return PK_BOMB;
+ }
#ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */
UserStop();
#endif
@@ -1992,6 +2152,34 @@ static int extract_or_test_member(__G) /* return PK-type error code */
}
undefer_input(__G);
+
+ if ((G.lrec.general_purpose_bit_flag & 8) != 0) {
+ /* skip over data descriptor (harder than it sounds, due to signature
+ * ambiguity)
+ */
+# define SIG 0x08074b50
+# define LOW 0xffffffff
+ uch buf[12];
+ unsigned shy = 12 - readbuf((char *)buf, 12);
+ ulg crc = shy ? 0 : makelong(buf);
+ ulg clen = shy ? 0 : makelong(buf + 4);
+ ulg ulen = shy ? 0 : makelong(buf + 8); /* or high clen if ZIP64 */
+ if (crc == SIG && /* if not SIG, no signature */
+ (G.lrec.crc32 != SIG || /* if not SIG, have signature */
+ (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
+ /* if not SIG, have signature */
+ )))))
+ /* skip four more bytes to account for signature */
+ shy += 4 - readbuf((char *)buf, 4);
+ if (G.zip64)
+ shy += 8 - readbuf((char *)buf, 8); /* skip eight more for ZIP64 */
+ if (shy)
+ error = PK_ERR;
+ }
+
return error;
} /* end function extract_or_test_member() */
diff --git a/globals.c b/globals.c
index fa8cca5..1e0f608 100644
--- a/globals.c
+++ b/globals.c
@@ -181,6 +181,7 @@ Uz_Globs *globalsCtor()
# if (!defined(NO_TIMESTAMPS))
uO.D_flag=1; /* default to '-D', no restoration of dir timestamps */
# endif
+ G.cover = NULL; /* not allocated yet */
#endif
uO.lflag=(-1);
diff --git a/globals.h b/globals.h
index 11b7215..2bdcdeb 100644
--- a/globals.h
+++ b/globals.h
@@ -260,12 +260,15 @@ 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 */
int reported_backslash; /* extract.c static */
int disk_full;
int newfile;
+ void **cover; /* used in extract.c for bomb detection */
int didCRlast; /* fileio static */
ulg numlines; /* fileio static: number of lines printed */
diff --git a/process.c b/process.c
index 1e9a1e1..d2e4dc3 100644
--- a/process.c
+++ b/process.c
@@ -637,6 +637,13 @@ void free_G_buffers(__G) /* releases all memory allocated in global vars */
}
#endif
+ /* Free the cover span list and the cover structure. */
+ if (G.cover != NULL) {
+ free(*(G.cover));
+ free(G.cover);
+ G.cover = NULL;
+ }
+
} /* end function free_G_buffers() */
@@ -1890,6 +1897,8 @@ 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;
@@ -1927,6 +1936,8 @@ int getZip64Data(__G__ ef_buf, ef_len)
#if 0
break; /* Expect only one EF_PKSZ64 block. */
#endif /* 0 */
+
+ G.zip64 = TRUE;
}
/* Skip this extra field block. */
diff --git a/unzip.h b/unzip.h
index 5b2a326..ed24a5b 100644
--- a/unzip.h
+++ b/unzip.h
@@ -645,6 +645,7 @@ typedef struct _Uzp_cdir_Rec {
#define PK_NOZIP 9 /* zipfile not found */
#define PK_PARAM 10 /* bad or illegal parameters specified */
#define PK_FIND 11 /* no files found */
+#define PK_BOMB 12 /* likely zip bomb */
#define PK_DISK 50 /* disk full */
#define PK_EOF 51 /* unexpected EOF */

View File

@ -0,0 +1,112 @@
From 6d351831be705cc26d897db44f878a978f4138fc Mon Sep 17 00:00:00 2001
From: Mark Adler <madler@alumni.caltech.edu>
Date: Thu, 25 Jul 2019 20:43:17 -0700
Subject: [PATCH] Do not raise a zip bomb alert for a misplaced central
directory.
There is a zip-like file in the Firefox distribution, omni.ja,
which is a zip container with the central directory placed at the
start of the file instead of after the local entries as required
by the zip standard. This commit marks the actual location of the
central directory, as well as the end of central directory records,
as disallowed locations. This now permits such containers to not
raise a zip bomb alert, where in fact there are no overlaps.
---
extract.c | 25 +++++++++++++++++++------
process.c | 6 ++++++
unzpriv.h | 10 ++++++++++
3 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/extract.c b/extract.c
index 0973a33..1b73cb0 100644
--- a/extract.c
+++ b/extract.c
@@ -493,8 +493,11 @@ int extract_or_test_files(__G) /* return PK-type error code */
}
#endif /* !SFX || SFX_EXDIR */
- /* One more: initialize cover structure for bomb detection. Start with a
- span that covers the central directory though the end of the file. */
+ /* One more: initialize cover structure for bomb detection. Start with
+ spans that cover any extra bytes at the start, the central directory,
+ 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) {
G.cover = malloc(sizeof(cover_t));
if (G.cover == NULL) {
@@ -506,15 +509,25 @@ int extract_or_test_files(__G) /* return PK-type error code */
((cover_t *)G.cover)->max = 0;
}
((cover_t *)G.cover)->num = 0;
- if ((G.extra_bytes != 0 &&
- cover_add((cover_t *)G.cover, 0, G.extra_bytes) != 0) ||
- cover_add((cover_t *)G.cover,
+ if (cover_add((cover_t *)G.cover,
G.extra_bytes + G.ecrec.offset_start_central_directory,
- G.ziplen) != 0) {
+ G.extra_bytes + G.ecrec.offset_start_central_directory +
+ G.ecrec.size_central_directory) != 0) {
Info(slide, 0x401, ((char *)slide,
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) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(OverlappedComponents)));
+ return PK_BOMB;
+ }
/*---------------------------------------------------------------------------
The basic idea of this function is as follows. Since the central di-
diff --git a/process.c b/process.c
index d2e4dc3..d75d405 100644
--- a/process.c
+++ b/process.c
@@ -1408,6 +1408,10 @@ static int find_ecrec64(__G__ searchlen) /* return PK-class error */
/* Now, we are (almost) sure that we have a Zip64 archive. */
G.ecrec.have_ecr64 = 1;
+ G.ecrec.ec_start -= ECLOC64_SIZE+4;
+ G.ecrec.ec64_start = ecrec64_start_offset;
+ G.ecrec.ec64_end = ecrec64_start_offset +
+ 12 + makeint64(&byterec[ECREC64_LENGTH]);
/* Update the "end-of-central-dir offset" for later checks. */
G.real_ecrec_offset = ecrec64_start_offset;
@@ -1542,6 +1546,8 @@ static int find_ecrec(__G__ searchlen) /* return PK-class error */
makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]);
G.ecrec.zipfile_comment_length =
makeword(&byterec[ZIPFILE_COMMENT_LENGTH]);
+ G.ecrec.ec_start = G.real_ecrec_offset;
+ G.ecrec.ec_end = G.ecrec.ec_start + 22 + G.ecrec.zipfile_comment_length;
/* Now, we have to read the archive comment, BEFORE the file pointer
is moved away backwards to seek for a Zip64 ECLOC64 structure.
diff --git a/unzpriv.h b/unzpriv.h
index dc9eff5..297b3c7 100644
--- a/unzpriv.h
+++ b/unzpriv.h
@@ -2185,6 +2185,16 @@ typedef struct VMStimbuf {
int have_ecr64; /* valid Zip64 ecdir-record exists */
int is_zip64_archive; /* Zip64 ecdir-record is mandatory */
ush zipfile_comment_length;
+ zusz_t ec_start, ec_end; /* offsets of start and end of the
+ end of central directory record,
+ including if present the Zip64
+ end of central directory locator,
+ which immediately precedes the
+ end of central directory record */
+ zusz_t ec64_start, ec64_end; /* if have_ecr64 is true, then these
+ are the offsets of the start and
+ end of the Zip64 end of central
+ directory record */
} ecdir_rec;

32
extra/unzip/sources Normal file
View File

@ -0,0 +1,32 @@
https://versaweb.dl.sourceforge.net/project/infozip/UnZip%206.x%20%28latest%29/UnZip%206.0/unzip60.tar.gz
patches/0001-Fix-CVE-2016-9844-rhbz-1404283.patch
patches/series
patches/unzip-6.0-COVSCAN-fix-unterminated-string.patch
patches/unzip-6.0-alt-iconv-utf8-print.patch
patches/unzip-6.0-alt-iconv-utf8.patch
patches/unzip-6.0-attribs-overflow.patch
patches/unzip-6.0-bzip2-configure.patch
patches/unzip-6.0-caseinsensitive.patch
patches/unzip-6.0-close.patch
patches/unzip-6.0-configure.patch
patches/unzip-6.0-cve-2014-8139.patch
patches/unzip-6.0-cve-2014-8140.patch
patches/unzip-6.0-cve-2014-8141.patch
patches/unzip-6.0-cve-2018-1000035-heap-based-overflow.patch
patches/unzip-6.0-cve-2018-18384.patch
patches/unzip-6.0-exec-shield.patch
patches/unzip-6.0-fix-recmatch.patch
patches/unzip-6.0-format-secure.patch
patches/unzip-6.0-heap-overflow-infloop.patch
patches/unzip-6.0-manpage-fix.patch
patches/unzip-6.0-overflow-long-fsize.patch
patches/unzip-6.0-overflow.patch
patches/unzip-6.0-symlink.patch
patches/unzip-6.0-timestamp.patch
patches/unzip-6.0-valgrind.patch
patches/unzip-6.0-x-option.patch
patches/unzip-6.0_CVE-2021-4217.patch
patches/unzip-zipbomb-manpage.patch
patches/unzip-zipbomb-part1.patch
patches/unzip-zipbomb-part2.patch
patches/unzip-zipbomb-part3.patch

1
extra/unzip/version Normal file
View File

@ -0,0 +1 @@
6.0 2