https://github.com/python/cpython/commit/5775aa8e295102156de14fd1ba284722c6ede95a
commit: 5775aa8e295102156de14fd1ba284722c6ede95a
branch: main
author: ankhikarmakar <[email protected]>
committer: encukou <[email protected]>
date: 2026-05-18T19:31:15Z
summary:

gh-149980: Strip all trailing slashes from GNU long directory names in tarfile 
(GH-150019)

files:
A Misc/NEWS.d/next/Library/2026-05-19-12-00-00.gh-issue-149980.Kx7p2A.rst
M Lib/tarfile.py
M Lib/test/test_tarfile.py

diff --git a/Lib/tarfile.py b/Lib/tarfile.py
index 772b51295fcfbe..87500c726ce9a8 100644
--- a/Lib/tarfile.py
+++ b/Lib/tarfile.py
@@ -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
 
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index 8e213a8f999218..02fd9620bcf33d 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -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):
 
diff --git 
a/Misc/NEWS.d/next/Library/2026-05-19-12-00-00.gh-issue-149980.Kx7p2A.rst 
b/Misc/NEWS.d/next/Library/2026-05-19-12-00-00.gh-issue-149980.Kx7p2A.rst
new file mode 100644
index 00000000000000..b056f6a3cda25d
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-05-19-12-00-00.gh-issue-149980.Kx7p2A.rst
@@ -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.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to