]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Fix thread locks in zlib module may go wrong in rare case. (#22126)
authorMa Lin <animalize@users.noreply.github.com>
Tue, 27 Apr 2021 08:37:11 +0000 (16:37 +0800)
committerGitHub <noreply@github.com>
Tue, 27 Apr 2021 08:37:11 +0000 (10:37 +0200)
Setting `next_in` before acquiring the thread lock may mix up compress/decompress state in other threads.

Misc/NEWS.d/next/Library/2020-09-07-11-15-15.bpo-41735.NKqGKy.rst [new file with mode: 0644]
Modules/zlibmodule.c

diff --git a/Misc/NEWS.d/next/Library/2020-09-07-11-15-15.bpo-41735.NKqGKy.rst b/Misc/NEWS.d/next/Library/2020-09-07-11-15-15.bpo-41735.NKqGKy.rst
new file mode 100644 (file)
index 0000000..9e36435
--- /dev/null
@@ -0,0 +1 @@
+Fix thread locks in zlib module may go wrong in rare case. Patch by Ma Lin.
index a537087d19d8359dadd4c29dfe6859976a6eeef1..1ddaefd8a6d792901819d72fb6882feb7ef85d54 100644 (file)
 #include "zlib.h"
 
 
-#define ENTER_ZLIB(obj) \
-    Py_BEGIN_ALLOW_THREADS; \
-    PyThread_acquire_lock((obj)->lock, 1); \
-    Py_END_ALLOW_THREADS;
+#define ENTER_ZLIB(obj) do {                      \
+    if (!PyThread_acquire_lock((obj)->lock, 0)) { \
+        Py_BEGIN_ALLOW_THREADS                    \
+        PyThread_acquire_lock((obj)->lock, 1);    \
+        Py_END_ALLOW_THREADS                      \
+    } } while (0)
 #define LEAVE_ZLIB(obj) PyThread_release_lock((obj)->lock);
 
 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1221
@@ -634,14 +636,13 @@ zlib_Compress_compress_impl(compobject *self, PyTypeObject *cls,
     PyObject *RetVal = NULL;
     Py_ssize_t obuflen = DEF_BUF_SIZE;
     int err;
-
     zlibstate *state = PyType_GetModuleState(cls);
 
+    ENTER_ZLIB(self);
+
     self->zst.next_in = data->buf;
     Py_ssize_t ibuflen = data->len;
 
-    ENTER_ZLIB(self);
-
     do {
         arrange_input_buffer(&self->zst, &ibuflen);
 
@@ -761,6 +762,8 @@ zlib_Decompress_decompress_impl(compobject *self, PyTypeObject *cls,
     else
         hard_limit = max_length;
 
+    ENTER_ZLIB(self);
+
     self->zst.next_in = data->buf;
     ibuflen = data->len;
 
@@ -768,8 +771,6 @@ zlib_Decompress_decompress_impl(compobject *self, PyTypeObject *cls,
     if (max_length && obuflen > max_length)
         obuflen = max_length;
 
-    ENTER_ZLIB(self);
-
     do {
         arrange_input_buffer(&self->zst, &ibuflen);