Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Lib/tarfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -1425,7 +1425,7 @@ def _proc_gnulong(self, tarfile):
# Remove redundant slashes from directories. This is to be consistent
# with frombuf().
if next.isdir():
next.name = next.name.removesuffix("/")
next.name = next.name.rstrip("/")

return next

Expand Down
21 changes: 21 additions & 0 deletions Lib/test/test_tarfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -1313,6 +1313,27 @@ def _fs_supports_holes():
else:
return False

def test_gnulong_dirname_strips_all_trailing_slashes(self):
# gh-149980: _proc_gnulong must normalize trailing slashes the same
# way _frombuf and _proc_builtin do (rstrip, not removesuffix), so
# a GNU long-name directory entry agrees with a short-name one.
long_name = "a" * 120 + "///" # > 100 bytes => GNUTYPE_LONGNAME
short_name = "b" * 20 + "///"

buf = io.BytesIO()
with tarfile.open(fileobj=buf, mode="w",
format=tarfile.GNU_FORMAT) as tar:
for name in (short_name, long_name):
info = tarfile.TarInfo(name=name)
info.type = tarfile.DIRTYPE
tar.addfile(info)

buf.seek(0)
with tarfile.open(fileobj=buf, mode="r") as tar:
names = [m.name for m in tar.getmembers()]

self.assertEqual(names, ["b" * 20, "a" * 120])


class PaxReadTest(LongnameTest, ReadTest, unittest.TestCase):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix :mod:`tarfile` so that GNU long-name directory entries have all
trailing slashes stripped from their names, matching the behavior for
short-name entries. Previously, only a single trailing slash was removed.
Loading