]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Merged revisions 70525 via svnmerge from
authorLars Gustäbel <lars@gustaebel.de>
Sun, 22 Mar 2009 20:39:38 +0000 (20:39 +0000)
committerLars Gustäbel <lars@gustaebel.de>
Sun, 22 Mar 2009 20:39:38 +0000 (20:39 +0000)
svn+ssh://pythondev@svn.python.org/python/branches/py3k

................
  r70525 | lars.gustaebel | 2009-03-22 21:34:29 +0100 (Sun, 22 Mar 2009) | 12 lines

  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.
  ........
................

Lib/tarfile.py
Lib/test/test_tarfile.py
Misc/NEWS

index be7daf14c37fcb5bf0d4a2e19a4360e4fccb9e04..dabf64a4316d09a7923a0c5fd054bc281759f068 100644 (file)
@@ -639,12 +639,11 @@ class _BZ2Proxy(object):
     def read(self, size):
         x = len(self.buf)
         while x < size:
-            try:
-                raw = self.fileobj.read(self.blocksize)
-                data = self.bz2obj.decompress(raw)
-                self.buf += data
-            except EOFError:
+            raw = self.fileobj.read(self.blocksize)
+            if not raw:
                 break
+            data = self.bz2obj.decompress(raw)
+            self.buf += data
             x += len(data)
 
         buf = self.buf[:size]
index affbeeb6c2acf999bff77fd827459649914ce7a9..f4c00359859d385217fb2f9d291eaa1a4dac4a58 100644 (file)
@@ -1121,6 +1121,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 MyBytesIO(io.BytesIO):
+            hit_eof = False
+            def read(self, n):
+                if self.hit_eof:
+                    raise AssertionError("infinite loop detected in tarfile.open()")
+                self.hit_eof = self.tell() == len(self.getvalue())
+                return super(MyBytesIO, self).read(n)
+
+        data = bz2.compress(tarfile.TarInfo("foo").tobuf())
+        for x in range(len(data) + 1):
+            tarfile.open(fileobj=MyBytesIO(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)
@@ -1178,6 +1202,7 @@ def test_main():
             Bz2StreamReadTest,
             Bz2WriteTest,
             Bz2StreamWriteTest,
+            Bz2PartialReadTest,
         ]
 
     try:
index fd2c3298eb7e983bf6118805af164f53e6a27053..f9ed24486333b47201157dd8f6ad1903d0365bed 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -24,6 +24,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.
+
 - Fix Decimal.__format__ bug that swapped the meanings of the '<' and
   '>' alignment characters.