Hi ports@,

the archivers/unzip port has two unfixed CVE:
CVE-2019-13232 and CVE-2018-1000035
Additionaly the bug bluhm@ patched in 2017 got a name too
CVE-2018-18384

The diff is attached, further info is included with the patches.
mbuhl

Index: archivers/unzip/Makefile
===================================================================
RCS file: /cvs/ports/archivers/unzip/Makefile,v
retrieving revision 1.64
diff -u -p -r1.64 Makefile
--- archivers/unzip/Makefile    12 Jul 2019 20:43:30 -0000      1.64
+++ archivers/unzip/Makefile    20 Feb 2020 07:20:15 -0000
@@ -7,7 +7,7 @@ COMMENT =       extract, list & test files in 
 VERSION =      6.0
 DISTNAME =     unzip${VERSION:S/.//}
 PKGNAME =      unzip-${VERSION}
-REVISION =     12
+REVISION =     13
 CATEGORIES =   archivers
 MASTER_SITES = ${MASTER_SITE_SOURCEFORGE:=infozip/} \
                ftp://ftp.info-zip.org/pub/infozip/src/
Index: archivers/unzip/patches/patch-extract_c
===================================================================
RCS file: /cvs/ports/archivers/unzip/patches/patch-extract_c,v
retrieving revision 1.2
diff -u -p -r1.2 patch-extract_c
--- archivers/unzip/patches/patch-extract_c     23 Mar 2017 17:26:17 -0000      
1.2
+++ archivers/unzip/patches/patch-extract_c     20 Feb 2020 08:49:05 -0000
@@ -12,6 +12,8 @@ Fix CVE-2015-7697: infinite loop when ex
     https://bugs.debian.org/802160
     https://bugzilla.redhat.com/show_bug.cgi?id=1260944
     https://bugzilla.redhat.com/attachment.cgi?id=1073339
+Fix CVE-2019-13232: a zip bomb using overlapped entries
+https://github.com/madler/unzip/commit/47b3ceae397d21bf822bc2ac73052a4b1daf8e1c
 
 --- extract.c.orig     Sat Mar 14 02:32:52 2009
 +++ extract.c  Tue Mar 21 16:10:27 2017
@@ -31,6 +33,189 @@ Fix CVE-2015-7697: infinite loop when ex
     static ZCONST char Far InvalidComprDataEAs[] =
       " invalid compressed data for EAs\n";
  #  if (defined(WIN32) && defined(NTSD_EAS))
+@@ -321,11 +321,130 @@ 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;
++}
++
++
++
++
++
+ /**************************************/
+ /*  Function extract_or_test_files()  */
+ /**************************************/
+@@ -376,6 +495,29 @@ int extract_or_test_files(__G)    /* return PK-type er
+     }
+ #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
+@@ -593,7 +735,8 @@ int extract_or_test_files(__G)    /* return PK-type er
+             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 */
+@@ -1062,6 +1205,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;
+ 
 @@ -1255,8 +1257,17 @@ static int extract_or_test_entrylist(__G__ numchunk,
          if (G.lrec.compression_method == STORED) {
              zusz_t csiz_decrypted = G.lrec.csize;
@@ -50,6 +235,60 @@ Fix CVE-2015-7697: infinite loop when ex
              if (G.lrec.ucsize != csiz_decrypted) {
                  Info(slide, 0x401, ((char *)slide,
                    LoadFarStringSmall2(WrnStorUCSizCSizDiff),
+@@ -1602,6 +1750,18 @@ reprompt:
+             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
+@@ -2003,6 +2163,34 @@ static int extract_or_test_member(__G)    /* return PK
+     }
+ 
+     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() */
 @@ -2023,7 +2034,8 @@ static int TestExtraField(__G__ ef, ef_len)
          ebID = makeword(ef);
          ebLen = (unsigned)makeword(ef+EB_LEN);
Index: archivers/unzip/patches/patch-fileio_c
===================================================================
RCS file: /cvs/ports/archivers/unzip/patches/patch-fileio_c,v
retrieving revision 1.1
diff -u -p -r1.1 patch-fileio_c
--- archivers/unzip/patches/patch-fileio_c      6 Feb 2015 21:37:04 -0000       
1.1
+++ archivers/unzip/patches/patch-fileio_c      20 Feb 2020 08:06:53 -0000
@@ -1,6 +1,10 @@
 $OpenBSD: patch-fileio_c,v 1.1 2015/02/06 21:37:04 naddy Exp $
 
 Fix CVE-2014-8141: out-of-bounds read issues in getZip64Data()
+Fix CVE-2018-1000035: buffer overflow for password-protected archives
+https://security-tracker.debian.org/tracker/CVE-2018-1000035
+Fix CVE-2019-13232: a zip bomb using overlapped entries
+https://github.com/madler/unzip/commit/47b3ceae397d21bf822bc2ac73052a4b1daf8e1c
 
 --- fileio.c.orig      Mon Apr 20 02:03:44 2009
 +++ fileio.c   Thu Feb  5 18:57:59 2015
@@ -13,6 +17,48 @@ Fix CVE-2014-8141: out-of-bounds read is
  
  #ifdef WINDLL
     static ZCONST char Far DiskFullQuery[] =
+@@ -532,8 +532,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;
+@@ -1613,7 +1613,11 @@ int UZ_EXP UzpPassword (pG, rcnt, pwbuf,
+     int r = IZ_PW_ENTERED;
+     char *m;
+     char *prompt;
+-
++    char *zfnf;
++    char *efnf;
++    size_t zfnfl;
++    int isOverflow;
++    
+ #ifndef REENTRANT
+     /* tell picky compilers to shut up about "unused variable" warnings */
+     pG = pG;
+@@ -1621,7 +1625,15 @@ int UZ_EXP UzpPassword (pG, rcnt, pwbuf,
+ 
+     if (*rcnt == 0) {           /* First call for current entry */
+         *rcnt = 2;
+-        if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) {
++        zfnf = FnFilter1(zfn);
++        efnf = FnFilter2(efn);
++        zfnfl = strlen(zfnf);
++        isOverflow = TRUE;
++        if (2*FILNAMSIZ >= zfnfl && (2*FILNAMSIZ - zfnfl) >= strlen(efnf))
++        {
++              isOverflow = FALSE;
++        }
++        if ((isOverflow == FALSE) && ((prompt = (char *)malloc(2*FILNAMSIZ + 
15)) != (char *)NULL)) {
+             sprintf(prompt, LoadFarString(PasswPrompt),
+                     FnFilter1(zfn), FnFilter2(efn));
+             m = prompt;
 @@ -2295,7 +2297,12 @@ int do_string(__G__ length, option)   /* return PK-typ
              if (readbuf(__G__ (char *)G.extra_field, length) == 0)
                  return PK_EOF;
Index: archivers/unzip/patches/patch-globals_c
===================================================================
RCS file: archivers/unzip/patches/patch-globals_c
diff -N archivers/unzip/patches/patch-globals_c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ archivers/unzip/patches/patch-globals_c     20 Feb 2020 08:50:28 -0000
@@ -0,0 +1,15 @@
+$OpenBSD$
+
+Fix CVE-2019-13232: a zip bomb using overlapped entries
+https://github.com/madler/unzip/commit/47b3ceae397d21bf822bc2ac73052a4b1daf8e1c
+
+--- globals.c.orig
++++ 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);
Index: archivers/unzip/patches/patch-globals_h
===================================================================
RCS file: archivers/unzip/patches/patch-globals_h
diff -N archivers/unzip/patches/patch-globals_h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ archivers/unzip/patches/patch-globals_h     20 Feb 2020 08:50:48 -0000
@@ -0,0 +1,23 @@
+$OpenBSD$
+
+Fix CVE-2019-13232: a zip bomb using overlapped entries
+https://github.com/madler/unzip/commit/47b3ceae397d21bf822bc2ac73052a4b1daf8e1c
+
+--- glabals.h.orig
++++ 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 
*/
Index: archivers/unzip/patches/patch-list_c
===================================================================
RCS file: /cvs/ports/archivers/unzip/patches/patch-list_c,v
retrieving revision 1.1
diff -u -p -r1.1 patch-list_c
--- archivers/unzip/patches/patch-list_c        23 Mar 2017 17:26:17 -0000      
1.1
+++ archivers/unzip/patches/patch-list_c        20 Feb 2020 07:41:50 -0000
@@ -1,14 +1,16 @@
 $OpenBSD: patch-list_c,v 1.1 2017/03/23 17:26:17 bluhm Exp $
 
-Fix: increase size of cfactorstr array to avoid buffer overflow
+Fix CVE-2018-18384: increase size of cfactorstr array to avoid buffer overflow
     https://bugs.debian.org/741384
+    https://sourceforge.net/p/infozip/bugs/53/
 Fix CVE-2014-9913: buffer overflow in unzip
     https://sourceforge.net/p/infozip/bugs/27/
     https://bugs.debian.org/847485
     https://launchpad.net/bugs/387350
 
---- list.c.orig        Sun Feb  8 18:11:34 2009
-+++ list.c     Tue Mar 21 16:10:27 2017
+Index: list.c
+--- list.c.orig
++++ 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;
@@ -38,3 +40,27 @@ Fix CVE-2014-9913: buffer overflow in un
              }
  
  #if 0       /* GRR/Euro:  add this? */
+@@ -378,9 +389,9 @@ int list_files(__G)    /* return PK-type error code */
+             }
+ #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,
+@@ -460,9 +471,9 @@ int list_files(__G)    /* return PK-type error code */
+ 
+ #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"),
Index: archivers/unzip/patches/patch-process_c
===================================================================
RCS file: /cvs/ports/archivers/unzip/patches/patch-process_c,v
retrieving revision 1.3
diff -u -p -r1.3 patch-process_c
--- archivers/unzip/patches/patch-process_c     23 Mar 2017 17:26:17 -0000      
1.3
+++ archivers/unzip/patches/patch-process_c     20 Feb 2020 08:48:45 -0000
@@ -8,6 +8,8 @@ Fix: do not ignore extra fields containi
     https://bugs.debian.org/842993
 Fix: restore uid and gid information when requested
     https://bugs.debian.org/689212
+Fix CVE-2019-13232: a zip bomb using overlapped entries
+https://github.com/madler/unzip/commit/47b3ceae397d21bf822bc2ac73052a4b1daf8e1c
 
 --- process.c.orig     Fri Mar  6 02:25:10 2009
 +++ process.c  Tue Mar 21 16:10:27 2017
Index: archivers/unzip/patches/patch-unzip_h
===================================================================
RCS file: archivers/unzip/patches/patch-unzip_h
diff -N archivers/unzip/patches/patch-unzip_h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ archivers/unzip/patches/patch-unzip_h       20 Feb 2020 08:56:01 -0000
@@ -0,0 +1,14 @@
+$OpenBSD$
+
+Fix CVE-2019-13232: a zip bomb using overlapped entries
+https://github.com/madler/unzip/commit/47b3ceae397d21bf822bc2ac73052a4b1daf8e1c
+
+--- unzip.h.orig
++++ 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 */

Reply via email to