Skip to content

Commit be4acc7

Browse files
[3.11] gh-105967: Work around a macOS bug, limit zlib C library crc32 API calls to 1gig (GH-112615) (#112725)
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 4eddb4c) Co-authored-by: Gregory P. Smith <[email protected]>
1 parent 8dbda1c commit be4acc7

File tree

3 files changed

+30
-10
lines changed

3 files changed

+30
-10
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Workaround a bug in Apple's macOS platform zlib library where
2+
:func:`zlib.crc32` and :func:`binascii.crc32` could produce incorrect results
3+
on multi-gigabyte inputs. Including when using :mod:`zipfile` on zips
4+
containing large data.

Modules/binascii.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -780,12 +780,20 @@ binascii_crc32_impl(PyObject *module, Py_buffer *data, unsigned int crc)
780780

781781
Py_BEGIN_ALLOW_THREADS
782782
/* Avoid truncation of length for very large buffers. crc32() takes
783-
length as an unsigned int, which may be narrower than Py_ssize_t. */
784-
while ((size_t)len > UINT_MAX) {
785-
crc = crc32(crc, buf, UINT_MAX);
786-
buf += (size_t) UINT_MAX;
787-
len -= (size_t) UINT_MAX;
783+
length as an unsigned int, which may be narrower than Py_ssize_t.
784+
We further limit size due to bugs in Apple's macOS zlib.
785+
See https://github.com/python/cpython/issues/105967
786+
*/
787+
#define ZLIB_CRC_CHUNK_SIZE 0x40000000
788+
#if ZLIB_CRC_CHUNK_SIZE > INT_MAX
789+
# error "unsupported less than 32-bit platform?"
790+
#endif
791+
while ((size_t)len > ZLIB_CRC_CHUNK_SIZE) {
792+
crc = crc32(crc, buf, ZLIB_CRC_CHUNK_SIZE);
793+
buf += (size_t) ZLIB_CRC_CHUNK_SIZE;
794+
len -= (size_t) ZLIB_CRC_CHUNK_SIZE;
788795
}
796+
#undef ZLIB_CRC_CHUNK_SIZE
789797
crc = crc32(crc, buf, (unsigned int)len);
790798
Py_END_ALLOW_THREADS
791799
} else {

Modules/zlibmodule.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,12 +1444,20 @@ zlib_crc32_impl(PyObject *module, Py_buffer *data, unsigned int value)
14441444

14451445
Py_BEGIN_ALLOW_THREADS
14461446
/* Avoid truncation of length for very large buffers. crc32() takes
1447-
length as an unsigned int, which may be narrower than Py_ssize_t. */
1448-
while ((size_t)len > UINT_MAX) {
1449-
value = crc32(value, buf, UINT_MAX);
1450-
buf += (size_t) UINT_MAX;
1451-
len -= (size_t) UINT_MAX;
1447+
length as an unsigned int, which may be narrower than Py_ssize_t.
1448+
We further limit size due to bugs in Apple's macOS zlib.
1449+
See https://github.com/python/cpython/issues/105967.
1450+
*/
1451+
#define ZLIB_CRC_CHUNK_SIZE 0x40000000
1452+
#if ZLIB_CRC_CHUNK_SIZE > INT_MAX
1453+
# error "unsupported less than 32-bit platform?"
1454+
#endif
1455+
while ((size_t)len > ZLIB_CRC_CHUNK_SIZE) {
1456+
value = crc32(value, buf, ZLIB_CRC_CHUNK_SIZE);
1457+
buf += (size_t) ZLIB_CRC_CHUNK_SIZE;
1458+
len -= (size_t) ZLIB_CRC_CHUNK_SIZE;
14521459
}
1460+
#undef ZLIB_CRC_CHUNK_SIZE
14531461
value = crc32(value, buf, (unsigned int)len);
14541462
Py_END_ALLOW_THREADS
14551463
} else {

0 commit comments

Comments
 (0)