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