diff --git a/README.md b/README.md index cc5b17a..453a042 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,5 @@ The zip program is a compression and file packaging utility. Zip is analogous to a combination of the UNIX tar and compress commands and is compatible with PKZIP (a compression and file packaging utility for MS-DOS systems). - Install the zip package if you need to compress files using the zip program. diff --git a/unzip-6.0-crc32.patch b/unzip-6.0-crc32.patch new file mode 100644 index 0000000..43b29d7 --- /dev/null +++ b/unzip-6.0-crc32.patch @@ -0,0 +1,45 @@ +--- unzip60/extract.c 2010-04-03 14:41:55 -0500 ++++ unzip60/extract.c 2014-12-03 15:33:35 -0600 +@@ -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 @@ + #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 TooSmallEFlength[] = "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)) +@@ -2023,7 +2025,8 @@ + 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 ", +@@ -2032,6 +2035,16 @@ + ebLen, (ef_len - EB_HEADSIZE))); + return PK_ERR; + } ++ else if (ebLen < EB_HEADSIZE) ++ { ++ /* Extra block length smaller than header length. */ ++ if (uO.qflag) ++ Info(slide, 1, ((char *)slide, "%-22s ", ++ FnFilter1(G.filename))); ++ Info(slide, 1, ((char *)slide, LoadFarString(TooSmallEFlength), ++ ebLen, EB_HEADSIZE)); ++ return PK_ERR; ++ } + + switch (ebID) { + case EF_OS2: diff --git a/unzip-6.0-csiz-underflow.patch b/unzip-6.0-csiz-underflow.patch new file mode 100644 index 0000000..45afbdd --- /dev/null +++ b/unzip-6.0-csiz-underflow.patch @@ -0,0 +1,32 @@ +From: Kamil Dudka +Date: Tue, 22 Sep 2015 18:52:23 +0200 +Subject: [PATCH] extract: prevent unsigned overflow on invalid input +Origin: other, https://bugzilla.redhat.com/attachment.cgi?id=1075942 +Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1260944 + +Suggested-by: Stefan Cornelius +--- + extract.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +--- a/extract.c ++++ b/extract.c +@@ -1257,8 +1257,17 @@ + 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), diff --git a/unzip-6.0-cve20149636.patch b/unzip-6.0-cve20149636.patch new file mode 100644 index 0000000..228c283 --- /dev/null +++ b/unzip-6.0-cve20149636.patch @@ -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) || diff --git a/unzip-6.0-empty-input.patch b/unzip-6.0-empty-input.patch new file mode 100644 index 0000000..45cbe92 --- /dev/null +++ b/unzip-6.0-empty-input.patch @@ -0,0 +1,26 @@ +From: Kamil Dudka +Date: Mon, 14 Sep 2015 18:24:56 +0200 +Subject: fix infinite loop when extracting empty bzip2 data +Bug-Debian: https://bugs.debian.org/802160 +Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1260944 +Origin: other, https://bugzilla.redhat.com/attachment.cgi?id=1073339 + +--- + extract.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/extract.c ++++ b/extract.c +@@ -2728,6 +2728,12 @@ + 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; diff --git a/unzip-6.0-getZip64Data.patch b/unzip-6.0-getZip64Data.patch new file mode 100644 index 0000000..1684c73 --- /dev/null +++ b/unzip-6.0-getZip64Data.patch @@ -0,0 +1,133 @@ +--- process.c 2009-03-06 02:25:10.000000000 +0100 ++++ process.c 2014-12-05 22:42:39.000000000 +0100 +@@ -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. +@@ -1888,48 +1888,82 @@ 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); + } +--- fileio.c 2009-04-20 02:03:44.000000000 +0200 ++++ fileio.c 2014-12-05 22:44:16.000000000 +0100 +@@ -176,6 +176,8 @@ static ZCONST char Far FilenameTooLongTr + #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[] = +@@ -2295,7 +2297,12 @@ int do_string(__G__ length, option) /* + if (readbuf(__G__ (char *)G.extra_field, length) == 0) + return PK_EOF; + /* 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/unzip-6.0-nextbyte-overflow.patch b/unzip-6.0-nextbyte-overflow.patch new file mode 100644 index 0000000..91482da --- /dev/null +++ b/unzip-6.0-nextbyte-overflow.patch @@ -0,0 +1,33 @@ +From: Petr Stodulka +Date: Mon, 14 Sep 2015 18:23:17 +0200 +Subject: Upstream fix for heap overflow +Bug-Debian: https://bugs.debian.org/802162 +Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1260944 +Origin: https://bugzilla.redhat.com/attachment.cgi?id=1073002 +Forwarded: yes + +--- + crypt.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +--- a/crypt.c ++++ b/crypt.c +@@ -465,7 +465,17 @@ + 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])); + } diff --git a/unzip-6.0-overflow-fsize.patch b/unzip-6.0-overflow-fsize.patch new file mode 100644 index 0000000..910b22d --- /dev/null +++ b/unzip-6.0-overflow-fsize.patch @@ -0,0 +1,34 @@ +t 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? */ diff --git a/unzip-6.0-test_compr_eb.patch b/unzip-6.0-test_compr_eb.patch new file mode 100644 index 0000000..7e8c297 --- /dev/null +++ b/unzip-6.0-test_compr_eb.patch @@ -0,0 +1,23 @@ +--- extract.c 2009-03-14 02:32:52.000000000 +0100 ++++ extract.c 2014-12-05 22:43:13.000000000 +0100 +@@ -2221,10 +2234,17 @@ static int test_compr_eb(__G__ eb, eb_si + 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! */ + + if ( + #ifdef INT_16BIT diff --git a/unzip.spec b/unzip.spec index 0d8b7a7..fabe6dc 100644 --- a/unzip.spec +++ b/unzip.spec @@ -2,7 +2,7 @@ Name: unzip Version: 6.0 -Release: 2mamba +Release: 3mamba Summary: A file compression and packaging utility compatible with PKZIP Group: Applications/Archiving Vendor: openmamba @@ -15,42 +15,61 @@ Patch1: %{name}-5.51-link-segv.patch Patch2: %{name}-5.52-can-2005-2475.patch Patch3: %{name}-5.52-CVE-2005-4667.patch Patch4: %{name}-6.0-iconv.patch +Patch5: unzip-6.0-overflow-fsize.patch +Patch6: unzip-6.0-cve20149636.patch +Patch7: unzip-6.0-test_compr_eb.patch +Patch8: unzip-6.0-getZip64Data.patch +Patch9: unzip-6.0-crc32.patch +Patch10: unzip-6.0-empty-input.patch +Patch11: unzip-6.0-csiz-underflow.patch +Patch12: unzip-6.0-nextbyte-overflow.patch License: BSD ## AUTOBUILDREQ-BEGIN BuildRequires: glibc-devel +BuildRequires: libbzip2-devel ## AUTOBUILDREQ-END BuildRoot: %{_tmppath}/%{name}-%{version}-root %description The zip program is a compression and file packaging utility. Zip is analogous to a combination of the UNIX tar and compress commands and is compatible with PKZIP (a compression and file packaging utility for MS-DOS systems). - Install the zip package if you need to compress files using the zip program. %debug_package %prep %setup -q -n unzip%{src_ver} -#%patch0 -p1 -#%patch1 -p1 -#%patch2 -p1 -b .can-2005-2475 -#%patch3 -p1 -b .can-2005-4667 %patch4 -p1 +%patch5 -p1 +%patch6 -p1 +#%patch7 -p0 +%patch8 -p0 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 ln -sf unix/Makefile Makefile -sed -i "s|CC=gcc |CC=%{_host}-gcc |" Makefile -sed -i "s|LD=gcc |LD=%{_host}-gcc |" Makefile -sed -i "s|AS=gcc |AS=%{_host}-gcc |" Makefile +#sed -i "s|CC=gcc |CC=%{_host}-gcc |" Makefile +#sed -i "s|LD=gcc |LD=%{_host}-gcc |" Makefile +#sed -i "s|AS=gcc |AS=%{_host}-gcc |" Makefile %build -%make linux_noasm LF2="" CC=%{_host}-gcc +# DEFINES, make, and install args from Debian +DEFINES='-DACORN_FTYPE_NFS -DWILD_STOP_AT_DIR -DLARGE_FILE_SUPPORT \ + -DUNICODE_SUPPORT -DUNICODE_WCHAR -DUTF8_MAYBE_NATIVE -DNO_LCHMOD \ + -DDATE_FORMAT=DF_YMD -DUSE_BZIP2 -DNOMEMCPY -DNO_WORKING_ISPRINT' + +%make -f unix/Makefile prefix=/usr \ + D_USE_BZ2=-DUSE_BZIP2 L_BZ2=-lbz2 \ + LF2="" CF="%{optflags} -I. $DEFINES" \ + unzips %install [ "%{buildroot}" != / ] && rm -rf "%{buildroot}" %makeoldinstall \ - LF2="" \ MANDIR=%{buildroot}%{_mandir}/man1 %clean @@ -63,6 +82,9 @@ sed -i "s|AS=gcc |AS=%{_host}-gcc |" Makefile %doc README BUGS LICENSE %changelog +* Wed May 12 2021 Silvan Calarco 6.0-3mamba +- applied patches from Arch Linux + * Wed Nov 25 2020 Silvan Calarco 6.0-2mamba - rebuilt with debug package