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