From b836b786faa2c80a2a44cd25b11268299cb77d66 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sun, 10 Dec 2023 22:08:48 +0800 Subject: [PATCH 1/4] allow / folder in a zipfile --- Lib/test/test_zipfile/_path/test_path.py | 12 ++++++++++++ Lib/zipfile/__init__.py | 3 --- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_zipfile/_path/test_path.py b/Lib/test/test_zipfile/_path/test_path.py index c66cb3cba69ebd..a5f1347044240c 100644 --- a/Lib/test/test_zipfile/_path/test_path.py +++ b/Lib/test/test_zipfile/_path/test_path.py @@ -577,3 +577,15 @@ def test_getinfo_missing(self, alpharep): zipfile.Path(alpharep) with self.assertRaises(KeyError): alpharep.getinfo('does-not-exist') + + def test_root_folder_in_zipfile(self): + """ + gh-112795: Some tools or self constructed codes will add '/' folder to + the zip file, this is a strange behavior, but we should support it. + """ + in_memory_file = io.BytesIO() + zf = zipfile.ZipFile(in_memory_file, "w") + zf.mkdir('/') + zf.writestr('./a.txt', 'aaa') + tmpdir = pathlib.Path(self.fixtures.enter_context(temp_dir())) + zf.extractall(tmpdir) \ No newline at end of file diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py index fe629ed1cf2fc5..48a8174c268852 100644 --- a/Lib/zipfile/__init__.py +++ b/Lib/zipfile/__init__.py @@ -1772,9 +1772,6 @@ def _extract_member(self, member, targetpath, pwd): # filter illegal characters on Windows arcname = self._sanitize_windows_name(arcname, os.path.sep) - if not arcname: - raise ValueError("Empty filename.") - targetpath = os.path.join(targetpath, arcname) targetpath = os.path.normpath(targetpath) From cad2a1ff520308242bb97b755107cc8013f9ea82 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sun, 10 Dec 2023 22:23:02 +0800 Subject: [PATCH 2/4] fix linter errors --- Lib/test/test_zipfile/_path/test_path.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_zipfile/_path/test_path.py b/Lib/test/test_zipfile/_path/test_path.py index a5f1347044240c..171ab6fdb5fc28 100644 --- a/Lib/test/test_zipfile/_path/test_path.py +++ b/Lib/test/test_zipfile/_path/test_path.py @@ -588,4 +588,4 @@ def test_root_folder_in_zipfile(self): zf.mkdir('/') zf.writestr('./a.txt', 'aaa') tmpdir = pathlib.Path(self.fixtures.enter_context(temp_dir())) - zf.extractall(tmpdir) \ No newline at end of file + zf.extractall(tmpdir) From 3773d986cec4493712af4afb5eb16bbb19368d0a Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Sat, 6 Jan 2024 15:44:26 -0800 Subject: [PATCH 3/4] Keep the empty filename check, just not on directories. --- Lib/zipfile/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py index 48a8174c268852..1c415a2eb7bc09 100644 --- a/Lib/zipfile/__init__.py +++ b/Lib/zipfile/__init__.py @@ -1772,6 +1772,9 @@ def _extract_member(self, member, targetpath, pwd): # filter illegal characters on Windows arcname = self._sanitize_windows_name(arcname, os.path.sep) + if not arcname and not member.is_dir(): + raise ValueError("Empty filename.") + targetpath = os.path.join(targetpath, arcname) targetpath = os.path.normpath(targetpath) From 0f05ac9d49911caa9de468076ee9b5f614bd4098 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith [Google LLC]" Date: Sun, 7 Jan 2024 00:56:48 +0000 Subject: [PATCH 4/4] NEWS entry. --- .../Library/2024-01-07-00-56-41.gh-issue-112932.OfhUu7.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2024-01-07-00-56-41.gh-issue-112932.OfhUu7.rst diff --git a/Misc/NEWS.d/next/Library/2024-01-07-00-56-41.gh-issue-112932.OfhUu7.rst b/Misc/NEWS.d/next/Library/2024-01-07-00-56-41.gh-issue-112932.OfhUu7.rst new file mode 100644 index 00000000000000..c61525ca67d2b0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-01-07-00-56-41.gh-issue-112932.OfhUu7.rst @@ -0,0 +1,3 @@ +Restore the ability for :mod:`zipfile` to ``extractall`` from zip files with +a "/" directory entry in them as is commonly added to zips by some wiki or +bug tracker data exporters.