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 <grantlouisherman041@gmail.com>
Co-authored-by: Ethan Furman <ethan@stoneleaf.us>
This commit is contained in:
Grant HermanandEthan Furman authored and GitHub committed 2026-10-21 14:23:37 -07:00
1 parent ba96fab734
commit 0a86a343f0
3 files changed
+28 -1

No files matched your search

+4 -1
View File
@@ -2456,11 +2456,14 @@ class TarFile(object):
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)
+23
View File
@@ -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',
@@ -0,0 +1 @@
tar.addfile() now sets member offsets in TarInfo objects