]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.15] gh-151669: Normalize symlink targets in tarfile.TarFile.gettarinfo() (GH-15167...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 17 Jul 2026 20:37:49 +0000 (22:37 +0200)
committerGitHub <noreply@github.com>
Fri, 17 Jul 2026 20:37:49 +0000 (23:37 +0300)
Co-authored-by: Daniele Nicolodi <daniele@grinta.net>
Doc/whatsnew/3.15.rst
Lib/tarfile.py
Lib/test/test_tarfile.py
Misc/NEWS.d/next/Library/2026-06-24-23-28-42.gh-issue-151669.tPUavQ.rst [new file with mode: 0644]

index bad9e2d8dff37f66ad10414c97fc66b3659e1731..ae75d14a3088ba90c87fa828ec148602a43bd31c 100644 (file)
@@ -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
index 8c058357f114ad76386a1a96f6cad593e22974f7..fe28ea68cfd1322e26ca41d774104ead24dcd186 100644 (file)
@@ -2275,7 +2275,7 @@ class TarFile(object):
             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):
index 9615547fc22dfa72148577347f6103d1cb3ff0a8..2c6f0da7887f53e40d6a894144a772a79f77ef93 100644 (file)
@@ -1647,6 +1647,22 @@ class WriteTest(WriteTestBase, unittest.TestCase):
         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 (file)
index 0000000..d8e4850
--- /dev/null
@@ -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.