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

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