From 14c13955c59c15bd58520241ce64e27c68028d64 Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Sun, 13 Nov 2022 11:40:18 -0800 Subject: [PATCH] gh-99275: Fix `SystemError` in `ctypes` during `__initsubclass__` (GH-99283) (cherry picked from commit 343eb0f94b26f2a4c1c15505d417e8157ec19660) Co-authored-by: Nikita Sobolev --- Lib/ctypes/test/test_struct_fields.py | 9 +++++++++ .../2022-11-09-12-16-35.gh-issue-99275.klOqoL.rst | 2 ++ Modules/_ctypes/stgdict.c | 5 ++++- 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2022-11-09-12-16-35.gh-issue-99275.klOqoL.rst diff --git a/Lib/ctypes/test/test_struct_fields.py b/Lib/ctypes/test/test_struct_fields.py index ee8415f3e63..fefeaea1496 100644 --- a/Lib/ctypes/test/test_struct_fields.py +++ b/Lib/ctypes/test/test_struct_fields.py @@ -54,6 +54,15 @@ class X(Structure): x.char = b'a\0b\0' self.assertEqual(bytes(x), b'a\x00###') + def test_gh99275(self): + class BrokenStructure(Structure): + def __init_subclass__(cls, **kwargs): + cls._fields_ = [] # This line will fail, `stgdict` is not ready + + with self.assertRaisesRegex(TypeError, + 'ctypes state is not initialized'): + class Subclass(BrokenStructure): ... + # __set__ and __get__ should raise a TypeError in case their self # argument is not a ctype instance. def test___set__(self): diff --git a/Misc/NEWS.d/next/Library/2022-11-09-12-16-35.gh-issue-99275.klOqoL.rst b/Misc/NEWS.d/next/Library/2022-11-09-12-16-35.gh-issue-99275.klOqoL.rst new file mode 100644 index 00000000000..2bf05a3bdfb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-11-09-12-16-35.gh-issue-99275.klOqoL.rst @@ -0,0 +1,2 @@ +Fix ``SystemError`` in :mod:`ctypes` when exception was not set during +``__initsubclass__``. diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index 747339dee35..f9811aced7c 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -420,8 +420,11 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct } stgdict = PyType_stgdict(type); - if (!stgdict) + if (!stgdict) { + PyErr_SetString(PyExc_TypeError, + "ctypes state is not initialized"); return -1; + } /* If this structure/union is already marked final we cannot assign _fields_ anymore. */