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

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