diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 247b84ba37bbbd..5cff59e83dd1dd 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -620,6 +620,12 @@ Lib/test/test_unittest/testmock/ @cjw296 # Weakref **/*weakref* @kumaraditya303 +# Zlib +Doc/library/zlib.rst @StanFromIreland +Lib/compression/zlib.py @StanFromIreland +Lib/test/test_zlib.py @StanFromIreland +Modules/_zlibmodule.c @StanFromIreland + # Zipfile.Path Lib/test/test_zipfile/_path/ @jaraco Lib/zipfile/_path/ @jaraco diff --git a/Doc/glossary.rst b/Doc/glossary.rst index bb00a4f02f0efd..4017f1e37f748e 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -509,7 +509,7 @@ Glossary A piece of syntax which can be evaluated to some value. In other words, an expression is an accumulation of expression elements like literals, names, attribute access, operators or function calls which all return a - value. In contrast to many other languages, not all language constructs + value. Not all language constructs are expressions. There are also :term:`statement`\s which cannot be used as expressions, such as :keyword:`while`. Assignments are also statements, not expressions. diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py index 46c84c55c93398..70d1cd81ac6c46 100644 --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -182,6 +182,9 @@ def test_combine_no_iv_invalid_length(self): self.assertNotEqual(invalid_res, checksum) self.assertRaises(TypeError, self.combine, 0, 0, "len") + self.assertRaises(ValueError, self.combine, 0, 0, -1) + self.assertRaises(OverflowError, self.combine, 0, 0, 2**1000) + self.assertRaises(OverflowError, self.combine, 0, 0, -2**1000) def test_combine_with_iv(self): for _ in range(self.N): diff --git a/Misc/NEWS.d/next/Library/2026-08-21-14-30-00.gh-issue-156180.Qz3Lv8.rst b/Misc/NEWS.d/next/Library/2026-08-21-14-30-00.gh-issue-156180.Qz3Lv8.rst new file mode 100644 index 00000000000000..5730627e49e98f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-08-21-14-30-00.gh-issue-156180.Qz3Lv8.rst @@ -0,0 +1,3 @@ +:func:`zlib.adler32_combine` and :func:`zlib.crc32_combine` now raise +:exc:`ValueError` if the *len2* argument is negative, instead of returning +rubbish or hanging indefinitely, respectively. diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index 0a6732835eb51f..d06b94d1e83713 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -1948,7 +1948,10 @@ zlib_adler32_combine_impl(PyObject *module, unsigned int adler1, #else z_off_t len = convert_to_z_off_t(len2); #endif - if (PyErr_Occurred()) { + if (len < 0) { + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ValueError, "len2 must be non-negative"); + } return (unsigned int)-1; } return adler32_combine(adler1, adler2, len); @@ -2033,7 +2036,10 @@ zlib_crc32_combine_impl(PyObject *module, unsigned int crc1, #else z_off_t len = convert_to_z_off_t(len2); #endif - if (PyErr_Occurred()) { + if (len < 0) { + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ValueError, "len2 must be non-negative"); + } return (unsigned int)-1; } return crc32_combine(crc1, crc2, len);