From 10a3fa845e6392b96120d9ca764d747918122ccf Mon Sep 17 00:00:00 2001 From: animalize Date: Mon, 7 Sep 2020 11:16:12 +0800 Subject: [PATCH] Fix thread locks in zlib module may go wrong in rare case. Setting `next_in` before acquiring the thread lock may mix up compress/decompress state in other threads. --- .../2020-09-07-11-15-15.bpo-41735.NKqGKy.rst | 1 + Modules/zlibmodule.c | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-09-07-11-15-15.bpo-41735.NKqGKy.rst 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 index 000000000000000..9e36435a364eaf8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-09-07-11-15-15.bpo-41735.NKqGKy.rst @@ -0,0 +1 @@ +Fix thread locks in zlib module may go wrong in rare case. Patch by Ma Lin. diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index fd3064952869bf8..b94c6fb0d1c6475 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -10,10 +10,12 @@ #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 @@ -636,11 +638,11 @@ zlib_Compress_compress_impl(compobject *self, Py_buffer *data) Py_ssize_t ibuflen, obuflen = DEF_BUF_SIZE; int err; + ENTER_ZLIB(self); + self->zst.next_in = data->buf; ibuflen = data->len; - ENTER_ZLIB(self); - do { arrange_input_buffer(&self->zst, &ibuflen); @@ -754,6 +756,8 @@ zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, else hard_limit = max_length; + ENTER_ZLIB(self); + self->zst.next_in = data->buf; ibuflen = data->len; @@ -761,8 +765,6 @@ zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, if (max_length && obuflen > max_length) obuflen = max_length; - ENTER_ZLIB(self); - do { arrange_input_buffer(&self->zst, &ibuflen);