From 90cd990fa03348389c3912065a2407a9485d33a4 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" <68491+gpshead@users.noreply.github.com> Date: Sun, 1 Nov 2026 10:23:38 -0800 Subject: [PATCH] [3.15] gh-161094: Fix `zipfile.is_zipfile()` raising `ValueError` on file-like objects (GH-161095) Return False instead of seeking to a negative offset when the end of central directory record places the central directory before the start of the file. (cherry picked from commit 2789841a48f1edd8cfe1a9dc6e6c2b54c117d401) --- Lib/test/test_zipfile/test_core.py | 14 ++++++++++++++ Lib/zipfile/__init__.py | 5 +++-- .../2026-10-22-05-21-00.gh-issue-161094.MDjCNm.rst | 4 ++++ 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-10-22-05-21-00.gh-issue-161094.MDjCNm.rst diff --git a/Lib/test/test_zipfile/test_core.py b/Lib/test/test_zipfile/test_core.py index a969f9d5d9e486..21f95f8e421986 100644 --- a/Lib/test/test_zipfile/test_core.py +++ b/Lib/test/test_zipfile/test_core.py @@ -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("= 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.