From 8f459255eba2b6639f1912e5c5e318a7cdafada1 Mon Sep 17 00:00:00 2001 From: VanshAgarwal24036 <148854295+VanshAgarwal24036@users.noreply.github.com> Date: Mon, 26 Jan 2026 17:57:42 +0530 Subject: [PATCH] gh-144100: Fix crash for POINTER(str) used in ctypes argtypes (#144108) Co-authored-by: Victor Stinner --- Lib/test/test_ctypes/test_pointers.py | 10 ++++++++++ .../2026-01-21-19-39-07.gh-issue-144100.hLMZ8Y.rst | 3 +++ Modules/_ctypes/_ctypes.c | 8 +++++++- 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2026-01-21-19-39-07.gh-issue-144100.hLMZ8Y.rst diff --git a/Lib/test/test_ctypes/test_pointers.py b/Lib/test/test_ctypes/test_pointers.py index a8d243a45de0..771cc8fbe0ec 100644 --- a/Lib/test/test_ctypes/test_pointers.py +++ b/Lib/test/test_ctypes/test_pointers.py @@ -403,6 +403,16 @@ class PointersTestCase(unittest.TestCase): self.assertEqual(len(ws_typ), 0, ws_typ) self.assertEqual(len(ws_ptr), 0, ws_ptr) + def test_pointer_proto_missing_argtypes_error(self): + class BadType(ctypes._Pointer): + # _type_ is intentionally missing + pass + + func = ctypes.pythonapi.Py_GetVersion + func.argtypes = (BadType,) + + with self.assertRaises(ctypes.ArgumentError): + func(object()) class PointerTypeCacheTestCase(unittest.TestCase): # dummy tests to check warnings and base behavior diff --git a/Misc/NEWS.d/next/Library/2026-01-21-19-39-07.gh-issue-144100.hLMZ8Y.rst b/Misc/NEWS.d/next/Library/2026-01-21-19-39-07.gh-issue-144100.hLMZ8Y.rst new file mode 100644 index 000000000000..7093b753141f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-01-21-19-39-07.gh-issue-144100.hLMZ8Y.rst @@ -0,0 +1,3 @@ +Fixed a crash in ctypes when using a deprecated ``POINTER(str)`` type in +``argtypes``. Instead of aborting, ctypes now raises a proper Python +exception when the pointer target type is unresolved. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 563e95a76259..6d9193af657e 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1419,7 +1419,13 @@ PyCPointerType_from_param_impl(PyObject *type, PyTypeObject *cls, /* If we expect POINTER(), but receive a instance, accept it by calling byref(). */ - assert(typeinfo->proto); + if (typeinfo->proto == NULL) { + PyErr_SetString( + PyExc_TypeError, + "cannot convert argument: POINTER _type_ type is not set" + ); + return NULL; + } switch (PyObject_IsInstance(value, typeinfo->proto)) { case 1: Py_INCREF(value); /* _byref steals a refcount */ -- 2.47.3