bpo-29843: raise AttributeError if given negative _length_ (GH-10029)
Raise ValueError OverflowError in case of a negative _length_ in a ctypes.Array subclass. Also raise TypeError instead of AttributeError for non-integer _length_. Co-authored-by: Oren Milman <orenmn@gmail.com>
This commit is contained in:
parent
121eb1694c
commit
2447773573
|
@ -163,8 +163,6 @@ class ArrayTestCase(unittest.TestCase):
|
||||||
self.assertEqual(Y()._length_, 187)
|
self.assertEqual(Y()._length_, 187)
|
||||||
|
|
||||||
def test_bad_subclass(self):
|
def test_bad_subclass(self):
|
||||||
import sys
|
|
||||||
|
|
||||||
with self.assertRaises(AttributeError):
|
with self.assertRaises(AttributeError):
|
||||||
class T(Array):
|
class T(Array):
|
||||||
pass
|
pass
|
||||||
|
@ -174,14 +172,30 @@ class ArrayTestCase(unittest.TestCase):
|
||||||
with self.assertRaises(AttributeError):
|
with self.assertRaises(AttributeError):
|
||||||
class T(Array):
|
class T(Array):
|
||||||
_length_ = 13
|
_length_ = 13
|
||||||
|
|
||||||
|
def test_bad_length(self):
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
class T(Array):
|
||||||
|
_type_ = c_int
|
||||||
|
_length_ = - sys.maxsize * 2
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
class T(Array):
|
||||||
|
_type_ = c_int
|
||||||
|
_length_ = -1
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
class T(Array):
|
||||||
|
_type_ = c_int
|
||||||
|
_length_ = 1.87
|
||||||
with self.assertRaises(OverflowError):
|
with self.assertRaises(OverflowError):
|
||||||
class T(Array):
|
class T(Array):
|
||||||
_type_ = c_int
|
_type_ = c_int
|
||||||
_length_ = sys.maxsize * 2
|
_length_ = sys.maxsize * 2
|
||||||
with self.assertRaises(AttributeError):
|
|
||||||
class T(Array):
|
def test_zero_length(self):
|
||||||
_type_ = c_int
|
# _length_ can be zero.
|
||||||
_length_ = 1.87
|
class T(Array):
|
||||||
|
_type_ = c_int
|
||||||
|
_length_ = 0
|
||||||
|
|
||||||
@unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform')
|
@unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform')
|
||||||
@bigmemtest(size=_2G, memuse=1, dry_run=False)
|
@bigmemtest(size=_2G, memuse=1, dry_run=False)
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Raise :exc:`ValueError` instead of :exc:`OverflowError` in case of a negative
|
||||||
|
``_length_`` in a :class:`ctypes.Array` subclass. Also raise :exc:`TypeError`
|
||||||
|
instead of :exc:`AttributeError` for non-integer ``_length_``.
|
||||||
|
Original patch by Oren Milman.
|
|
@ -1405,13 +1405,28 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
type_attr = NULL;
|
type_attr = NULL;
|
||||||
|
|
||||||
length_attr = PyObject_GetAttrString((PyObject *)result, "_length_");
|
length_attr = PyObject_GetAttrString((PyObject *)result, "_length_");
|
||||||
if (!length_attr || !PyLong_Check(length_attr)) {
|
if (!length_attr) {
|
||||||
PyErr_SetString(PyExc_AttributeError,
|
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
||||||
"class must define a '_length_' attribute, "
|
PyErr_SetString(PyExc_AttributeError,
|
||||||
"which must be a positive integer");
|
"class must define a '_length_' attribute");
|
||||||
Py_XDECREF(length_attr);
|
}
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!PyLong_Check(length_attr)) {
|
||||||
|
Py_DECREF(length_attr);
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"The '_length_' attribute must be an integer");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_PyLong_Sign(length_attr) == -1) {
|
||||||
|
Py_DECREF(length_attr);
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"The '_length_' attribute must not be negative");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
length = PyLong_AsSsize_t(length_attr);
|
length = PyLong_AsSsize_t(length_attr);
|
||||||
Py_DECREF(length_attr);
|
Py_DECREF(length_attr);
|
||||||
if (length == -1 && PyErr_Occurred()) {
|
if (length == -1 && PyErr_Occurred()) {
|
||||||
|
|
Loading…
Reference in New Issue