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]
