https://github.com/python/cpython/commit/0a86a343f0aa2fb8624633712bccc929777907b6
commit: 0a86a343f0aa2fb8624633712bccc929777907b6
branch: main
author: Grant Herman <[email protected]>
committer: ethanfurman <[email protected]>
date: 2026-10-21T14:23:37-07:00
summary:

gh-150075: tar.addfile() now sets member offsets in active TarInfo (GH-150278)

The on-disk data was correct, but the in-memory TarInfo was not being properly 
updated.

---------

Signed-off-by: grantlouisherman <[email protected]>
Co-authored-by: Ethan Furman <[email protected]>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2026-05-21-14-21-06.gh-issue-150075.dLI21Z.rst
M Lib/tarfile.py
M Lib/test/test_tarfile.py

diff --git a/Lib/tarfile.py b/Lib/tarfile.py
index 3c3375ca77cb41..41394171832cbc 100644
--- a/Lib/tarfile.py
+++ b/Lib/tarfile.py
@@ -2456,11 +2456,14 @@ def addfile(self, tarinfo, fileobj=None):
             raise ValueError("fileobj not provided for non zero-size regular 
file")
 
         tarinfo = copy.copy(tarinfo)
-
+        # get current offset
+        tarinfo.offset = self.offset
         buf = tarinfo.tobuf(self.format, self.encoding, self.errors)
         self.fileobj.write(buf)
         self.offset += len(buf)
+        # add original offset to block size
         bufsize=self.copybufsize
+        tarinfo.offset_data = self.offset
         # If there's data to follow, append it.
         if fileobj is not None:
             copyfileobj(fileobj, self.fileobj, tarinfo.size, bufsize=bufsize)
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index 219a563a193be3..dba51d7131aa35 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -1700,6 +1700,29 @@ class WriteTest(WriteTestBase, unittest.TestCase):
 
     prefix = "w:"
 
+    def test_addfile_sets_offsets(self):
+        # gh-150075: addfile() must set offset and offset_data on the
+        # TarInfo stored in the archive so they match a subsequent read.
+        data = b"data"
+
+        with tarfile.open(tmpname, self.mode) as tar:
+            t1 = tarfile.TarInfo("test1.txt")
+            t1.size = len(data)
+            tar.addfile(t1, io.BytesIO(data))
+
+            t2 = tarfile.TarInfo("test2.txt")
+            t2.size = len(data)
+            tar.addfile(t2, io.BytesIO(data))
+
+            write_members = tar.getmembers()
+
+        with tarfile.open(tmpname) as tar:
+            read_members = tar.getmembers()
+
+        for w, r in zip(write_members, read_members):
+            self.assertEqual(w.offset, r.offset)
+            self.assertEqual(w.offset_data, r.offset_data)
+
     def test_100_char_name(self):
         # The name field in a tar header stores strings of at most 100 chars.
         # If a string is shorter than 100 chars it has to be padded with '\0',
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2026-05-21-14-21-06.gh-issue-150075.dLI21Z.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-21-14-21-06.gh-issue-150075.dLI21Z.rst
new file mode 100644
index 00000000000000..25213e3283f169
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-21-14-21-06.gh-issue-150075.dLI21Z.rst
@@ -0,0 +1 @@
+tar.addfile() now sets member offsets in TarInfo objects

_______________________________________________
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