Skip to content

Commit 567ab3b

Browse files
gh-117084: Fix ZIP file extraction for directory entry names with backslashes on Windows (GH-117129)
1 parent 5a78f6e commit 567ab3b

File tree

4 files changed

+27
-1
lines changed

4 files changed

+27
-1
lines changed
192 Bytes
Binary file not shown.

Lib/test/test_zipfile/test_core.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2937,6 +2937,22 @@ def test_bug_6050(self):
29372937
os.mkdir(os.path.join(TESTFN2, "a"))
29382938
self.test_extract_dir()
29392939

2940+
def test_extract_dir_backslash(self):
2941+
zfname = findfile("zipdir_backslash.zip", subdir="archivetestdata")
2942+
with zipfile.ZipFile(zfname) as zipf:
2943+
zipf.extractall(TESTFN2)
2944+
if os.name == 'nt':
2945+
self.assertTrue(os.path.isdir(os.path.join(TESTFN2, "a")))
2946+
self.assertTrue(os.path.isdir(os.path.join(TESTFN2, "a", "b")))
2947+
self.assertTrue(os.path.isfile(os.path.join(TESTFN2, "a", "b", "c")))
2948+
self.assertTrue(os.path.isdir(os.path.join(TESTFN2, "d")))
2949+
self.assertTrue(os.path.isdir(os.path.join(TESTFN2, "d", "e")))
2950+
else:
2951+
self.assertTrue(os.path.isfile(os.path.join(TESTFN2, "a\\b\\c")))
2952+
self.assertTrue(os.path.isfile(os.path.join(TESTFN2, "d\\e\\")))
2953+
self.assertFalse(os.path.exists(os.path.join(TESTFN2, "a")))
2954+
self.assertFalse(os.path.exists(os.path.join(TESTFN2, "d")))
2955+
29402956
def test_write_dir(self):
29412957
dirpath = os.path.join(TESTFN2, "x")
29422958
os.mkdir(dirpath)

Lib/zipfile/__init__.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,15 @@ def from_file(cls, filename, arcname=None, *, strict_timestamps=True):
605605

606606
def is_dir(self):
607607
"""Return True if this archive member is a directory."""
608-
return self.filename.endswith('/')
608+
if self.filename.endswith('/'):
609+
return True
610+
# The ZIP format specification requires to use forward slashes
611+
# as the directory separator, but in practice some ZIP files
612+
# created on Windows can use backward slashes. For compatibility
613+
# with the extraction code which already handles this:
614+
if os.path.altsep:
615+
return self.filename.endswith((os.path.sep, os.path.altsep))
616+
return False
609617

610618

611619
# ZIP encryption uses the CRC32 one-byte primitive for scrambling some
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :mod:`zipfile` extraction for directory entries with the name containing
2+
backslashes on Windows.

0 commit comments

Comments
 (0)