Skip to content

Commit 688d39e

Browse files
yuanx749miss-islington
authored andcommitted
pythongh-127636: Fix tarfile extracting trailing slash member names (pythonGH-152984)
Fixes tarfile.TarFile.extract to accept archive member names with a trailing forward slash, including those returned by tarfile.TarFile.getnames very old style tar files may have these. new archivers likely do not do this. (cherry picked from commit 7a562c474c6885b1d6f3ac74962bb920483bfbe1) Co-authored-by: Xiao Yuan <47032563+yuanx749@users.noreply.github.com>
1 parent 59f15f3 commit 688d39e

3 files changed

Lines changed: 19 additions & 1 deletion

File tree

Lib/tarfile.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2127,7 +2127,9 @@ def getmember(self, name):
21272127
than once in the archive, its last occurrence is assumed to be the
21282128
most up-to-date version.
21292129
"""
2130-
tarinfo = self._getmember(name.rstrip('/'))
2130+
tarinfo = self._getmember(name)
2131+
if tarinfo is None and name.endswith('/'):
2132+
tarinfo = self._getmember(name.rstrip('/'))
21312133
if tarinfo is None:
21322134
raise KeyError("filename %r not found" % name)
21332135
return tarinfo

Lib/test/test_tarfile.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,19 @@ def test_add_dir_getmember(self):
242242
self.add_dir_and_getmember('bar')
243243
self.add_dir_and_getmember('a'*101)
244244

245+
def test_extract_name_with_trailing_slash(self):
246+
# gh-127636: './mydir/' is deliberately a regular-file member
247+
# (REGTYPE, not DIRTYPE) whose stored name ends in a slash. It
248+
# extracts as a file. Do not "fix" this by setting DIRTYPE; the
249+
# trailing-slash name on a non-directory is what is being tested.
250+
with tarfile.open(tmpname, 'w') as tar:
251+
tar.addfile(tarfile.TarInfo('./mydir/'))
252+
with os_helper.temp_dir() as tmpdir, tarfile.open(tmpname) as tar:
253+
names = tar.getnames()
254+
self.assertEqual(names, ['./mydir/'])
255+
tar.extract(names[0], tmpdir, filter='fully_trusted')
256+
self.assertTrue(os.path.isfile(os.path.join(tmpdir, 'mydir')))
257+
245258
@unittest.skipUnless(hasattr(os, "getuid") and hasattr(os, "getgid"),
246259
"Missing getuid or getgid implementation")
247260
def add_dir_and_getmember(self, name):
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix :meth:`tarfile.TarFile.extract` to accept archive member names with a
2+
trailing forward slash, including those returned by
3+
:meth:`tarfile.TarFile.getnames`. Contributed by Xiao Yuan.

0 commit comments

Comments
 (0)