From 41f0608645155d78ec249b8bf51687fb8bf0a938 Mon Sep 17 00:00:00 2001 From: lipengyu Date: Thu, 20 Aug 2026 09:59:31 +0800 Subject: [PATCH 1/2] gh-156078: Prevent ZipFile.mkdir() during an active write Fix `ZipFile.mkdir()` so that it raises `ValueError` when another writable member handle returned by `ZipFile.open(..., mode="w")` is still open. --- Lib/test/test_zipfile/test_core.py | 2 ++ Lib/zipfile/__init__.py | 5 +++++ .../Library/2026-08-20-09-56-45.gh-issue-156078.-E7gZc.rst | 3 +++ 3 files changed, 10 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-08-20-09-56-45.gh-issue-156078.-E7gZc.rst diff --git a/Lib/test/test_zipfile/test_core.py b/Lib/test/test_zipfile/test_core.py index 1c6e3a9f0a9a2de..a2dcbc36352ec14 100644 --- a/Lib/test/test_zipfile/test_core.py +++ b/Lib/test/test_zipfile/test_core.py @@ -4598,6 +4598,8 @@ def test_open_conflicting_handles(self): zipf.writestr('str', 'abcde') with self.assertRaises(ValueError): zipf.write(__file__, 'file') + with self.assertRaises(ValueError): + zipf.mkdir('directory') with self.assertRaises(ValueError): zipf.close() w1.write(msg2) diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py index 7a81aa8f44c8f4c..1868d467161bd6e 100644 --- a/Lib/zipfile/__init__.py +++ b/Lib/zipfile/__init__.py @@ -2596,6 +2596,11 @@ def mkdir(self, zinfo_or_directory_name, mode=511): else: raise TypeError("Expected type str or ZipInfo") + if self._writing: + raise ValueError( + "Can't write to ZIP archive while an open writing handle exists." + ) + with self._lock: if self._seekable: self.fp.seek(self.start_dir) diff --git a/Misc/NEWS.d/next/Library/2026-08-20-09-56-45.gh-issue-156078.-E7gZc.rst b/Misc/NEWS.d/next/Library/2026-08-20-09-56-45.gh-issue-156078.-E7gZc.rst new file mode 100644 index 000000000000000..43c35dba56a4b7b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-08-20-09-56-45.gh-issue-156078.-E7gZc.rst @@ -0,0 +1,3 @@ +Fix :meth:`zipfile.ZipFile.mkdir` to raise :exc:`ValueError` when called +while a writable member handle is open, preventing corruption of the ZIP +archive. From 60a6c3815720b7cb6ddb5521366b2df0b0640195 Mon Sep 17 00:00:00 2001 From: lipengyu Date: Thu, 20 Aug 2026 19:01:02 +0800 Subject: [PATCH 2/2] Add the missing closed-archive check --- Lib/test/test_zipfile/test_core.py | 3 +++ Lib/zipfile/__init__.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Lib/test/test_zipfile/test_core.py b/Lib/test/test_zipfile/test_core.py index a2dcbc36352ec14..f37696be8a3eb4b 100644 --- a/Lib/test/test_zipfile/test_core.py +++ b/Lib/test/test_zipfile/test_core.py @@ -5520,6 +5520,9 @@ def test_mkdir(self): zf.extractall(target) self.assertEqual(set(os.listdir(target)), {"directory", "directory2", "directory3", "directory4"}) + with self.assertRaises(ValueError): + zf.mkdir("closed") + def test_create_directory_with_write(self): with zipfile.ZipFile(TESTFN, "w") as zf: zf.writestr(zipfile.ZipInfo('directory/'), '') diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py index 1868d467161bd6e..36e844a3f9089b7 100644 --- a/Lib/zipfile/__init__.py +++ b/Lib/zipfile/__init__.py @@ -2596,6 +2596,9 @@ def mkdir(self, zinfo_or_directory_name, mode=511): else: raise TypeError("Expected type str or ZipInfo") + if not self.fp: + raise ValueError( + "Attempt to write to ZIP archive that was already closed") if self._writing: raise ValueError( "Can't write to ZIP archive while an open writing handle exists."