gh-91387: Strip trailing slash from tarfile longname directories (GH-32423)

Co-authored-by: Brett Cannon <brett@python.org>
(cherry picked from commit c1e19421c2)

Co-authored-by: Chris Fernald <chrisf671@gmail.com>
This commit is contained in:
Miss Islington (bot) 2022-06-21 11:09:07 -07:00 committed by GitHub
parent cc42716275
commit f6d777ce38
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 0 deletions

View file

@ -1163,6 +1163,11 @@ class TarInfo(object):
# header information. # header information.
self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors) self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors)
# Remove redundant slashes from directories. This is to be consistent
# with frombuf().
if self.isdir():
self.name = self.name.rstrip("/")
return self return self
def _proc_gnulong(self, tarfile): def _proc_gnulong(self, tarfile):
@ -1185,6 +1190,11 @@ class TarInfo(object):
elif self.type == GNUTYPE_LONGLINK: elif self.type == GNUTYPE_LONGLINK:
next.linkname = nts(buf, tarfile.encoding, tarfile.errors) next.linkname = nts(buf, tarfile.encoding, tarfile.errors)
# Remove redundant slashes from directories. This is to be consistent
# with frombuf().
if next.isdir():
next.name = next.name.removesuffix("/")
return next return next
def _proc_sparse(self, tarfile): def _proc_sparse(self, tarfile):

View file

@ -228,6 +228,7 @@ class UstarReadTest(ReadTest, unittest.TestCase):
def add_dir_and_getmember(self, name): def add_dir_and_getmember(self, name):
with os_helper.temp_cwd(): with os_helper.temp_cwd():
with tarfile.open(tmpname, 'w') as tar: with tarfile.open(tmpname, 'w') as tar:
tar.format = tarfile.USTAR_FORMAT
try: try:
os.mkdir(name) os.mkdir(name)
tar.add(name) tar.add(name)
@ -1020,11 +1021,26 @@ class LongnameTest:
"iso8859-1", "strict") "iso8859-1", "strict")
self.assertEqual(tarinfo.type, self.longnametype) self.assertEqual(tarinfo.type, self.longnametype)
def test_longname_directory(self):
# Test reading a longlink directory. Issue #47231.
longdir = ('a' * 101) + '/'
with os_helper.temp_cwd():
with tarfile.open(tmpname, 'w') as tar:
tar.format = self.format
try:
os.mkdir(longdir)
tar.add(longdir)
finally:
os.rmdir(longdir)
with tarfile.open(tmpname) as tar:
self.assertIsNotNone(tar.getmember(longdir))
self.assertIsNotNone(tar.getmember(longdir.removesuffix('/')))
class GNUReadTest(LongnameTest, ReadTest, unittest.TestCase): class GNUReadTest(LongnameTest, ReadTest, unittest.TestCase):
subdir = "gnu" subdir = "gnu"
longnametype = tarfile.GNUTYPE_LONGNAME longnametype = tarfile.GNUTYPE_LONGNAME
format = tarfile.GNU_FORMAT
# Since 3.2 tarfile is supposed to accurately restore sparse members and # Since 3.2 tarfile is supposed to accurately restore sparse members and
# produce files with holes. This is what we actually want to test here. # produce files with holes. This is what we actually want to test here.
@ -1084,6 +1100,7 @@ class PaxReadTest(LongnameTest, ReadTest, unittest.TestCase):
subdir = "pax" subdir = "pax"
longnametype = tarfile.XHDTYPE longnametype = tarfile.XHDTYPE
format = tarfile.PAX_FORMAT
def test_pax_global_headers(self): def test_pax_global_headers(self):
tar = tarfile.open(tarname, encoding="iso8859-1") tar = tarfile.open(tarname, encoding="iso8859-1")

View file

@ -0,0 +1 @@
Fixed an issue with inconsistent trailing slashes in tarfile longname directories.