diff --git a/Lib/ctypes/test/test_anon.py b/Lib/ctypes/test/test_anon.py index d892b598985..d378392ebe2 100644 --- a/Lib/ctypes/test/test_anon.py +++ b/Lib/ctypes/test/test_anon.py @@ -1,4 +1,5 @@ import unittest +import test.support from ctypes import * class AnonTest(unittest.TestCase): @@ -35,6 +36,18 @@ class AnonTest(unittest.TestCase): {"_fields_": [], "_anonymous_": ["x"]})) + @test.support.cpython_only + def test_issue31490(self): + # There shouldn't be an assertion failure in case the class has an + # attribute whose name is specified in _anonymous_ but not in _fields_. + + # AttributeError: 'x' is specified in _anonymous_ but not in _fields_ + with self.assertRaises(AttributeError): + class Name(Structure): + _fields_ = [] + _anonymous_ = ["x"] + x = 42 + def test_nested(self): class ANON_S(Structure): _fields_ = [("a", c_int)] diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-09-16-13-32-35.bpo-31490.r7m2sj.rst b/Misc/NEWS.d/next/Core and Builtins/2017-09-16-13-32-35.bpo-31490.r7m2sj.rst new file mode 100644 index 00000000000..d95e825f132 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-09-16-13-32-35.bpo-31490.r7m2sj.rst @@ -0,0 +1,3 @@ +Fix an assertion failure in `ctypes` class definition, in case the class has +an attribute whose name is specified in ``_anonymous_`` but not in +``_fields_``. Patch by Oren Milman. diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index 3496c5706cb..b66c6ecd2f3 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -302,7 +302,15 @@ MakeAnonFields(PyObject *type) Py_DECREF(anon_names); return -1; } - assert(Py_TYPE(descr) == &PyCField_Type); + if (Py_TYPE(descr) != &PyCField_Type) { + PyErr_Format(PyExc_AttributeError, + "'%U' is specified in _anonymous_ but not in " + "_fields_", + fname); + Py_DECREF(anon_names); + Py_DECREF(descr); + return -1; + } descr->anonymous = 1; /* descr is in the field descriptor. */