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

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