[Python-checkins] cpython (3.5): Issue #27164: Allow decompressing raw Deflate streams with predefined zdict

martin.panter python-checkins at python.org
Sun Jun 5 08:36:53 EDT 2016


https://hg.python.org/cpython/rev/d91b951e676f
changeset:   101755:d91b951e676f
branch:      3.5
parent:      101752:33b53734805b
user:        Martin Panter <vadmium+py at gmail.com>
date:        Sun Jun 05 10:48:34 2016 +0000
summary:
  Issue #27164: Allow decompressing raw Deflate streams with predefined zdict

Based on patch by Xiang Zhang.

files:
  Lib/test/test_zlib.py |   9 ++++
  Misc/NEWS             |   3 +
  Modules/zlibmodule.c  |  62 ++++++++++++++++++++++---------
  3 files changed, 56 insertions(+), 18 deletions(-)


diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py
--- a/Lib/test/test_zlib.py
+++ b/Lib/test/test_zlib.py
@@ -553,6 +553,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 --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -131,6 +131,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 --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
--- a/Modules/zlibmodule.c
+++ b/Modules/zlibmodule.c
@@ -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
@@ -474,6 +478,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
 
@@ -515,6 +544,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);
@@ -741,29 +784,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);

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list