[Python-checkins] cpython (merge 3.2 -> 3.3): Issue #4844: ZipFile now raises BadZipFile when opens a ZIP file with an

serhiy.storchaka python-checkins at python.org
Thu Jan 31 14:33:43 CET 2013


http://hg.python.org/cpython/rev/46f24a18a4ab
changeset: 81849:46f24a18a4ab
branch: 3.3
parent: 81845:d218ecb7392d
parent: 81848:01147e468c8c
user: Serhiy Storchaka <storchaka at gmail.com>
date: Thu Jan 31 15:29:20 2013 +0200
summary:
 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.
files:
 Lib/test/test_zipfile.py | 14 ++++++++++++++
 Lib/zipfile.py | 25 +++++++++++++++++++------
 Misc/NEWS | 4 ++++
 3 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -996,6 +996,20 @@
 chk = zipfile.is_zipfile(fp)
 self.assertTrue(not chk)
 
+ def test_damaged_zipfile(self):
+ """Check that zipfiles with missing bytes at the end raise BadZipFile."""
+ # - Create a valid zip file
+ fp = io.BytesIO()
+ with zipfile.ZipFile(fp, mode="w") as zipf:
+ zipf.writestr("foo.txt", b"O, for a Muse of Fire!")
+ zipfiledata = fp.getvalue()
+
+ # - Now create copies of it missing the last N bytes and make sure
+ # a BadZipFile exception is raised when we try to open it
+ for N in range(len(zipfiledata)):
+ fp = io.BytesIO(zipfiledata[:N])
+ self.assertRaises(zipfile.BadZipFile, zipfile.ZipFile, fp)
+
 def test_is_zip_valid_file(self):
 """Check that is_zipfile() correctly identifies zip files."""
 # - passing a filename
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -196,6 +196,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
@@ -206,6 +208,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)
@@ -241,7 +245,9 @@
 except IOError:
 return None
 data = fpin.read()
- if data[0:4] == stringEndArchive and data[-2:] == b"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)
@@ -265,6 +271,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]
@@ -276,7 +285,7 @@
 endrec)
 
 # Unable to find a valid end of central directory structure
- return
+ return None
 
 
 class ZipInfo (object):
@@ -978,9 +987,11 @@
 total = 0
 while total < size_cd:
 centdir = fp.read(sizeCentralDir)
- if centdir[0:4] != stringCentralDir:
+ 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")
- centdir = struct.unpack(structCentralDir, centdir)
 if self.debug > 2:
 print(centdir)
 filename = fp.read(centdir[_CD_FILENAME_LENGTH])
@@ -1123,10 +1134,12 @@
 
 # Skip the file header:
 fheader = zef_file.read(sizeFileHeader)
- if fheader[0:4] != stringFileHeader:
+ 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")
 
- fheader = struct.unpack(structFileHeader, fheader)
 fname = zef_file.read(fheader[_FH_FILENAME_LENGTH])
 if fheader[_FH_EXTRA_FIELD_LENGTH]:
 zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH])
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -164,6 +164,10 @@
 Library
 -------
 
+- 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.
+
 - Issue #17071: Signature.bind() now works when one of the keyword arguments
 is named ``self``.
 
-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /