diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -934,6 +934,10 @@ "An optional starting value can be specified. The returned checksum is\n" "an integer."); +fdef HAVE_SSIZE_T +typedef ssize_t Py_ssize_t; +#elif SIZEOF_VOID_P == SIZEOF_SIZE_T + static PyObject * PyZlib_adler32(PyObject *self, PyObject *args) { @@ -942,11 +946,24 @@ if (!PyArg_ParseTuple(args, "y*|I:adler32", &pbuf, &adler32val)) return NULL; + /* Releasing the GIL for very small buffers is inefficient and may lower performance */ if (pbuf.len > 1024*5) { + Py_ssize_t len = pbuf.len, rest = 0; Py_BEGIN_ALLOW_THREADS - adler32val = adler32(adler32val, pbuf.buf, pbuf.len); + if ((size_t)len >= UINT_MAX) { + rest = len; + len = UINT_MAX; + } + for (;;) { + adler32val = adler32(adler32val, pbuf.buf, len); + rest -= len; + if (rest <= 0) + break; + if (rest < len) + len = rest; + } Py_END_ALLOW_THREADS } else { adler32val = adler32(adler32val, pbuf.buf, pbuf.len); @@ -970,11 +987,24 @@ if (!PyArg_ParseTuple(args, "y*|I:crc32", &pbuf, &crc32val)) return NULL; + /* Releasing the GIL for very small buffers is inefficient and may lower performance */ if (pbuf.len > 1024*5) { + Py_ssize_t len = pbuf.len, rest = 0; Py_BEGIN_ALLOW_THREADS - signed_val = crc32(crc32val, pbuf.buf, pbuf.len); + if ((size_t)len >= UINT_MAX) { + rest = len; + len = UINT_MAX; + } + for (;;) { + adler32val = crc32(crc32val, pbuf.buf, len); + rest -= len; + if (rest <= 0) + break; + if (rest < len) + len = rest; + } Py_END_ALLOW_THREADS } else { signed_val = crc32(crc32val, pbuf.buf, pbuf.len);