diff options
author | Oren Milman <orenmn@gmail.com> | 2017-09-29 21:34:31 +0300 |
---|---|---|
committer | Brett Cannon <brettcannon@users.noreply.github.com> | 2017-09-29 11:34:31 -0700 |
commit | 01c6a8859ef2ff5545a87cf537573bd342c848bf (patch) | |
tree | 67a72ecdad511b4890802ea8c12494f2e3888a58 | |
parent | 66033733aa032707b57cf1b0e8d5a1c5e4afceb9 (diff) | |
download | cpython-git-01c6a8859ef2ff5545a87cf537573bd342c848bf.tar.gz |
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.
-rw-r--r-- | Lib/test/test_zipimport.py | 17 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2017-09-27-09-30-03.bpo-31602.MtgLCn.rst | 2 | ||||
-rw-r--r-- | Modules/zipimport.c | 8 |
3 files changed, 27 insertions, 0 deletions
diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py index daa5138751..4a934ff6cb 100644 --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -17,6 +17,10 @@ import doctest 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 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase): 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 0000000000..3a6320911e --- /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 141ada5adc..493e6db394 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: |