https://github.com/python/cpython/commit/fefc0b4e84a7852fd5c72625465cdfa25376e403
commit: fefc0b4e84a7852fd5c72625465cdfa25376e403
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: hugovk <[email protected]>
date: 2026-07-17T23:37:49+03:00
summary:

[3.15] gh-151669: Normalize symlink targets in tarfile.TarFile.gettarinfo() 
(GH-151671) (#153517)

Co-authored-by: Daniele Nicolodi <[email protected]>

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 bad9e2d8dff37f6..ae75d14a3088ba9 100644
--- a/Doc/whatsnew/3.15.rst
+++ b/Doc/whatsnew/3.15.rst
@@ -1541,6 +1541,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 8c058357f114ad7..fe28ea68cfd1322 100644
--- a/Lib/tarfile.py
+++ b/Lib/tarfile.py
@@ -2275,7 +2275,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 9615547fc22dfa7..2c6f0da7887f53e 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -1647,6 +1647,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 000000000000000..d8e4850ba94e140
--- /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]

Reply via email to