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

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