changeset: 101756:470954641f3b parent: 101753:31ad7885e2e5 parent: 101755:d91b951e676f user: Martin Panter date: Sun Jun 05 12:07:48 2016 +0000 files: Lib/test/test_zlib.py Misc/NEWS Modules/zlibmodule.c description: Issue #27164: Merge raw Deflate zdict support from 3.5 diff -r 31ad7885e2e5 -r 470954641f3b Lib/test/test_zlib.py --- a/Lib/test/test_zlib.py Sun Jun 05 10:50:16 2016 +0300 +++ b/Lib/test/test_zlib.py Sun Jun 05 12:07:48 2016 +0000 @@ -557,6 +557,15 @@ self.assertEqual(dco.unconsumed_tail, b'') self.assertEqual(dco.unused_data, remainder) + # issue27164 + def test_decompress_raw_with_dictionary(self): + zdict = b'abcdefghijklmnopqrstuvwxyz' + co = zlib.compressobj(wbits=-zlib.MAX_WBITS, zdict=zdict) + comp = co.compress(zdict) + co.flush() + dco = zlib.decompressobj(wbits=-zlib.MAX_WBITS, zdict=zdict) + uncomp = dco.decompress(comp) + dco.flush() + self.assertEqual(zdict, uncomp) + def test_flush_with_freed_input(self): # Issue #16411: decompressor accesses input to last decompress() call # in flush(), even if this object has been freed in the meanwhile. diff -r 31ad7885e2e5 -r 470954641f3b Misc/NEWS --- a/Misc/NEWS Sun Jun 05 10:50:16 2016 +0300 +++ b/Misc/NEWS Sun Jun 05 12:07:48 2016 +0000 @@ -27,6 +27,9 @@ Library ------- +- Issue #27164: In the zlib module, allow decompressing raw Deflate streams + with a predefined zdict. Based on patch by Xiang Zhang. + - Issue #24291: Fix wsgiref.simple_server.WSGIRequestHandler to completely write data to the client. Previously it could do partial writes and truncate data. Also, wsgiref.handler.ServerHandler can now handle stdout diff -r 31ad7885e2e5 -r 470954641f3b Modules/zlibmodule.c --- a/Modules/zlibmodule.c Sun Jun 05 10:50:16 2016 +0300 +++ b/Modules/zlibmodule.c Sun Jun 05 12:07:48 2016 +0000 @@ -22,6 +22,10 @@ #define LEAVE_ZLIB(obj) #endif +#if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1221 +#define AT_LEAST_ZLIB_1_2_2_1 +#endif + /* The following parameters are copied from zutil.h, version 0.95 */ #define DEFLATED 8 #if MAX_MEM_LEVEL >= 8 @@ -473,6 +477,31 @@ return (PyObject*)self; } +static int +set_inflate_zdict(compobject *self) +{ + Py_buffer zdict_buf; + int err; + + if (PyObject_GetBuffer(self->zdict, &zdict_buf, PyBUF_SIMPLE) == -1) { + return -1; + } + if ((size_t)zdict_buf.len > UINT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "zdict length does not fit in an unsigned int"); + PyBuffer_Release(&zdict_buf); + return -1; + } + err = inflateSetDictionary(&(self->zst), + zdict_buf.buf, (unsigned int)zdict_buf.len); + PyBuffer_Release(&zdict_buf); + if (err != Z_OK) { + zlib_error(self->zst, err, "while setting zdict"); + return -1; + } + return 0; +} + /*[clinic input] zlib.decompressobj @@ -514,6 +543,20 @@ switch(err) { case (Z_OK): self->is_initialised = 1; + if (self->zdict != NULL && wbits < 0) { +#ifdef AT_LEAST_ZLIB_1_2_2_1 + if (set_inflate_zdict(self) < 0) { + Py_DECREF(self); + return NULL; + } +#else + PyErr_Format(ZlibError, + "zlib version %s does not allow raw inflate with dictionary", + ZLIB_VERSION); + Py_DECREF(self); + return NULL; +#endif + } return (PyObject*)self; case(Z_STREAM_ERROR): Py_DECREF(self); @@ -740,29 +783,12 @@ Py_END_ALLOW_THREADS if (err == Z_NEED_DICT && self->zdict != NULL) { - Py_buffer zdict_buf; - if (PyObject_GetBuffer(self->zdict, &zdict_buf, PyBUF_SIMPLE) == -1) { + if (set_inflate_zdict(self) < 0) { Py_DECREF(RetVal); RetVal = NULL; goto error; } - if ((size_t)zdict_buf.len > UINT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "zdict length does not fit in an unsigned int"); - PyBuffer_Release(&zdict_buf); - Py_CLEAR(RetVal); - goto error; - } - - err = inflateSetDictionary(&(self->zst), - zdict_buf.buf, (unsigned int)zdict_buf.len); - PyBuffer_Release(&zdict_buf); - if (err != Z_OK) { - zlib_error(self->zst, err, "while decompressing data"); - Py_CLEAR(RetVal); - goto error; - } /* Repeat the call to inflate. */ Py_BEGIN_ALLOW_THREADS err = inflate(&(self->zst), Z_SYNC_FLUSH);