Skip to content

Commit bdb215b

Browse files
miss-islingtonserhiy-storchaka
authored andcommitted
[3.6] bpo-31490: Fix an assertion failure in ctypes in case an _anonymous_ attr is defined only outside _fields_. (GH-3615) (#3774)
(cherry picked from commit 30b61b5)
1 parent f0db2df commit bdb215b

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

‎Lib/ctypes/test/test_anon.py‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import unittest
2+
import test.support
23
from ctypes import *
34

45
class AnonTest(unittest.TestCase):
@@ -35,6 +36,18 @@ def test_anon_nonmember(self):
3536
{"_fields_": [],
3637
"_anonymous_": ["x"]}))
3738

39+
@test.support.cpython_only
40+
def test_issue31490(self):
41+
# There shouldn't be an assertion failure in case the class has an
42+
# attribute whose name is specified in _anonymous_ but not in _fields_.
43+
44+
# AttributeError: 'x' is specified in _anonymous_ but not in _fields_
45+
with self.assertRaises(AttributeError):
46+
class Name(Structure):
47+
_fields_ = []
48+
_anonymous_ = ["x"]
49+
x = 42
50+
3851
def test_nested(self):
3952
class ANON_S(Structure):
4053
_fields_ = [("a", c_int)]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix an assertion failure in `ctypes` class definition, in case the class has
2+
an attribute whose name is specified in ``_anonymous_`` but not in
3+
``_fields_``. Patch by Oren Milman.

‎Modules/_ctypes/stgdict.c‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,15 @@ MakeAnonFields(PyObject *type)
282282
Py_DECREF(anon_names);
283283
return -1;
284284
}
285-
assert(Py_TYPE(descr) == &PyCField_Type);
285+
if (Py_TYPE(descr) != &PyCField_Type) {
286+
PyErr_Format(PyExc_AttributeError,
287+
"'%U' is specified in _anonymous_ but not in "
288+
"_fields_",
289+
fname);
290+
Py_DECREF(anon_names);
291+
Py_DECREF(descr);
292+
return -1;
293+
}
286294
descr->anonymous = 1;
287295

288296
/* descr is in the field descriptor. */

0 commit comments

Comments
 (0)