From d518d8bc8d5dac1a1270612f424d33e0e5afc2b5 Mon Sep 17 00:00:00 2001 From: Oren Milman Date: Thu, 10 May 2018 00:38:56 +0300 Subject: [PATCH] bpo-21983: Fix a crash in ctypes.cast() when passed a ctypes structured data type (GH-3859) --- Lib/ctypes/test/test_cast.py | 13 +++++++++++++ .../2017-10-02-21-02-14.bpo-21983.UoC319.rst | 2 ++ Modules/_ctypes/_ctypes.c | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst diff --git a/Lib/ctypes/test/test_cast.py b/Lib/ctypes/test/test_cast.py index 187d2bde143..6878f973282 100644 --- a/Lib/ctypes/test/test_cast.py +++ b/Lib/ctypes/test/test_cast.py @@ -82,5 +82,18 @@ class Test(unittest.TestCase): self.assertEqual(cast(cast(s, c_void_p), c_wchar_p).value, "hiho") + def test_bad_type_arg(self): + # The type argument must be a ctypes pointer type. + array_type = c_byte * sizeof(c_int) + array = array_type() + self.assertRaises(TypeError, cast, array, None) + self.assertRaises(TypeError, cast, array, array_type) + class Struct(Structure): + _fields_ = [("a", c_int)] + self.assertRaises(TypeError, cast, array, Struct) + class MyUnion(Union): + _fields_ = [("a", c_int)] + self.assertRaises(TypeError, cast, array, MyUnion) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst b/Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst new file mode 100644 index 00000000000..88a03685073 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst @@ -0,0 +1,2 @@ +Fix a crash in `ctypes.cast()` in case the type argument is a ctypes +structured data type. Patch by Eryk Sun and Oren Milman. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 93e8d8d4233..5bf49acb6c2 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -5319,7 +5319,7 @@ cast_check_pointertype(PyObject *arg) if (PyCFuncPtrTypeObject_Check(arg)) return 1; dict = PyType_stgdict(arg); - if (dict) { + if (dict != NULL && dict->proto != NULL) { if (PyUnicode_Check(dict->proto) && (strchr("sPzUZXO", PyUnicode_AsUTF8(dict->proto)[0]))) { /* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */