diff --git a/Lib/test/test_zipfile/test_core.py b/Lib/test/test_zipfile/test_core.py index ab1995e91286e6..84000f472c4df9 100644 --- a/Lib/test/test_zipfile/test_core.py +++ b/Lib/test/test_zipfile/test_core.py @@ -4300,6 +4300,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("= 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 diff --git a/Misc/NEWS.d/next/Library/2026-10-22-05-21-00.gh-issue-161094.MDjCNm.rst b/Misc/NEWS.d/next/Library/2026-10-22-05-21-00.gh-issue-161094.MDjCNm.rst new file mode 100644 index 00000000000000..716da00504cc59 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-22-05-21-00.gh-issue-161094.MDjCNm.rst @@ -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.