diff --git a/Lib/ctypes/test/test_delattr.py b/Lib/ctypes/test/test_delattr.py new file mode 100644 index 00000000000..0f4d58691b5 --- /dev/null +++ b/Lib/ctypes/test/test_delattr.py @@ -0,0 +1,21 @@ +import unittest +from ctypes import * + +class X(Structure): + _fields_ = [("foo", c_int)] + +class TestCase(unittest.TestCase): + def test_simple(self): + self.assertRaises(TypeError, + delattr, c_int(42), "value") + + def test_chararray(self): + self.assertRaises(TypeError, + delattr, (c_char * 5)(), "value") + + def test_struct(self): + self.assertRaises(TypeError, + delattr, X(), "foo") + +if __name__ == "__main__": + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS index a45ac11a016..1599ade483b 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -325,6 +325,8 @@ Core and builtins Library ------- +- Issue #1642: Fix segfault in ctypes when trying to delete attributes. + - Issue #1727780: Support loading pickles of random.Random objects created on 32-bit systems on 64-bit systems, and vice versa. As a consequence of the change, Random pickles created by Python 2.6 cannot be loaded diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index d564fb93aa8..03e2e7abdaa 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -788,6 +788,12 @@ CharArray_set_value(CDataObject *self, PyObject *value) char *ptr; Py_ssize_t size; + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, + "can't delete attribute"); + return -1; + } + if (PyUnicode_Check(value)) { value = PyUnicode_AsEncodedString(value, conversion_mode_encoding, @@ -843,6 +849,11 @@ WCharArray_set_value(CDataObject *self, PyObject *value) { Py_ssize_t result = 0; + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, + "can't delete attribute"); + return -1; + } if (PyString_Check(value)) { value = PyUnicode_FromEncodedObject(value, conversion_mode_encoding, @@ -4139,6 +4150,11 @@ Simple_set_value(CDataObject *self, PyObject *value) PyObject *result; StgDictObject *dict = PyObject_stgdict((PyObject *)self); + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, + "can't delete attribute"); + return -1; + } assert(dict); /* Cannot be NULL for CDataObject instances */ assert(dict->setfunc); result = dict->setfunc(self->b_ptr, value, dict->size); diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 77667f544dc..8857e4468e1 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -199,6 +199,11 @@ CField_set(CFieldObject *self, PyObject *inst, PyObject *value) assert(CDataObject_Check(inst)); dst = (CDataObject *)inst; ptr = dst->b_ptr + self->offset; + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, + "can't delete attribute"); + return -1; + } return CData_set(inst, self->proto, self->setfunc, value, self->index, self->size, ptr); }