Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Lib/tarfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,8 @@ def _read(self, size):
else:
# Other decompressors have needs_input.
# decompress() can buffer data internally.
if self.cmp.eof:
break
if self.cmp.needs_input:
cbuf = self.fileobj.read(self.bufsize)
if not cbuf:
Expand Down
20 changes: 20 additions & 0 deletions Lib/test/test_tarfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,26 @@ def test_compare_members(self):
finally:
tar1.close()

def test_ignore_zeros_concatenated(self):
# gh-159643: reading past the end of the compressed data
# must not raise EOFError.
with self.open(tmpname, "wb") as fobj:
for name in ("a", "b"):
with tarfile.open(fileobj=fobj, mode="w") as tar:
tar.addfile(tarfile.TarInfo(name))
with tarfile.open(tmpname, self.mode, ignore_zeros=True) as tar:
self.assertEqual(tar.getnames(), ["a", "b"])

def test_no_end_of_archive_blocks(self):
# gh-159643
tarinfo = tarfile.TarInfo("a")
tarinfo.size = 5
with self.open(tmpname, "wb") as fobj:
fobj.write(tarinfo.tobuf())
fobj.write(b"hello".ljust(tarfile.BLOCKSIZE, b"\0"))
with tarfile.open(tmpname, self.mode) as tar:
self.assertEqual(tar.getnames(), ["a"])

class GzipStreamReadTest(GzipTest, GzipReadTestBase, StreamReadTest):
pass

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix :exc:`EOFError` raised by :mod:`tarfile` in stream mode with bz2, xz or
zstd compression when reading past the end of the compressed data, for
example with *ignore_zeros* or an archive without end-of-archive blocks.
Loading