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

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