Skip to content

Commit 4eddb4c

Browse files
authored
gh-105967: Work around a macOS bug, limit zlib C library crc32 API calls to 1gig (#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.
1 parent a1551b4 commit 4eddb4c

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
@@ -770,12 +770,20 @@ binascii_crc32_impl(PyObject *module, Py_buffer *data, unsigned int crc)
770770

771771
Py_BEGIN_ALLOW_THREADS
772772
/* Avoid truncation of length for very large buffers. crc32() takes
773-
length as an unsigned int, which may be narrower than Py_ssize_t. */
774-
while ((size_t)len > UINT_MAX) {
775-
crc = crc32(crc, buf, UINT_MAX);
776-
buf += (size_t) UINT_MAX;
777-
len -= (size_t) UINT_MAX;
773+
length as an unsigned int, which may be narrower than Py_ssize_t.
774+
We further limit size due to bugs in Apple's macOS zlib.
775+
See https://github.com/python/cpython/issues/105967
776+
*/
777+
#define ZLIB_CRC_CHUNK_SIZE 0x40000000
778+
#if ZLIB_CRC_CHUNK_SIZE > INT_MAX
779+
# error "unsupported less than 32-bit platform?"
780+
#endif
781+
while ((size_t)len > ZLIB_CRC_CHUNK_SIZE) {
782+
crc = crc32(crc, buf, ZLIB_CRC_CHUNK_SIZE);
783+
buf += (size_t) ZLIB_CRC_CHUNK_SIZE;
784+
len -= (size_t) ZLIB_CRC_CHUNK_SIZE;
778785
}
786+
#undef ZLIB_CRC_CHUNK_SIZE
779787
crc = crc32(crc, buf, (unsigned int)len);
780788
Py_END_ALLOW_THREADS
781789
} else {

Modules/zlibmodule.c

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

18971897
Py_BEGIN_ALLOW_THREADS
18981898
/* Avoid truncation of length for very large buffers. crc32() takes
1899-
length as an unsigned int, which may be narrower than Py_ssize_t. */
1900-
while ((size_t)len > UINT_MAX) {
1901-
value = crc32(value, buf, UINT_MAX);
1902-
buf += (size_t) UINT_MAX;
1903-
len -= (size_t) UINT_MAX;
1899+
length as an unsigned int, which may be narrower than Py_ssize_t.
1900+
We further limit size due to bugs in Apple's macOS zlib.
1901+
See https://github.com/python/cpython/issues/105967.
1902+
*/
1903+
#define ZLIB_CRC_CHUNK_SIZE 0x40000000
1904+
#if ZLIB_CRC_CHUNK_SIZE > INT_MAX
1905+
# error "unsupported less than 32-bit platform?"
1906+
#endif
1907+
while ((size_t)len > ZLIB_CRC_CHUNK_SIZE) {
1908+
value = crc32(value, buf, ZLIB_CRC_CHUNK_SIZE);
1909+
buf += (size_t) ZLIB_CRC_CHUNK_SIZE;
1910+
len -= (size_t) ZLIB_CRC_CHUNK_SIZE;
19041911
}
1912+
#undef ZLIB_CRC_CHUNK_SIZE
19051913
value = crc32(value, buf, (unsigned int)len);
19061914
Py_END_ALLOW_THREADS
19071915
} else {

0 commit comments

Comments
 (0)