summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Gustäbel <lars@gustaebel.de>2009-03-22 20:09:33 (GMT)
committerLars Gustäbel <lars@gustaebel.de>2009-03-22 20:09:33 (GMT)
commit2020a59563caeda95023307a4c830fe03c338990 (patch)
treedbd8152d0b445bbebd60a48eecaadf0fdc687a37
parentb364bfe2f406a99a83fc5b1073726ecbaa63f50f (diff)
downloadcpython-2020a59563caeda95023307a4c830fe03c338990.zip
cpython-2020a59563caeda95023307a4c830fe03c338990.tar.gz
cpython-2020a59563caeda95023307a4c830fe03c338990.tar.bz2
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.
-rw-r--r--Lib/tarfile.py9
-rw-r--r--Lib/test/test_tarfile.py25
-rw-r--r--Misc/NEWS5
3 files changed, 34 insertions, 5 deletions
diff --git a/Lib/tarfile.py b/Lib/tarfile.py
index 9191a82..1861664 100644
--- a/Lib/tarfile.py
+++ b/Lib/tarfile.py
@@ -662,12 +662,11 @@ class _BZ2Proxy(object):
b = [self.buf]
x = len(self.buf)
while x < size:
- try:
- raw = self.fileobj.read(self.blocksize)
- data = self.bz2obj.decompress(raw)
- b.append(data)
- except EOFError:
+ raw = self.fileobj.read(self.blocksize)
+ if not raw:
break
+ data = self.bz2obj.decompress(raw)
+ b.append(data)
x += len(data)
self.buf = "".join(b)
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index f5c9ed4..ee68118 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -1140,6 +1140,30 @@ class Bz2WriteTest(WriteTest):
class Bz2StreamWriteTest(StreamWriteTest):
mode = "w|bz2"
+class Bz2PartialReadTest(unittest.TestCase):
+ # Issue5068: The _BZ2Proxy.read() method loops forever
+ # on an empty or partial bzipped file.
+
+ def _test_partial_input(self, mode):
+ class MyStringIO(StringIO.StringIO):
+ hit_eof = False
+ def read(self, n):
+ if self.hit_eof:
+ raise AssertionError("infinite loop detected in tarfile.open()")
+ self.hit_eof = self.pos == self.len
+ return StringIO.StringIO.read(self, n)
+
+ data = bz2.compress(tarfile.TarInfo("foo").tobuf())
+ for x in range(len(data) + 1):
+ tarfile.open(fileobj=MyStringIO(data[:x]), mode=mode)
+
+ def test_partial_input(self):
+ self._test_partial_input("r")
+
+ def test_partial_input_bz2(self):
+ self._test_partial_input("r:bz2")
+
+
def test_main():
if not os.path.exists(TEMPDIR):
os.mkdir(TEMPDIR)
@@ -1196,6 +1220,7 @@ def test_main():
Bz2StreamReadTest,
Bz2WriteTest,
Bz2StreamWriteTest,
+ Bz2PartialReadTest,
]
try:
diff --git a/Misc/NEWS b/Misc/NEWS
index 0b02dd9..17bc214 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -188,6 +188,11 @@ Core and Builtins
Library
-------
+- 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.
+
- Issue #5536: urllib.urlretrieve makes sure to close the file it's writing to
even if an exception occurs.