From bdb215b18a42360b6a9c82876fa71f19ca1a416d Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
 <31488909+miss-islington@users.noreply.github.com>
Date: Tue, 26 Sep 2017 21:37:37 -0700
Subject: [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 30b61b51e05d2d43e8e2e783b0a9df738535423b)
---
 Lib/ctypes/test/test_anon.py                                | 13 +++++++++++++
 .../2017-09-16-13-32-35.bpo-31490.r7m2sj.rst                |  3 +++
 Modules/_ctypes/stgdict.c                                   | 10 +++++++++-
 3 files changed, 25 insertions(+), 1 deletion(-)
 create mode 100644 Misc/NEWS.d/next/Core and Builtins/2017-09-16-13-32-35.bpo-31490.r7m2sj.rst

diff --git a/Lib/ctypes/test/test_anon.py b/Lib/ctypes/test/test_anon.py
index d892b59..d378392 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 0000000..d95e825
--- /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 716d1e9..8278b2f 100644
--- a/Modules/_ctypes/stgdict.c
+++ b/Modules/_ctypes/stgdict.c
@@ -282,7 +282,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. */
-- 
cgit v0.12