Issue #4844: ZipFile now raises BadZipfile when opens a ZIP file with an
incomplete "End of Central Directory" record.  Original patch by Guilherme
Polo and Alan McIntyre.
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index f340aa6..9dc4f57 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -166,6 +166,8 @@
         return endrec
 
     data = fpin.read(sizeEndCentDir64Locator)
+    if len(data) != sizeEndCentDir64Locator:
+        return endrec
     sig, diskno, reloff, disks = struct.unpack(structEndArchive64Locator, data)
     if sig != stringEndArchive64Locator:
         return endrec
@@ -176,6 +178,8 @@
     # Assume no 'zip64 extensible data'
     fpin.seek(offset - sizeEndCentDir64Locator - sizeEndCentDir64, 2)
     data = fpin.read(sizeEndCentDir64)
+    if len(data) != sizeEndCentDir64:
+        return endrec
     sig, sz, create_version, read_version, disk_num, disk_dir, \
             dircount, dircount2, dirsize, diroffset = \
             struct.unpack(structEndArchive64, data)
@@ -211,7 +215,9 @@
     except IOError:
         return None
     data = fpin.read()
-    if data[0:4] == stringEndArchive and data[-2:] == "\000\000":
+    if (len(data) == sizeEndCentDir and
+        data[0:4] == stringEndArchive and
+        data[-2:] == b"\000\000"):
         # the signature is correct and there's no comment, unpack structure
         endrec = struct.unpack(structEndArchive, data)
         endrec=list(endrec)
@@ -235,6 +241,9 @@
     if start >= 0:
         # found the magic number; attempt to unpack and interpret
         recData = data[start:start+sizeEndCentDir]
+        if len(recData) != sizeEndCentDir:
+            # Zip file is corrupted.
+            return None
         endrec = list(struct.unpack(structEndArchive, recData))
         commentSize = endrec[_ECD_COMMENT_SIZE] #as claimed by the zip file
         comment = data[start+sizeEndCentDir:start+sizeEndCentDir+commentSize]
@@ -246,7 +255,7 @@
                              endrec)
 
     # Unable to find a valid end of central directory structure
-    return
+    return None
 
 
 class ZipInfo (object):
@@ -818,9 +827,11 @@
         total = 0
         while total < size_cd:
             centdir = fp.read(sizeCentralDir)
-            if centdir[0:4] != stringCentralDir:
-                raise BadZipfile, "Bad magic number for central directory"
+            if len(centdir) != sizeCentralDir:
+                raise BadZipfile("Truncated central directory")
             centdir = struct.unpack(structCentralDir, centdir)
+            if centdir[_CD_SIGNATURE] != stringCentralDir:
+                raise BadZipfile("Bad magic number for central directory")
             if self.debug > 2:
                 print centdir
             filename = fp.read(centdir[_CD_FILENAME_LENGTH])
@@ -948,10 +959,12 @@
 
             # Skip the file header:
             fheader = zef_file.read(sizeFileHeader)
-            if fheader[0:4] != stringFileHeader:
-                raise BadZipfile, "Bad magic number for file header"
-
+            if len(fheader) != sizeFileHeader:
+                raise BadZipfile("Truncated file header")
             fheader = struct.unpack(structFileHeader, fheader)
+            if fheader[_FH_SIGNATURE] != stringFileHeader:
+                raise BadZipfile("Bad magic number for file header")
+
             fname = zef_file.read(fheader[_FH_FILENAME_LENGTH])
             if fheader[_FH_EXTRA_FIELD_LENGTH]:
                 zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH])