summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2023-12-04 20:29:23 (GMT)
committerGitHub <noreply@github.com>2023-12-04 20:29:23 (GMT)
commit88ec2a4fef5e05e281acf30262ae5981eafa44ab (patch)
tree931a9ae19e54b10089782da91c27f363a5878256
parent8d21242bd1bcde660c81eb86b986afbc7d25a4ba (diff)
downloadcpython-88ec2a4fef5e05e281acf30262ae5981eafa44ab.zip
cpython-88ec2a4fef5e05e281acf30262ae5981eafa44ab.tar.gz
cpython-88ec2a4fef5e05e281acf30262ae5981eafa44ab.tar.bz2
[3.12] gh-105967: Work around a macOS bug, limit zlib C library crc32 API calls to 1gig (GH-112615) (#112724)
gh-105967: Work around a macOS bug, limit zlib C library crc32 API calls to 1gig (GH-112615) Work around a macOS bug, limit zlib crc32 calls to 1GiB. Without this, `zlib.crc32` and `binascii.crc32` could produce incorrect results on multi-gigabyte inputs depending on the macOS version's Apple supplied zlib implementation. (cherry picked from commit 4eddb4c9d9452482c9af7fa9eec223d12b5a9f33) Co-authored-by: Gregory P. Smith <greg@krypto.org>
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2023-12-01-19-02-21.gh-issue-105967.Puq5Cn.rst4
-rw-r--r--Modules/binascii.c18
-rw-r--r--Modules/zlibmodule.c18
3 files changed, 30 insertions, 10 deletions
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-01-19-02-21.gh-issue-105967.Puq5Cn.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-01-19-02-21.gh-issue-105967.Puq5Cn.rst
new file mode 100644
index 0000000..c695112
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-01-19-02-21.gh-issue-105967.Puq5Cn.rst
@@ -0,0 +1,4 @@
+Workaround a bug in Apple's macOS platform zlib library where
+:func:`zlib.crc32` and :func:`binascii.crc32` could produce incorrect results
+on multi-gigabyte inputs. Including when using :mod:`zipfile` on zips
+containing large data.
diff --git a/Modules/binascii.c b/Modules/binascii.c
index 4ecff47..0614edf 100644
--- a/Modules/binascii.c
+++ b/Modules/binascii.c
@@ -780,12 +780,20 @@ binascii_crc32_impl(PyObject *module, Py_buffer *data, unsigned int crc)
Py_BEGIN_ALLOW_THREADS
/* Avoid truncation of length for very large buffers. crc32() takes
- length as an unsigned int, which may be narrower than Py_ssize_t. */
- while ((size_t)len > UINT_MAX) {
- crc = crc32(crc, buf, UINT_MAX);
- buf += (size_t) UINT_MAX;
- len -= (size_t) UINT_MAX;
+ length as an unsigned int, which may be narrower than Py_ssize_t.
+ We further limit size due to bugs in Apple's macOS zlib.
+ See https://github.com/python/cpython/issues/105967
+ */
+#define ZLIB_CRC_CHUNK_SIZE 0x40000000
+#if ZLIB_CRC_CHUNK_SIZE > INT_MAX
+# error "unsupported less than 32-bit platform?"
+#endif
+ while ((size_t)len > ZLIB_CRC_CHUNK_SIZE) {
+ crc = crc32(crc, buf, ZLIB_CRC_CHUNK_SIZE);
+ buf += (size_t) ZLIB_CRC_CHUNK_SIZE;
+ len -= (size_t) ZLIB_CRC_CHUNK_SIZE;
}
+#undef ZLIB_CRC_CHUNK_SIZE
crc = crc32(crc, buf, (unsigned int)len);
Py_END_ALLOW_THREADS
} else {
diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
index b67844a..f94c57e 100644
--- a/Modules/zlibmodule.c
+++ b/Modules/zlibmodule.c
@@ -1890,12 +1890,20 @@ zlib_crc32_impl(PyObject *module, Py_buffer *data, unsigned int value)
Py_BEGIN_ALLOW_THREADS
/* Avoid truncation of length for very large buffers. crc32() takes
- length as an unsigned int, which may be narrower than Py_ssize_t. */
- while ((size_t)len > UINT_MAX) {
- value = crc32(value, buf, UINT_MAX);
- buf += (size_t) UINT_MAX;
- len -= (size_t) UINT_MAX;
+ length as an unsigned int, which may be narrower than Py_ssize_t.
+ We further limit size due to bugs in Apple's macOS zlib.
+ See https://github.com/python/cpython/issues/105967.
+ */
+#define ZLIB_CRC_CHUNK_SIZE 0x40000000
+#if ZLIB_CRC_CHUNK_SIZE > INT_MAX
+# error "unsupported less than 32-bit platform?"
+#endif
+ while ((size_t)len > ZLIB_CRC_CHUNK_SIZE) {
+ value = crc32(value, buf, ZLIB_CRC_CHUNK_SIZE);
+ buf += (size_t) ZLIB_CRC_CHUNK_SIZE;
+ len -= (size_t) ZLIB_CRC_CHUNK_SIZE;
}
+#undef ZLIB_CRC_CHUNK_SIZE
value = crc32(value, buf, (unsigned int)len);
Py_END_ALLOW_THREADS
} else {