https://github.com/python/cpython/commit/cc316410177c29f0398135f208e28e9525ca8bd9
commit: cc316410177c29f0398135f208e28e9525ca8bd9
branch: main
author: Daniele Nicolodi <[email protected]>
committer: encukou <[email protected]>
date: 2026-07-10T15:53:01+02:00
summary:
gh-151669: Normalize symlink targets in tarfile.TarFile.gettarinfo() (GH-151671)
This applies a normalization when creating members vrom the filesystem,
complementary to the one added to tarfile.TarFile.extract() in gh-138309
that does it in the other direction.
This solves an issue with round-tripping through the filesystem.
files:
A Misc/NEWS.d/next/Library/2026-06-24-23-28-42.gh-issue-151669.tPUavQ.rst
M Doc/whatsnew/3.15.rst
M Lib/tarfile.py
M Lib/test/test_tarfile.py
diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst
index aad4758297c30d..8cba187bf31dd1 100644
--- a/Doc/whatsnew/3.15.rst
+++ b/Doc/whatsnew/3.15.rst
@@ -1549,6 +1549,9 @@ tarfile
now replace slashes with backslashes in symlink targets on Windows to prevent
creation of corrupted links.
(Contributed by Christoph Walcher in :gh:`57911`.)
+* :func:`~tarfile.TarFile.gettarinfo` now replaces backslashes with slashes in
+ symlink targets on Windows to conform to the tar format standard.
(Contributed
+ by Daniele Nicolodi in :gh:`151669`.)
threading
diff --git a/Lib/tarfile.py b/Lib/tarfile.py
index 385dbb536d8a7d..5d5cef2f139a42 100644
--- a/Lib/tarfile.py
+++ b/Lib/tarfile.py
@@ -2255,7 +2255,7 @@ def gettarinfo(self, name=None, arcname=None,
fileobj=None):
type = FIFOTYPE
elif stat.S_ISLNK(stmd):
type = SYMTYPE
- linkname = os.readlink(name)
+ linkname = os.readlink(name).replace(os.sep, "/")
elif stat.S_ISCHR(stmd):
type = CHRTYPE
elif stat.S_ISBLK(stmd):
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index 2998a3667b4d17..514cfbb07cd76a 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -1668,6 +1668,22 @@ def test_symlink_size(self):
finally:
os_helper.unlink(path)
+ @os_helper.skip_unless_symlink
+ def test_symlink_target_normalization(self):
+ # Test for gh-151669.
+ path = os.path.join(TEMPDIR, "symlink")
+ target = "subdir/link/target"
+ os.symlink(target.replace("/", os.sep), path)
+ try:
+ tar = tarfile.open(tmpname, self.mode)
+ try:
+ tarinfo = tar.gettarinfo(path)
+ self.assertEqual(tarinfo.linkname, target)
+ finally:
+ tar.close()
+ finally:
+ os_helper.unlink(path)
+
def test_add_self(self):
# Test for #1257255.
dstname = os.path.abspath(tmpname)
diff --git
a/Misc/NEWS.d/next/Library/2026-06-24-23-28-42.gh-issue-151669.tPUavQ.rst
b/Misc/NEWS.d/next/Library/2026-06-24-23-28-42.gh-issue-151669.tPUavQ.rst
new file mode 100644
index 00000000000000..d8e4850ba94e14
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-06-24-23-28-42.gh-issue-151669.tPUavQ.rst
@@ -0,0 +1,3 @@
+On Windows, when populating tar archives from filesystem content, to
+conform to the tar format standard, backslashes in symlink targets are
+be replaced by slashes.
_______________________________________________
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]