diff --git a/Doc/c-api/arg.rst b/Doc/c-api/arg.rst index 0b05e868917a4e..bebfcd42ca44cc 100644 --- a/Doc/c-api/arg.rst +++ b/Doc/c-api/arg.rst @@ -249,6 +249,10 @@ small to receive the value. Convert a nonnegative Python integer to an unsigned tiny integer, stored in a C :c:expr:`unsigned char`. + .. versionchanged:: next + A negative Python integer now raises :exc:`ValueError`, + not :exc:`OverflowError`. + ``B`` (:class:`int`) [unsigned char] Convert a Python integer to a tiny integer without overflow checking, stored in a C :c:expr:`unsigned char`. diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst index 25d9e62e387279..6c911d284bbdbd 100644 --- a/Doc/c-api/long.rst +++ b/Doc/c-api/long.rst @@ -286,12 +286,15 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. Return a C :c:expr:`unsigned long` representation of *pylong*. *pylong* must be an instance of :c:type:`PyLongObject`. - Raise :exc:`OverflowError` if the value of *pylong* is out of range for a - :c:expr:`unsigned long`. + Raise :exc:`ValueError` if the value of *pylong* is negative and + :exc:`OverflowError` if it is out of range for a :c:expr:`unsigned long`. Returns ``(unsigned long)-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. + .. versionchanged:: next + A negative *pylong* now raises :exc:`ValueError`, not :exc:`OverflowError`. + .. c:function:: size_t PyLong_AsSize_t(PyObject *pylong) @@ -302,12 +305,15 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. Return a C :c:type:`size_t` representation of *pylong*. *pylong* must be an instance of :c:type:`PyLongObject`. - Raise :exc:`OverflowError` if the value of *pylong* is out of range for a - :c:type:`size_t`. + Raise :exc:`ValueError` if the value of *pylong* is negative and + :exc:`OverflowError` if it is out of range for a :c:type:`size_t`. Returns ``(size_t)-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. + .. versionchanged:: next + A negative *pylong* now raises :exc:`ValueError`, not :exc:`OverflowError`. + .. c:function:: unsigned long long PyLong_AsUnsignedLongLong(PyObject *pylong) @@ -317,8 +323,8 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. Return a C :c:expr:`unsigned long long` representation of *pylong*. *pylong* must be an instance of :c:type:`PyLongObject`. - Raise :exc:`OverflowError` if the value of *pylong* is out of range for an - :c:expr:`unsigned long long`. + Raise :exc:`ValueError` if the value of *pylong* is negative and + :exc:`OverflowError` if it is out of range for a :c:expr:`unsigned long long`. Returns ``(unsigned long long)-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. @@ -326,6 +332,9 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. .. versionchanged:: 3.1 A negative *pylong* now raises :exc:`OverflowError`, not :exc:`TypeError`. + .. versionchanged:: next + A negative *pylong* now raises :exc:`ValueError`, not :exc:`OverflowError`. + .. c:function:: unsigned long PyLong_AsUnsignedLongMask(PyObject *obj) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 39aaa5da0786f8..78e529fffa144d 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -534,7 +534,7 @@ class`. In addition, it provides a few more methods: The *signed* argument determines whether two's complement is used to represent the integer. If *signed* is ``False`` and a negative integer is - given, an :exc:`OverflowError` is raised. The default value for *signed* + given, a :exc:`ValueError` is raised. The default value for *signed* is ``False``. The default values can be used to conveniently turn an integer into a @@ -559,8 +559,14 @@ class`. In addition, it provides a few more methods: return bytes((n >> i*8) & 0xff for i in order) .. versionadded:: 3.2 + .. versionchanged:: 3.11 - Added default argument values for ``length`` and ``byteorder``. + Added default argument values for *length* and *byteorder*. + + .. versionchanged:: next + Raise :exc:`ValueError` instead of :exc:`OverflowError` for + negative integer if *signed* is false. + .. classmethod:: int.from_bytes(bytes, byteorder='big', *, signed=False) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 646a0b4007fc05..0aedcaf67c869f 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -1920,6 +1920,10 @@ Others integer must implement either :meth:`~object.__int__` or :meth:`~object.__index__`. (Contributed by Mark Dickinson in :gh:`119743`.) +* Converting negative Python integer to a C unsigned integer type now raises + :exc:`ValueError`, not :exc:`OverflowError`. + (Contributed by Serhiy Storchaka in :gh:`74020`.) + CPython Bytecode Changes ======================== diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index 58ea89c4fac833..8e5d4204a93d77 100755 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -1326,8 +1326,9 @@ def check_overflow(self, lower, upper): a = array.array(self.typecode, [lower]) a[0] = lower # should overflow assigning less than lower limit - self.assertRaises(OverflowError, array.array, self.typecode, [lower-1]) - self.assertRaises(OverflowError, a.__setitem__, 0, lower-1) + exc = ValueError if int(lower) == 0 else OverflowError + self.assertRaises(exc, array.array, self.typecode, [lower-1]) + self.assertRaises(exc, a.__setitem__, 0, lower-1) # should not overflow assigning upper limit a = array.array(self.typecode, [upper]) a[0] = upper diff --git a/Lib/test/test_capi/test_getargs.py b/Lib/test/test_capi/test_getargs.py index 67a8da7599511f..a1f5cca10b1b7f 100644 --- a/Lib/test/test_capi/test_getargs.py +++ b/Lib/test/test_capi/test_getargs.py @@ -182,7 +182,7 @@ def test_b(self): self.assertRaises(TypeError, getargs_b, BadInt2()) self.assertEqual(0, getargs_b(BadInt3())) - self.assertRaises(OverflowError, getargs_b, -1) + self.assertRaises(ValueError, getargs_b, -1) self.assertEqual(0, getargs_b(0)) self.assertEqual(UCHAR_MAX, getargs_b(UCHAR_MAX)) self.assertRaises(OverflowError, getargs_b, UCHAR_MAX + 1) diff --git a/Lib/test/test_capi/test_long.py b/Lib/test/test_capi/test_long.py index d3156645eeec2d..b6d4735181ad9c 100644 --- a/Lib/test/test_capi/test_long.py +++ b/Lib/test/test_capi/test_long.py @@ -165,8 +165,7 @@ def test_long_fromunicodeobject(self): def check_long_asint(self, func, min_val, max_val, *, use_index=True, - mask=False, - negative_value_error=OverflowError): + mask=False): # round trip (object -> C integer -> object) values = (0, 1, 512, 1234, max_val) if min_val < 0: @@ -190,6 +189,7 @@ def check_long_asint(self, func, min_val, max_val, *, self.assertEqual(func(-1 << 1000), 0) self.assertEqual(func(1 << 1000), 0) else: + negative_value_error = ValueError if min_val == 0 else OverflowError self.assertRaises(negative_value_error, func, min_val - 1) self.assertRaises(negative_value_error, func, -1 << 1000) self.assertRaises(OverflowError, func, max_val + 1) @@ -236,8 +236,7 @@ def test_long_asunsignedlong(self): # Test PyLong_AsUnsignedLong() and PyLong_FromUnsignedLong() asunsignedlong = _testlimitedcapi.pylong_asunsignedlong from _testcapi import ULONG_MAX - self.check_long_asint(asunsignedlong, 0, ULONG_MAX, - use_index=False) + self.check_long_asint(asunsignedlong, 0, ULONG_MAX, use_index=False) def test_long_asunsignedlongmask(self): # Test PyLong_AsUnsignedLongMask() @@ -704,15 +703,13 @@ def test_long_asuint32(self): # Test PyLong_AsUInt32() and PyLong_FromUInt32() as_uint32 = _testlimitedcapi.pylong_asuint32 from _testcapi import UINT32_MAX - self.check_long_asint(as_uint32, 0, UINT32_MAX, - negative_value_error=ValueError) + self.check_long_asint(as_uint32, 0, UINT32_MAX) def test_long_asuint64(self): # Test PyLong_AsUInt64() and PyLong_FromUInt64() as_uint64 = _testlimitedcapi.pylong_asuint64 from _testcapi import UINT64_MAX - self.check_long_asint(as_uint64, 0, UINT64_MAX, - negative_value_error=ValueError) + self.check_long_asint(as_uint64, 0, UINT64_MAX) def test_long_layout(self): # Test PyLong_GetNativeLayout() diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py index f336d49fa4f008..3363ec932a3288 100644 --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -1377,8 +1377,8 @@ def equivalent_python(n, length, byteorder, signed=False): self.assertRaises(OverflowError, (256).to_bytes, 1, 'big', signed=True) self.assertRaises(OverflowError, (256).to_bytes, 1, 'little', signed=False) self.assertRaises(OverflowError, (256).to_bytes, 1, 'little', signed=True) - self.assertRaises(OverflowError, (-1).to_bytes, 2, 'big', signed=False) - self.assertRaises(OverflowError, (-1).to_bytes, 2, 'little', signed=False) + self.assertRaises(ValueError, (-1).to_bytes, 2, 'big', signed=False) + self.assertRaises(ValueError, (-1).to_bytes, 2, 'little', signed=False) self.assertEqual((0).to_bytes(0, 'big'), b'') self.assertEqual((1).to_bytes(5, 'big'), b'\x00\x00\x00\x00\x01') self.assertEqual((0).to_bytes(5, 'big'), b'\x00\x00\x00\x00\x00') diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 333179a71e3cdc..ff7732d4da0428 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -3564,7 +3564,7 @@ def test_waitstatus_to_exitcode_windows(self): # invalid values with self.assertRaises(ValueError): os.waitstatus_to_exitcode((max_exitcode + 1) << 8) - with self.assertRaises(OverflowError): + with self.assertRaises(ValueError): os.waitstatus_to_exitcode(-1) # Skip the test on Windows diff --git a/Lib/test/test_winreg.py b/Lib/test/test_winreg.py index 924a962781a75b..5a27b129d47426 100644 --- a/Lib/test/test_winreg.py +++ b/Lib/test/test_winreg.py @@ -359,8 +359,9 @@ def test_setvalueex_negative_one_check(self): # the value set was not -1. try: with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck: - with self.assertRaises(OverflowError): + with self.assertRaises(ValueError): SetValueEx(ck, "test_name_dword", None, REG_DWORD, -1) + with self.assertRaises(ValueError): SetValueEx(ck, "test_name_qword", None, REG_QWORD, -1) self.assertRaises(FileNotFoundError, QueryValueEx, ck, "test_name_dword") self.assertRaises(FileNotFoundError, QueryValueEx, ck, "test_name_qword") diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-06-28-10-51-56.gh-issue-74020.FcEAzj.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-06-28-10-51-56.gh-issue-74020.FcEAzj.rst new file mode 100644 index 00000000000000..c635861718173e --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-06-28-10-51-56.gh-issue-74020.FcEAzj.rst @@ -0,0 +1,2 @@ +Converting negative Python integer to a C unsigned integer type now raises +:exc:`ValueError`, not :exc:`OverflowError`. diff --git a/Modules/_struct.c b/Modules/_struct.c index ee757ed8a9d29d..ba2a5d9b716654 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -633,7 +633,9 @@ np_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) unsigned long x; unsigned int y; if (get_ulong(state, v, &x) < 0) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + if (PyErr_ExceptionMatches(PyExc_OverflowError) || + PyErr_ExceptionMatches(PyExc_ValueError)) + { RANGE_ERROR(state, f, 1); } return -1; @@ -666,7 +668,9 @@ np_ulong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { unsigned long x; if (get_ulong(state, v, &x) < 0) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + if (PyErr_ExceptionMatches(PyExc_OverflowError) || + PyErr_ExceptionMatches(PyExc_ValueError)) + { RANGE_ERROR(state, f, 1); } return -1; @@ -694,7 +698,9 @@ np_size_t(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { size_t x; if (get_size_t(state, v, &x) < 0) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + if (PyErr_ExceptionMatches(PyExc_OverflowError) || + PyErr_ExceptionMatches(PyExc_ValueError)) + { RANGE_ERROR(state, f, 1); } return -1; @@ -726,7 +732,9 @@ np_ulonglong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f { unsigned long long x; if (get_ulonglong(state, v, &x) < 0) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + if (PyErr_ExceptionMatches(PyExc_OverflowError) || + PyErr_ExceptionMatches(PyExc_ValueError)) + { PyErr_Format(state->StructError, "'%c' format requires 0 <= number <= %llu", f->format, @@ -1058,7 +1066,9 @@ bp_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) Py_ssize_t i; unsigned char *q = (unsigned char *)p; if (get_ulong(state, v, &x) < 0) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + if (PyErr_ExceptionMatches(PyExc_OverflowError) || + PyErr_ExceptionMatches(PyExc_ValueError)) + { RANGE_ERROR(state, f, 1); } return -1; @@ -1391,7 +1401,9 @@ lp_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) Py_ssize_t i; unsigned char *q = (unsigned char *)p; if (get_ulong(state, v, &x) < 0) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + if (PyErr_ExceptionMatches(PyExc_OverflowError) || + PyErr_ExceptionMatches(PyExc_ValueError)) + { RANGE_ERROR(state, f, 1); } return -1; @@ -2213,9 +2225,13 @@ s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset, *res = Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char); } else { if (e->pack(state, res, v, e) < 0) { - if (PyLong_Check(v) && PyErr_ExceptionMatches(PyExc_OverflowError)) + if (PyLong_Check(v) && + (PyErr_ExceptionMatches(PyExc_OverflowError) || + PyErr_ExceptionMatches(PyExc_ValueError))) + { PyErr_SetString(state->StructError, "int too large to convert"); + } return -1; } } diff --git a/Modules/_testlimitedcapi/testcapi_long.h b/Modules/_testlimitedcapi/testcapi_long.h index 143258140b4bb4..dd139fc4554a45 100644 --- a/Modules/_testlimitedcapi/testcapi_long.h +++ b/Modules/_testlimitedcapi/testcapi_long.h @@ -96,10 +96,10 @@ TESTNAME(PyObject *error(const char*)) if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred()) return error( "PyLong_AsUnsignedXXX(-1) didn't complain"); - if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + if (!PyErr_ExceptionMatches(PyExc_ValueError)) return error( "PyLong_AsUnsignedXXX(-1) raised " - "something other than OverflowError"); + "something other than ValueError"); PyErr_Clear(); UNBIND(x); diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 401a3a7072b846..a2b9aae819d816 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -214,20 +214,23 @@ b_getitem(arrayobject *ap, Py_ssize_t i) static int b_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) { - short x; - /* PyArg_Parse's 'b' formatter is for an unsigned char, therefore - must use the next size up that is signed ('h') and manually do - the overflow checking */ - if (!PyArg_Parse(v, "h;array item must be integer", &x)) + int overflow; + long x = PyLong_AsLongAndOverflow(v, &overflow); + if (x == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_TypeError)) { + PyErr_SetString(PyExc_TypeError, + "array item must be integer"); + } return -1; - else if (x < -128) { + } + if (overflow > 0 || x > 127) { PyErr_SetString(PyExc_OverflowError, - "signed char is less than minimum"); + "signed char is greater than maximum"); return -1; } - else if (x > 127) { + if (overflow < 0 || x < -128) { PyErr_SetString(PyExc_OverflowError, - "signed char is greater than maximum"); + "signed char is less than minimum"); return -1; } if (i >= 0) @@ -355,21 +358,25 @@ HH_getitem(arrayobject *ap, Py_ssize_t i) static int HH_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) { - int x; - /* PyArg_Parse's 'h' formatter is for a signed short, therefore - must use the next size up and manually do the overflow checking */ - if (!PyArg_Parse(v, "i;array item must be integer", &x)) - return -1; - else if (x < 0) { - PyErr_SetString(PyExc_OverflowError, - "unsigned short is less than minimum"); + int overflow; + long x = PyLong_AsLongAndOverflow(v, &overflow); + if (x == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_TypeError)) { + PyErr_SetString(PyExc_TypeError, + "array item must be integer"); + } return -1; } - else if (x > USHRT_MAX) { + if (overflow > 0 || x > USHRT_MAX) { PyErr_SetString(PyExc_OverflowError, "unsigned short is greater than maximum"); return -1; } + if (overflow < 0 || x < 0) { + PyErr_SetString(PyExc_ValueError, + "unsigned short is less than minimum"); + return -1; + } if (i >= 0) ((short *)ap->ob_item)[i] = (short)x; return 0; diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 11d9b7418a25a2..24501d886929c0 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -3952,13 +3952,6 @@ math_nextafter_impl(PyObject *module, double x, double y, PyObject *steps) return NULL; } assert(PyLong_CheckExact(steps)); - if (_PyLong_IsNegative((PyLongObject *)steps)) { - PyErr_SetString(PyExc_ValueError, - "steps must be a non-negative integer"); - Py_DECREF(steps); - return NULL; - } - unsigned long long usteps_ull = PyLong_AsUnsignedLongLong(steps); // Conveniently, uint64_t and double have the same number of bits // on all the platforms we care about. @@ -3970,7 +3963,12 @@ math_nextafter_impl(PyObject *module, double x, double y, PyObject *steps) // usteps_ull can be strictly larger than UINT64_MAX on a machine // where unsigned long long has width > 64 bits. if (PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + if (PyErr_ExceptionMatches(PyExc_ValueError)) { + PyErr_SetString(PyExc_ValueError, + "steps must be a non-negative integer"); + return NULL; + } + else if (PyErr_ExceptionMatches(PyExc_OverflowError)) { PyErr_Clear(); } else { diff --git a/Modules/pwdmodule.c b/Modules/pwdmodule.c index 2240e2078b2d98..d11051352f74d2 100644 --- a/Modules/pwdmodule.c +++ b/Modules/pwdmodule.c @@ -141,9 +141,12 @@ pwd_getpwuid(PyObject *module, PyObject *uidobj) char *buf = NULL, *buf2 = NULL; if (!_Py_Uid_Converter(uidobj, &uid)) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) + if (PyErr_ExceptionMatches(PyExc_OverflowError) || + PyErr_ExceptionMatches(PyExc_ValueError)) + { PyErr_Format(PyExc_KeyError, "getpwuid(): uid not found"); + } return NULL; } #ifdef HAVE_GETPWUID_R diff --git a/Objects/longobject.c b/Objects/longobject.c index 40d90ecf4fa068..21b658b893df54 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -703,7 +703,7 @@ PyLong_AsUnsignedLong(PyObject *vv) #endif } if (_PyLong_IsNegative(v)) { - PyErr_SetString(PyExc_OverflowError, + PyErr_SetString(PyExc_ValueError, "can't convert negative value to unsigned int"); return (unsigned long) -1; } @@ -748,7 +748,7 @@ PyLong_AsSize_t(PyObject *vv) return (size_t)_PyLong_CompactValue(v); } if (_PyLong_IsNegative(v)) { - PyErr_SetString(PyExc_OverflowError, + PyErr_SetString(PyExc_ValueError, "can't convert negative value to size_t"); return (size_t) -1; } @@ -1056,7 +1056,7 @@ _PyLong_AsByteArray(PyLongObject* v, if (_PyLong_IsNegative(v)) { if (!is_signed) { if (with_exceptions) { - PyErr_SetString(PyExc_OverflowError, + PyErr_SetString(PyExc_ValueError, "can't convert negative int to unsigned"); } return -1; diff --git a/Python/getargs.c b/Python/getargs.c index 0cf596285cc7b5..f966660fb201d5 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -713,19 +713,21 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, case 'b': { /* unsigned byte -- very short int */ unsigned char *p = va_arg(*p_va, unsigned char *); HANDLE_NULLABLE; - long ival = PyLong_AsLong(arg); + int overflow; + long ival = PyLong_AsLongAndOverflow(arg, &overflow); if (ival == -1 && PyErr_Occurred()) RETURN_ERR_OCCURRED; - else if (ival < 0) { + else if (overflow > 0 || ival > UCHAR_MAX) { PyErr_SetString(PyExc_OverflowError, - "unsigned byte integer is less than minimum"); + "unsigned byte integer is greater than maximum"); RETURN_ERR_OCCURRED; } - else if (ival > UCHAR_MAX) { - PyErr_SetString(PyExc_OverflowError, - "unsigned byte integer is greater than maximum"); + else if (overflow < 0 || ival < 0) { + PyErr_SetString(PyExc_ValueError, + "unsigned byte integer is less than minimum"); RETURN_ERR_OCCURRED; } + else *p = (unsigned char) ival; break; } @@ -745,17 +747,18 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, case 'h': {/* signed short int */ short *p = va_arg(*p_va, short *); HANDLE_NULLABLE; - long ival = PyLong_AsLong(arg); + int overflow; + long ival = PyLong_AsLongAndOverflow(arg, &overflow); if (ival == -1 && PyErr_Occurred()) RETURN_ERR_OCCURRED; - else if (ival < SHRT_MIN) { + else if (overflow > 0 || ival > SHRT_MAX) { PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); + "signed short integer is greater than maximum"); RETURN_ERR_OCCURRED; } - else if (ival > SHRT_MAX) { + else if (overflow < 0 || ival < SHRT_MIN) { PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); + "signed short integer is less than minimum"); RETURN_ERR_OCCURRED; } else @@ -778,15 +781,16 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, case 'i': {/* signed int */ int *p = va_arg(*p_va, int *); HANDLE_NULLABLE; - long ival = PyLong_AsLong(arg); + int overflow; + long ival = PyLong_AsLongAndOverflow(arg, &overflow); if (ival == -1 && PyErr_Occurred()) RETURN_ERR_OCCURRED; - else if (ival > INT_MAX) { + else if (overflow > 0 || ival > INT_MAX) { PyErr_SetString(PyExc_OverflowError, "signed integer is greater than maximum"); RETURN_ERR_OCCURRED; } - else if (ival < INT_MIN) { + else if (overflow < 0 || ival < INT_MIN) { PyErr_SetString(PyExc_OverflowError, "signed integer is less than minimum"); RETURN_ERR_OCCURRED; diff --git a/Python/initconfig.c b/Python/initconfig.c index 7d3043dd5d1dd9..648b4e1942ed4e 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -1343,7 +1343,9 @@ config_dict_get_ulong(PyObject *dict, const char *name, unsigned long *result) if (PyErr_ExceptionMatches(PyExc_TypeError)) { config_dict_invalid_type(name); } - else if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + else if (PyErr_ExceptionMatches(PyExc_OverflowError) || + PyErr_ExceptionMatches(PyExc_ValueError)) + { config_dict_invalid_value(name); } return -1;