Blame SOURCES/unzip-6.0-cve-2014-8141.patch

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