ports/opt (3.4): [notify] unzip: patched for CVE-2016-9844, CVE-2018-1000035. Closes FS#1631

crux at crux.nu crux at crux.nu
Sun Mar 11 22:25:42 UTC 2018


commit 57529ffe969d9f2e4cf9186c6f6308a1b8b02791
Author: Fredrik Rinnestam <fredrik at crux.nu>
Date:   Sun Mar 11 23:24:43 2018 +0100

    [notify] unzip: patched for CVE-2016-9844, CVE-2018-1000035. Closes
    FS#1631

diff --git a/unzip/.md5sum b/unzip/.md5sum
index 96220d8d9..26cabcb70 100644
--- a/unzip/.md5sum
+++ b/unzip/.md5sum
@@ -1,7 +1,10 @@
+f65429e4494c4d5a80ec72e4321335da  0001-Fix-CVE-2016-9844-rhbz-1404283.patch
+04bc89e05ccceb4c8600f646156fe242  unzip-6.0-alt-iconv-utf8-print.patch
 19341ef8810558e0cb4e3fe25b3eff70  unzip-6.0-attribs-overflow.patch
 cf3e3a98ff85d784c5d3843758645874  unzip-6.0-cve-2014-8139.patch
 4f6a01093e9a05fe0d2916170d961e29  unzip-6.0-cve-2014-8140.patch
 2a05a5d2f21511c5e393b62e4044e913  unzip-6.0-cve-2014-8141.patch
+704269930d2904b31f36c163e21b668c  unzip-6.0-cve-2018-1000035-heap-based-overflow.patch
 694e3c8ad965798a72569ff42101cc83  unzip-6.0-heap-overflow-infloop.patch
 40ae64ba09670480195539bcdf92c0ef  unzip-6.0-overflow.patch
 62b490407489521db863b523a7f86375  unzip60.tar.gz
diff --git a/unzip/.signature b/unzip/.signature
index d598df8f4..94d6c7f53 100644
--- a/unzip/.signature
+++ b/unzip/.signature
@@ -1,6 +1,6 @@
 untrusted comment: verify with /etc/ports/opt.pub
-RWSE3ohX2g5d/WGL7yDCnia1lYBcpunWX0rdnO4EZlpsSfb9e/VUkb7AkE5wQ76VJsp1uZZsrHwghkmC3cS9SrNOn3XIo0LrmAI=
-SHA256 (Pkgfile) = 43c69cfe9fd7168b20d34f7866cd82a216e00edc78f84d5fe943cac118e28d07
+RWSE3ohX2g5d/U+lQa2p9GXkrS4tGusd6mGpljiq6h1SgJx6cZGoMPeGuSh/54lf/bI3nws9raM+XYq6ajd4aBywlFRjnkpwrAg=
+SHA256 (Pkgfile) = cd04f724cda5bc9cd4860bb3b297d0fc4cb7e21f33f5b8255d78f2c0ac1d2d65
 SHA256 (.footprint) = a1d2c71a5371982b87a8a14082aa2236258f84e0d602ec39247e0d63bf46ffdd
 SHA256 (unzip60.tar.gz) = 036d96991646d0449ed0aa952e4fbe21b476ce994abc276e49d30e686708bd37
 SHA256 (unzip-6.0-overflow.patch) = dcd41e0be383c485427fc5461a1aeb8a6207e7fcacf0d254f18700599845a9da
@@ -9,3 +9,6 @@ SHA256 (unzip-6.0-heap-overflow-infloop.patch) = b072c5a6d252425dbbda54a3d94285e
 SHA256 (unzip-6.0-cve-2014-8139.patch) = 337131428f491b7030f96ee5b8ef3d8f5963730d1619b2754c624f4616d79adb
 SHA256 (unzip-6.0-cve-2014-8140.patch) = 64f64985270e026c01d2c19c6b66c218cf5bcfc7cf3d4a44e601fad41975ec73
 SHA256 (unzip-6.0-cve-2014-8141.patch) = b7a14c33db93d1e5b4fc6ce113b4b99ff7a81ed56f46c87e001f22ec085e0273
+SHA256 (0001-Fix-CVE-2016-9844-rhbz-1404283.patch) = 1980d37c82591f9ad473052408b0a61d0c50cce8db795b9980e6a74b2270c339
+SHA256 (unzip-6.0-cve-2018-1000035-heap-based-overflow.patch) = aced0f27191a67f9b8b3fdc5995938a64fd87cea64a0bbba2106e06137ef91c2
+SHA256 (unzip-6.0-alt-iconv-utf8-print.patch) = b990d8d8d8e02777999484a132170666ea736a865f9ad81da651dc63725475ff
diff --git a/unzip/0001-Fix-CVE-2016-9844-rhbz-1404283.patch b/unzip/0001-Fix-CVE-2016-9844-rhbz-1404283.patch
new file mode 100644
index 000000000..2322ce104
--- /dev/null
+++ b/unzip/0001-Fix-CVE-2016-9844-rhbz-1404283.patch
@@ -0,0 +1,40 @@
+From 754137e70cf58a64ad524b704a86b651ba0cde07 Mon Sep 17 00:00:00 2001
+From: Petr Stodulka <pstodulk at 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
+
+
diff --git a/unzip/Pkgfile b/unzip/Pkgfile
index 9ad788787..cb3aaf3eb 100644
--- a/unzip/Pkgfile
+++ b/unzip/Pkgfile
@@ -4,13 +4,16 @@
 
 name=unzip
 version=6.0
-release=6
+release=7
 source=(http://downloads.sourceforge.net/sourceforge/infozip/${name}${version//./}.tar.gz \
 	unzip-6.0-overflow.patch unzip-6.0-attribs-overflow.patch \
 	unzip-6.0-heap-overflow-infloop.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-cve-2014-8141.patch \
+	0001-Fix-CVE-2016-9844-rhbz-1404283.patch \
+	unzip-6.0-cve-2018-1000035-heap-based-overflow.patch \
+	unzip-6.0-alt-iconv-utf8-print.patch)
 
 build() {
     cd ${name}${version//./}
@@ -20,6 +23,9 @@ build() {
     patch -p1 -i $SRC/unzip-6.0-cve-2014-8139.patch
     patch -p1 -i $SRC/unzip-6.0-cve-2014-8140.patch
     patch -p1 -i $SRC/unzip-6.0-cve-2014-8141.patch
+    patch -p1 -i $SRC/0001-Fix-CVE-2016-9844-rhbz-1404283.patch
+    patch -p1 -i $SRC/unzip-6.0-cve-2018-1000035-heap-based-overflow.patch
+    patch -p1 -i $SRC/unzip-6.0-alt-iconv-utf8-print.patch
 
     sed -i 's/-O3//' unix/configure
     make -f unix/Makefile LOCAL_UNZIP="$CFLAGS" generic
diff --git a/unzip/unzip-6.0-alt-iconv-utf8-print.patch b/unzip/unzip-6.0-alt-iconv-utf8-print.patch
new file mode 100644
index 000000000..0b0153ba5
--- /dev/null
+++ b/unzip/unzip-6.0-alt-iconv-utf8-print.patch
@@ -0,0 +1,381 @@
+From ca0212ba19b64488b9e8459a762c11ecd6e7d0bd Mon Sep 17 00:00:00 2001
+From: Petr Stodulka <pstodulk at 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
+
diff --git a/unzip/unzip-6.0-cve-2018-1000035-heap-based-overflow.patch b/unzip/unzip-6.0-cve-2018-1000035-heap-based-overflow.patch
new file mode 100644
index 000000000..8ca713865
--- /dev/null
+++ b/unzip/unzip-6.0-cve-2018-1000035-heap-based-overflow.patch
@@ -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);


More information about the CRUX mailing list