Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Lib/test/test_zipfile/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2128,6 +2128,20 @@ def test_is_zip_valid_file(self):
self.assertTrue(zipfile.is_zipfile(fp))
self.assertEqual(fp.tell(), mid)

def test_is_zip_bad_central_directory_offset(self):
"""Check that is_zipfile() rejects a central directory before the file."""
fp = io.BytesIO()
with zipfile.ZipFile(fp, mode="w") as zipf:
zipf.writestr("foo.txt", b"O, for a Muse of Fire!")
data = bytearray(fp.getvalue())
endrec = len(data) - zipfile.sizeEndCentDir
struct.pack_into("<L", data, endrec + 12, len(data))
fp = io.BytesIO(data)
pos = fp.seek(5)
self.assertFalse(zipfile.is_zipfile(fp))
self.assertEqual(fp.tell(), pos)
self.assertRaises(zipfile.BadZipFile, zipfile.ZipFile, io.BytesIO(data))

def test_non_existent_file_raises_OSError(self):
# make sure we don't raise an AttributeError when a partially-constructed
# ZipFile instance is finalized; this tests for regression on SF tracker
Expand Down
5 changes: 3 additions & 2 deletions Lib/zipfile/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,9 @@ def _check_zipfile(fp):
return True # Empty zipfiles are still zipfiles
elif endrec[_ECD_DISK_NUMBER] == endrec[_ECD_DISK_START]:
# Central directory is on the same disk
fp.seek(sum(_handle_prepended_data(endrec)))
if endrec[_ECD_SIZE] >= sizeCentralDir:
start_dir = sum(_handle_prepended_data(endrec))
if start_dir >= 0 and endrec[_ECD_SIZE] >= sizeCentralDir:
fp.seek(start_dir)
data = fp.read(sizeCentralDir) # CD is where we expect it to be
if len(data) == sizeCentralDir:
centdir = struct.unpack(structCentralDir, data) # CD is the right size
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Fix :func:`zipfile.is_zipfile` raising :exc:`ValueError` instead of returning
``False`` for a file-like object, such as :class:`io.BytesIO`, whose end of
central directory record places the central directory before the start of the
file.
Loading