diff --git a/Lib/test/test_zipfile/test_core.py b/Lib/test/test_zipfile/test_core.py index ffed328b171fda2..f51093a52eda16d 100644 --- a/Lib/test/test_zipfile/test_core.py +++ b/Lib/test/test_zipfile/test_core.py @@ -2711,6 +2711,16 @@ def test_overlap_with_archive_comment(self): with self.assertRaisesRegex(zipfile.BadZipFile, 'Overlapped entries'): zipf.read('a') + def test_reading_archive_member_starts_with_slash(self): + member_path = '/folder/file.txt' + member_data = b'hello world' + with open(TESTFN, "wb") as f: + f.write(member_data) + with zipfile.ZipFile(TESTFN2, 'w') as zf: + zf.write(TESTFN, member_path) + with zipfile.ZipFile(TESTFN2) as zf: + self.assertEqual(zf.read(member_path), member_data) + def tearDown(self): unlink(TESTFN) unlink(TESTFN2) diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py index 005b6f4eb840448..47b548a41d38a42 100644 --- a/Lib/zipfile/__init__.py +++ b/Lib/zipfile/__init__.py @@ -644,7 +644,10 @@ def from_file(cls, filename, arcname=None, *, strict_timestamps=True): if arcname is None: arcname = filename arcname = os.path.normpath(os.path.splitdrive(arcname)[1]) - while arcname[0] in (os.sep, os.altsep): + while (arcname[0] in (os.sep, os.altsep) and + arcname[1] in (os.sep, os.altsep)): + arcname = arcname[1:] + if arcname[0] in (os.sep, os.altsep) and os.sep not in arcname[1:]: arcname = arcname[1:] if isdir: arcname += '/' diff --git a/Misc/NEWS.d/next/Library/2020-10-22-07-07-17.bpo-42112.Z_ED9N.rst b/Misc/NEWS.d/next/Library/2020-10-22-07-07-17.bpo-42112.Z_ED9N.rst new file mode 100644 index 000000000000000..fdda11afbbb884e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-10-22-07-07-17.bpo-42112.Z_ED9N.rst @@ -0,0 +1,2 @@ +Fix unnecessary removing of a leading slash in :meth:`zipfile.ZipInfo.from_file` +when member's archive name is in the form of :code:`/directory/filename`.