diff --git a/Lib/ctypes/test/test_arrays.py b/Lib/ctypes/test/test_arrays.py index 4ed566b48e..5990906eae 100644 --- a/Lib/ctypes/test/test_arrays.py +++ b/Lib/ctypes/test/test_arrays.py @@ -181,5 +181,28 @@ class ArrayTestCase(unittest.TestCase): _type_ = c_int _length_ = 1.87 + def test_bad_length(self): + from _testcapi import LONG_MAX + + with self.assertRaises(ValueError): + class T(Array): + _type_ = c_int + _length_ = -1 << 1000 + with self.assertRaises(ValueError): + class T(Array): + _type_ = c_int + _length_ = -1 + class T(Array): + _type_ = c_int + _length_ = 0 + with self.assertRaises(OverflowError): + class T(Array): + _type_ = c_int + _length_ = LONG_MAX + 1 + with self.assertRaises(OverflowError): + class T(Array): + _type_ = c_int + _length_ = 1 << 1000 + if __name__ == '__main__': unittest.main() diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 9d42109b51..8143633529 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1349,9 +1349,19 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) goto error; } length = PyLong_AsLongAndOverflow(length_attr, &overflow); - if (overflow) { - PyErr_SetString(PyExc_OverflowError, - "The '_length_' attribute is too large"); + /* PyLong_Check(length_attr) is true, so it is guaranteed that + no error occurred in PyLong_AsLongAndOverflow. */ + assert(!(length == -1 && PyErr_Occurred())); + if (overflow || length < 0) { + if (overflow == 1) { + PyErr_SetString(PyExc_OverflowError, + "The '_length_' attribute is too large"); + } + else { + assert(overflow == -1 || length < 0); + PyErr_SetString(PyExc_ValueError, + "The '_length_' attribute must be non-negative"); + } Py_DECREF(length_attr); goto error; }