Non-exhaustively fixes CVE-2016-9844, CVE-2018-1000035, CVE-2018-18384, and CVE-2019-13232. * gnu/packages/patches/unzip-COVSCAN-fix-unterminated-string.patch, gnu/packages/patches/unzip-CVE-2016-9844.patch, gnu/packages/patches/unzip-CVE-2018-1000035.patch, gnu/packages/patches/unzip-CVE-2018-18384.patch, gnu/packages/patches/unzip-case-insensitive.patch, gnu/packages/patches/unzip-alt-iconv-utf8-print.patch, gnu/packages/patches/unzip-alt-iconv-utf8.patch, gnu/packages/patches/unzip-close.patch, gnu/packages/patches/unzip-exec-shield.patch, gnu/packages/patches/unzip-fix-recmatch.patch, gnu/packages/patches/unzip-manpage-fix.patch, gnu/packages/patches/unzip-overflow.patch, gnu/packages/patches/unzip-symlink.patch, gnu/packages/patches/unzip-timestamp.patch, gnu/packages/patches/unzip-valgrind.patch, gnu/packages/patches/unzip-x-option.patch, gnu/packages/patches/unzip-zipbomb-manpage.patch, gnu/packages/patches/unzip-zipbomb-part1.patch, gnu/packages/patches/unzip-zipbomb-part2.patch, gnu/packages/patches/unzip-zipbomb-part3.patch: New patches. * gnu/local.mk (dist_patch_DATA): Register them. * gnu/packages/compression.scm (unzip/fixed): New variable. Apply patches. (unzip)[replacement]: Graft.
		
			
				
	
	
		
			381 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			381 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 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
 | |
| 
 |