diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index f748b46190..5bca670dcf 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -873,6 +873,25 @@ class KDFTests(unittest.TestCase): def test_pbkdf2_hmac_c(self): self._test_pbkdf2_hmac(c_hashlib.pbkdf2_hmac) + @unittest.skipUnless(hasattr(c_hashlib, 'pbkdf2_hmac'), + ' test requires OpenSSL > 1.0') + @support.cpython_only + def test_pbkdf2_hmac_c_limits(self): + from _testcapi import INT_MAX + # test iterations limits + self.assertRaises(OverflowError, c_hashlib.pbkdf2_hmac, + 'sha1', b'pass', b'salt', -1 << 1000) + self.assertRaises(OverflowError, c_hashlib.pbkdf2_hmac, + 'sha1', b'pass', b'salt', INT_MAX + 1) + self.assertRaises(OverflowError, c_hashlib.pbkdf2_hmac, + 'sha1', b'pass', b'salt', 1 << 1000) + # test dklen limits + self.assertRaises(ValueError, c_hashlib.pbkdf2_hmac, + 'sha1', b'pass', b'salt', 1, -1 << 1000) + self.assertRaises(OverflowError, c_hashlib.pbkdf2_hmac, + 'sha1', b'pass', b'salt', 1, INT_MAX + 1) + self.assertRaises(OverflowError, c_hashlib.pbkdf2_hmac, + 'sha1', b'pass', b'salt', 1, 1 << 1000) @unittest.skipUnless(hasattr(c_hashlib, 'scrypt'), ' test requires OpenSSL > 1.1') diff --git a/Lib/test/test_lzma.py b/Lib/test/test_lzma.py index d7a8576d51..e8a1f76cb4 100644 --- a/Lib/test/test_lzma.py +++ b/Lib/test/test_lzma.py @@ -7,7 +7,7 @@ import random import unittest from test.support import ( - _4G, TESTFN, import_module, bigmemtest, run_unittest, unlink + _4G, TESTFN, import_module, bigmemtest, run_unittest, unlink, cpython_only ) lzma = import_module("lzma") @@ -58,6 +58,18 @@ class CompressorDecompressorTestCase(unittest.TestCase): lzd.decompress(empty) self.assertRaises(EOFError, lzd.decompress, b"quux") + @cpython_only + def test_INT_TYPE_CONVERTER_FUNC_macro(self): + # test the macro by testing uint32_converter, which is created + # by using the macro, and is later used to convert the preset + # argument of LZMACompressor. + self.assertRaises(OverflowError, LZMACompressor, preset=-1 << 1000) + self.assertRaises(OverflowError, LZMACompressor, preset=-1) + LZMACompressor(preset=0) + self.assertRaises(LZMAError, LZMACompressor, preset=(1 << 32) - 1) + self.assertRaises(OverflowError, LZMACompressor, preset=1 << 32) + self.assertRaises(OverflowError, LZMACompressor, preset=1 << 1000) + def test_bad_filter_spec(self): self.assertRaises(TypeError, LZMACompressor, filters=[b"wobsite"]) self.assertRaises(ValueError, LZMACompressor, filters=[{"xyzzy": 3}]) diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 49952947cb..190059e119 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -629,6 +629,7 @@ pbkdf2_hmac(PyObject *self, PyObject *args, PyObject *kwdict) long iterations, dklen; int retval; const EVP_MD *digest; + int overflow = 0; if (!PyArg_ParseTupleAndKeywords(args, kwdict, "sy*y*l|O:pbkdf2_hmac", kwlist, &name, &password, &salt, @@ -668,20 +669,22 @@ pbkdf2_hmac(PyObject *self, PyObject *args, PyObject *kwdict) if (dklen_obj == Py_None) { dklen = EVP_MD_size(digest); } else { - dklen = PyLong_AsLong(dklen_obj); - if ((dklen == -1) && PyErr_Occurred()) { + dklen = PyLong_AsLongAndOverflow(dklen_obj, &overflow); + if (dklen == -1 && PyErr_Occurred()) { goto end; } } - if (dklen < 1) { - PyErr_SetString(PyExc_ValueError, - "key length must be greater than 0."); - goto end; - } - if (dklen > INT_MAX) { - /* INT_MAX is always smaller than dkLen max (2^32 - 1) * hLen */ - PyErr_SetString(PyExc_OverflowError, - "key length is too great."); + if (overflow || dklen > INT_MAX || dklen < 1) { + if (overflow > 0 || dklen > INT_MAX) { + /* INT_MAX is always smaller than dkLen max (2^32 - 1) * hLen */ + PyErr_SetString(PyExc_OverflowError, + "key length is too large."); + } + else { + assert(overflow < 0 || dklen < 1); + PyErr_SetString(PyExc_ValueError, + "key length must be greater than 0."); + } goto end; } diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c index bb77552b67..21841f3dbd 100644 --- a/Modules/_lzmamodule.c +++ b/Modules/_lzmamodule.c @@ -166,22 +166,28 @@ grow_buffer(PyObject **buf, Py_ssize_t max_length) to be strictly correct, we need to define two separate converters. */ -#define INT_TYPE_CONVERTER_FUNC(TYPE, FUNCNAME) \ - static int \ - FUNCNAME(PyObject *obj, void *ptr) \ - { \ - unsigned long long val; \ - \ - val = PyLong_AsUnsignedLongLong(obj); \ - if (PyErr_Occurred()) \ - return 0; \ - if ((unsigned long long)(TYPE)val != val) { \ - PyErr_SetString(PyExc_OverflowError, \ - "Value too large for " #TYPE " type"); \ - return 0; \ - } \ - *(TYPE *)ptr = (TYPE)val; \ - return 1; \ +#define INT_TYPE_CONVERTER_FUNC(TYPE, FUNCNAME) \ + static int \ + FUNCNAME(PyObject *obj, void *ptr) \ + { \ + unsigned long long val; \ + \ + val = PyLong_AsUnsignedLongLong(obj); \ + if (val == (unsigned long long)-1 && PyErr_Occurred()) { \ + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) { \ + return 0; \ + } \ + } \ + else if ((unsigned long long)(TYPE)val == val) { \ + *(TYPE *)ptr = (TYPE)val; \ + return 1; \ + } \ + \ + /* Either PyExc_OverflowError occurred in \ + PyLong_AsUnsignedLongLong, or val didn't fit in TYPE. */ \ + PyErr_SetString(PyExc_OverflowError, \ + "Python int does not fit in C " #TYPE); \ + return 0; \ } INT_TYPE_CONVERTER_FUNC(uint32_t, uint32_converter) diff --git a/Modules/_pickle.c b/Modules/_pickle.c index e65b88e9c0..0c101d1808 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -1812,9 +1812,12 @@ save_long(PicklerObject *self, PyObject *obj) const char long_op = LONG; + assert(PyLong_CheckExact(obj)); val= PyLong_AsLong(obj); if (val == -1 && PyErr_Occurred()) { - /* out of range for int pickling */ + /* PyLong_Check(obj) is true, so it must be that + PyLong_AsLong raised an OverflowError, i.e. obj is out + of range for int pickling */ PyErr_Clear(); } else if (self->bin && @@ -1875,8 +1878,12 @@ save_long(PicklerObject *self, PyObject *obj) return 0; } nbits = _PyLong_NumBits(obj); - if (nbits == (size_t)-1 && PyErr_Occurred()) + if (nbits == (size_t)-1 && PyErr_Occurred()) { + assert(PyErr_ExceptionMatches(PyExc_OverflowError)); + PyErr_SetString(PyExc_OverflowError, + "int too large to pickle"); goto error; + } /* How many bytes do we need? There are nbits >> 3 full * bytes of data, and nbits & 7 leftover bits. If there * are any leftover bits, then we clearly need another