[Python-checkins] bpo-31602: Fix an assertion failure in zipimporter.get_source() in case of a bad zlib.decompress() (GH-3784)

Brett Cannon webhook-mailer at python.org
Fri Sep 29 14:34:34 EDT 2017


https://github.com/python/cpython/commit/01c6a8859ef2ff5545a87cf537573bd342c848bf
commit: 01c6a8859ef2ff5545a87cf537573bd342c848bf
branch: master
author: Oren Milman <orenmn at gmail.com>
committer: Brett Cannon <brettcannon at users.noreply.github.com>
date: 2017-09-29T11:34:31-07:00
summary:

bpo-31602: Fix an assertion failure in zipimporter.get_source() in case of a bad zlib.decompress() (GH-3784)

While a rare potential failure (it requires swapping out zlib.decompress() itself and forcing it to return a non-bytes object), this change prevents a potential C-level assertion failure and instead substitutes it with an exception.

Thanks to Oren Milman for the patch.

files:
A Misc/NEWS.d/next/Core and Builtins/2017-09-27-09-30-03.bpo-31602.MtgLCn.rst
M Lib/test/test_zipimport.py
M Modules/zipimport.c

diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py
index daa5138751b..4a934ff6cbd 100644
--- a/Lib/test/test_zipimport.py
+++ b/Lib/test/test_zipimport.py
@@ -17,6 +17,10 @@
 import inspect
 import io
 from traceback import extract_tb, extract_stack, print_tb
+try:
+    import zlib
+except ImportError:
+    zlib = None
 
 test_src = """\
 def get_name():
@@ -669,6 +673,19 @@ def testBytesPath(self):
 class CompressedZipImportTestCase(UncompressedZipImportTestCase):
     compression = ZIP_DEFLATED
 
+    @support.cpython_only
+    def test_issue31602(self):
+        # There shouldn't be an assertion failure in zipimporter.get_source()
+        # in case of a bad zlib.decompress().
+        def bad_decompress(*args):
+            return None
+        with ZipFile(TEMP_ZIP, 'w') as zip_file:
+            self.addCleanup(support.unlink, TEMP_ZIP)
+            zip_file.writestr('bar.py', b'print("hello world")', ZIP_DEFLATED)
+        zi = zipimport.zipimporter(TEMP_ZIP)
+        with support.swap_attr(zlib, 'decompress', bad_decompress):
+            self.assertRaises(TypeError, zi.get_source, 'bar')
+
 
 class BadFileZipImportTestCase(unittest.TestCase):
     def assertZipFailure(self, filename):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-09-27-09-30-03.bpo-31602.MtgLCn.rst b/Misc/NEWS.d/next/Core and Builtins/2017-09-27-09-30-03.bpo-31602.MtgLCn.rst
new file mode 100644
index 00000000000..3a6320911e1
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2017-09-27-09-30-03.bpo-31602.MtgLCn.rst	
@@ -0,0 +1,2 @@
+Fix an assertion failure in `zipimporter.get_source()` in case of a bad
+`zlib.decompress()`. Patch by Oren Milman.
diff --git a/Modules/zipimport.c b/Modules/zipimport.c
index 141ada5adc5..493e6db394a 100644
--- a/Modules/zipimport.c
+++ b/Modules/zipimport.c
@@ -1236,6 +1236,14 @@ get_data(PyObject *archive, PyObject *toc_entry)
     data = PyObject_CallFunction(decompress, "Oi", raw_data, -15);
     Py_DECREF(decompress);
     Py_DECREF(raw_data);
+    if (data != NULL && !PyBytes_Check(data)) {
+        PyErr_Format(PyExc_TypeError,
+                     "zlib.decompress() must return a bytes object, not "
+                     "%.200s",
+                     Py_TYPE(data)->tp_name);
+        Py_DECREF(data);
+        return NULL;
+    }
     return data;
 
 eof_error:



More information about the Python-checkins mailing list