gh-117084: Fix ZIP file extraction for directory entry names with backslashes on Windows (GH-117129)

This commit is contained in:
Serhiy Storchaka 2024-03-22 20:08:00 +02:00 committed by GitHub
parent 5a78f6e798
commit 567ab3bd15
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 27 additions and 1 deletions

Binary file not shown.

View File

@ -2937,6 +2937,22 @@ class TestWithDirectory(unittest.TestCase):
os.mkdir(os.path.join(TESTFN2, "a"))
self.test_extract_dir()
def test_extract_dir_backslash(self):
zfname = findfile("zipdir_backslash.zip", subdir="archivetestdata")
with zipfile.ZipFile(zfname) as zipf:
zipf.extractall(TESTFN2)
if os.name == 'nt':
self.assertTrue(os.path.isdir(os.path.join(TESTFN2, "a")))
self.assertTrue(os.path.isdir(os.path.join(TESTFN2, "a", "b")))
self.assertTrue(os.path.isfile(os.path.join(TESTFN2, "a", "b", "c")))
self.assertTrue(os.path.isdir(os.path.join(TESTFN2, "d")))
self.assertTrue(os.path.isdir(os.path.join(TESTFN2, "d", "e")))
else:
self.assertTrue(os.path.isfile(os.path.join(TESTFN2, "a\\b\\c")))
self.assertTrue(os.path.isfile(os.path.join(TESTFN2, "d\\e\\")))
self.assertFalse(os.path.exists(os.path.join(TESTFN2, "a")))
self.assertFalse(os.path.exists(os.path.join(TESTFN2, "d")))
def test_write_dir(self):
dirpath = os.path.join(TESTFN2, "x")
os.mkdir(dirpath)

View File

@ -605,7 +605,15 @@ class ZipInfo:
def is_dir(self):
"""Return True if this archive member is a directory."""
return self.filename.endswith('/')
if self.filename.endswith('/'):
return True
# The ZIP format specification requires to use forward slashes
# as the directory separator, but in practice some ZIP files
# created on Windows can use backward slashes. For compatibility
# with the extraction code which already handles this:
if os.path.altsep:
return self.filename.endswith((os.path.sep, os.path.altsep))
return False
# ZIP encryption uses the CRC32 one-byte primitive for scrambling some

View File

@ -0,0 +1,2 @@
Fix :mod:`zipfile` extraction for directory entries with the name containing
backslashes on Windows.