Skip to content

Commit 01c6a88

Browse files
orenmnbrettcannon
authored andcommitted
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.
1 parent 6603373 commit 01c6a88

File tree

3 files changed

+27
-0
lines changed

3 files changed

+27
-0
lines changed

Lib/test/test_zipimport.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
import inspect
1818
import io
1919
from traceback import extract_tb, extract_stack, print_tb
20+
try:
21+
import zlib
22+
except ImportError:
23+
zlib = None
2024

2125
test_src = """\
2226
def get_name():
@@ -669,6 +673,19 @@ def testBytesPath(self):
669673
class CompressedZipImportTestCase(UncompressedZipImportTestCase):
670674
compression = ZIP_DEFLATED
671675

676+
@support.cpython_only
677+
def test_issue31602(self):
678+
# There shouldn't be an assertion failure in zipimporter.get_source()
679+
# in case of a bad zlib.decompress().
680+
def bad_decompress(*args):
681+
return None
682+
with ZipFile(TEMP_ZIP, 'w') as zip_file:
683+
self.addCleanup(support.unlink, TEMP_ZIP)
684+
zip_file.writestr('bar.py', b'print("hello world")', ZIP_DEFLATED)
685+
zi = zipimport.zipimporter(TEMP_ZIP)
686+
with support.swap_attr(zlib, 'decompress', bad_decompress):
687+
self.assertRaises(TypeError, zi.get_source, 'bar')
688+
672689

673690
class BadFileZipImportTestCase(unittest.TestCase):
674691
def assertZipFailure(self, filename):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix an assertion failure in `zipimporter.get_source()` in case of a bad
2+
`zlib.decompress()`. Patch by Oren Milman.

Modules/zipimport.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,6 +1236,14 @@ get_data(PyObject *archive, PyObject *toc_entry)
12361236
data = PyObject_CallFunction(decompress, "Oi", raw_data, -15);
12371237
Py_DECREF(decompress);
12381238
Py_DECREF(raw_data);
1239+
if (data != NULL && !PyBytes_Check(data)) {
1240+
PyErr_Format(PyExc_TypeError,
1241+
"zlib.decompress() must return a bytes object, not "
1242+
"%.200s",
1243+
Py_TYPE(data)->tp_name);
1244+
Py_DECREF(data);
1245+
return NULL;
1246+
}
12391247
return data;
12401248

12411249
eof_error:

0 commit comments

Comments
 (0)