Skip to content

Commit 53e1009

Browse files
committed
Merged revisions 70523 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r70523 | lars.gustaebel | 2009-03-22 21:09:33 +0100 (Sun, 22 Mar 2009) | 5 lines Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop forever on incomplete input. That caused tarfile.open() to hang when used with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or partial bzip2 compressed data. ........
1 parent 4c436de commit 53e1009

3 files changed

Lines changed: 34 additions & 5 deletions

File tree

Lib/tarfile.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -639,12 +639,11 @@ def init(self):
639639
def read(self, size):
640640
x = len(self.buf)
641641
while x < size:
642-
try:
643-
raw = self.fileobj.read(self.blocksize)
644-
data = self.bz2obj.decompress(raw)
645-
self.buf += data
646-
except EOFError:
642+
raw = self.fileobj.read(self.blocksize)
643+
if not raw:
647644
break
645+
data = self.bz2obj.decompress(raw)
646+
self.buf += data
648647
x += len(data)
649648

650649
buf = self.buf[:size]

Lib/test/test_tarfile.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,30 @@ class Bz2WriteTest(WriteTest):
11211121
class Bz2StreamWriteTest(StreamWriteTest):
11221122
mode = "w|bz2"
11231123

1124+
class Bz2PartialReadTest(unittest.TestCase):
1125+
# Issue5068: The _BZ2Proxy.read() method loops forever
1126+
# on an empty or partial bzipped file.
1127+
1128+
def _test_partial_input(self, mode):
1129+
class MyBytesIO(io.BytesIO):
1130+
hit_eof = False
1131+
def read(self, n):
1132+
if self.hit_eof:
1133+
raise AssertionError("infinite loop detected in tarfile.open()")
1134+
self.hit_eof = self.tell() == len(self.getvalue())
1135+
return super(MyBytesIO, self).read(n)
1136+
1137+
data = bz2.compress(tarfile.TarInfo("foo").tobuf())
1138+
for x in range(len(data) + 1):
1139+
tarfile.open(fileobj=MyBytesIO(data[:x]), mode=mode)
1140+
1141+
def test_partial_input(self):
1142+
self._test_partial_input("r")
1143+
1144+
def test_partial_input_bz2(self):
1145+
self._test_partial_input("r:bz2")
1146+
1147+
11241148
def test_main():
11251149
if not os.path.exists(TEMPDIR):
11261150
os.mkdir(TEMPDIR)
@@ -1178,6 +1202,7 @@ def test_main():
11781202
Bz2StreamReadTest,
11791203
Bz2WriteTest,
11801204
Bz2StreamWriteTest,
1205+
Bz2PartialReadTest,
11811206
]
11821207

11831208
try:

Misc/NEWS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ Core and Builtins
3232
Library
3333
-------
3434

35+
- Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop
36+
forever on incomplete input. That caused tarfile.open() to hang when used
37+
with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or
38+
partial bzip2 compressed data.
39+
3540
- Issue #2110: Add support for thousands separator and 'n' type
3641
specifier to Decimal.__format__
3742

0 commit comments

Comments
 (0)