Skip to content

Commit 360deb1

Browse files
Fix zlib.Decompress.flush() silently returning corrupted output instead of raising zlib.error`
1 parent 228b1bf commit 360deb1

3 files changed

Lines changed: 27 additions & 0 deletions

File tree

Lib/test/test_zlib.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,20 @@ def test_decompress_eof_incomplete_stream(self):
719719
dco.flush()
720720
self.assertFalse(dco.eof)
721721

722+
def test_decompress_flush_corrupt_stream(self):
723+
x = b'x\x9cK\xcb\xcf\x07\x00\x02\x82\x01E' # 'foo'
724+
corrupt = x[:-1] + b'\x00'
725+
dco = zlib.decompressobj()
726+
self.assertEqual(dco.decompress(corrupt, 1), b'f')
727+
self.assertRaises(zlib.error, dco.flush)
728+
729+
def test_decompress_flush_twice(self):
730+
x = b'x\x9cK\xcb\xcf\x07\x00\x02\x82\x01E' # 'foo'
731+
dco = zlib.decompressobj()
732+
self.assertEqual(dco.decompress(x), b'foo')
733+
self.assertEqual(dco.flush(), b'')
734+
self.assertEqual(dco.flush(), b'')
735+
722736
def test_decompress_unused_data(self):
723737
# Repeated calls to decompress() after EOF should accumulate data in
724738
# dco.unused_data, instead of just storing the arg to the last call.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Calling :meth:`zlib.Decompress.flush` on invalid compressed data now
2+
raises :exc:`zlib.error` instead of being silently ignored.

Modules/zlibmodule.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,6 +1271,13 @@ zlib_Decompress_flush_impl(compobject *self, PyTypeObject *cls,
12711271

12721272
PyMutex_Lock(&self->mutex);
12731273

1274+
/* A previous flush() already reached the end of the stream and freed the
1275+
decompression state, so there is nothing left to process. */
1276+
if (!self->is_initialised) {
1277+
PyMutex_Unlock(&self->mutex);
1278+
return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES);
1279+
}
1280+
12741281
if (PyObject_GetBuffer(self->unconsumed_tail, &data, PyBUF_SIMPLE) == -1) {
12751282
PyMutex_Unlock(&self->mutex);
12761283
return NULL;
@@ -1328,6 +1335,10 @@ zlib_Decompress_flush_impl(compobject *self, PyTypeObject *cls,
13281335
goto abort;
13291336
}
13301337
}
1338+
else if (err != Z_OK && err != Z_BUF_ERROR) {
1339+
zlib_error(state, self->zst, err, "while decompressing data");
1340+
goto abort;
1341+
}
13311342

13321343
return_value = OutputBuffer_WindowFinish(&buffer, &window, self->zst.avail_out);
13331344
if (return_value != NULL) {

0 commit comments

Comments
 (0)