From 8617d769fa1f2e79a58ff25acfef22cba7c1e79c Mon Sep 17 00:00:00 2001 From: VanshAgarwal24036 Date: Wed, 21 Jan 2026 19:40:05 +0530 Subject: [PATCH 1/7] gh-144100: Fix crash for POINTER(str) used in ctypes argtypes --- Lib/test/test_ctypes/test_pointers.py | 18 ++++++++++++++++++ ...6-01-21-19-39-07.gh-issue-144100.hLMZ8Y.rst | 3 +++ Modules/_ctypes/_ctypes.c | 8 +++++++- 3 files changed, 28 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 a8d243a45de0f4..65ba008a8fd327 100644 --- a/Lib/test/test_ctypes/test_pointers.py +++ b/Lib/test/test_ctypes/test_pointers.py @@ -3,6 +3,7 @@ import gc import sys import unittest +import os from ctypes import (CDLL, CFUNCTYPE, Structure, POINTER, pointer, _Pointer, byref, sizeof, @@ -472,6 +473,23 @@ class C(Structure): ptr.set_type(c_int) self.assertIs(ptr._type_, c_int) +class TestPointerStringProto(unittest.TestCase): + def test_pointer_string_proto_argtypes_error(self): + + BadType = ctypes.POINTER("BugTrigger") + + if os.name == "nt": + libc = ctypes.WinDLL("kernel32.dll") + func = libc.GetCurrentProcessId + else: + libc = ctypes.CDLL(None) + func = libc.getpid + + func.argtypes = (BadType,) + + with self.assertRaises(ctypes.ArgumentError): + func(ctypes.byref(ctypes.c_int(0))) + if __name__ == '__main__': unittest.main() 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 00000000000000..7093b753141fb8 --- /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 563e95a762599b..f8af76ae915ed2 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 target type is unresolved" + ); + return NULL; + } switch (PyObject_IsInstance(value, typeinfo->proto)) { case 1: Py_INCREF(value); /* _byref steals a refcount */ From bda79212cb60cc5f4cd44309df05aa8d2f7bed2c Mon Sep 17 00:00:00 2001 From: VanshAgarwal24036 Date: Wed, 21 Jan 2026 20:17:37 +0530 Subject: [PATCH 2/7] Test corrected --- Lib/test/test_ctypes/test_pointers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_ctypes/test_pointers.py b/Lib/test/test_ctypes/test_pointers.py index 65ba008a8fd327..7cd99a19dbb770 100644 --- a/Lib/test/test_ctypes/test_pointers.py +++ b/Lib/test/test_ctypes/test_pointers.py @@ -475,8 +475,8 @@ class C(Structure): class TestPointerStringProto(unittest.TestCase): def test_pointer_string_proto_argtypes_error(self): - - BadType = ctypes.POINTER("BugTrigger") + with self.assertWarns(DeprecationWarning): + BadType = ctypes.POINTER("BugTrigger") if os.name == "nt": libc = ctypes.WinDLL("kernel32.dll") From 16859582c742ec58b000e6a1bce5325b75612b6d Mon Sep 17 00:00:00 2001 From: VanshAgarwal24036 <148854295+VanshAgarwal24036@users.noreply.github.com> Date: Fri, 23 Jan 2026 23:14:59 +0530 Subject: [PATCH 3/7] Update Modules/_ctypes/_ctypes.c Co-authored-by: Victor Stinner --- Modules/_ctypes/_ctypes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index f8af76ae915ed2..3ce9e1c2335992 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1422,7 +1422,7 @@ PyCPointerType_from_param_impl(PyObject *type, PyTypeObject *cls, if(typeinfo->proto == NULL){ PyErr_SetString( PyExc_TypeError, - "cannot convert argument: POINTER target type is unresolved" + "cannot convert argument: POINTER _type_ type is not set" ); return NULL; } From 5587067ab4944f972700c3bd72e48f9a0f99e42b Mon Sep 17 00:00:00 2001 From: VanshAgarwal24036 <148854295+VanshAgarwal24036@users.noreply.github.com> Date: Fri, 23 Jan 2026 23:15:14 +0530 Subject: [PATCH 4/7] Update Modules/_ctypes/_ctypes.c Co-authored-by: Victor Stinner --- Modules/_ctypes/_ctypes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 3ce9e1c2335992..6d9193af657e2a 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1419,7 +1419,7 @@ PyCPointerType_from_param_impl(PyObject *type, PyTypeObject *cls, /* If we expect POINTER(), but receive a instance, accept it by calling byref(). */ - if(typeinfo->proto == NULL){ + if (typeinfo->proto == NULL) { PyErr_SetString( PyExc_TypeError, "cannot convert argument: POINTER _type_ type is not set" From e948a1a14b1ae0e3fcbe4782e094bf00ad246812 Mon Sep 17 00:00:00 2001 From: VanshAgarwal24036 Date: Fri, 23 Jan 2026 23:27:18 +0530 Subject: [PATCH 5/7] Update test file --- Lib/test/test_ctypes/test_pointers.py | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_ctypes/test_pointers.py b/Lib/test/test_ctypes/test_pointers.py index 7cd99a19dbb770..4e48ea82372d80 100644 --- a/Lib/test/test_ctypes/test_pointers.py +++ b/Lib/test/test_ctypes/test_pointers.py @@ -404,6 +404,16 @@ class Cls(Structure): 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(None) class PointerTypeCacheTestCase(unittest.TestCase): # dummy tests to check warnings and base behavior @@ -473,23 +483,6 @@ class C(Structure): ptr.set_type(c_int) self.assertIs(ptr._type_, c_int) -class TestPointerStringProto(unittest.TestCase): - def test_pointer_string_proto_argtypes_error(self): - with self.assertWarns(DeprecationWarning): - BadType = ctypes.POINTER("BugTrigger") - - if os.name == "nt": - libc = ctypes.WinDLL("kernel32.dll") - func = libc.GetCurrentProcessId - else: - libc = ctypes.CDLL(None) - func = libc.getpid - - func.argtypes = (BadType,) - - with self.assertRaises(ctypes.ArgumentError): - func(ctypes.byref(ctypes.c_int(0))) - if __name__ == '__main__': unittest.main() From 8a05d9ed6dc00972921fcdad53929fe9b172cc89 Mon Sep 17 00:00:00 2001 From: VanshAgarwal24036 Date: Fri, 23 Jan 2026 23:32:15 +0530 Subject: [PATCH 6/7] Update test file --- Lib/test/test_ctypes/test_pointers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/test/test_ctypes/test_pointers.py b/Lib/test/test_ctypes/test_pointers.py index 4e48ea82372d80..cdd67f637568c1 100644 --- a/Lib/test/test_ctypes/test_pointers.py +++ b/Lib/test/test_ctypes/test_pointers.py @@ -3,7 +3,6 @@ import gc import sys import unittest -import os from ctypes import (CDLL, CFUNCTYPE, Structure, POINTER, pointer, _Pointer, byref, sizeof, From 138e52d880f4ff7738fd7a9d6f7ad8e550c7b5bc Mon Sep 17 00:00:00 2001 From: VanshAgarwal24036 Date: Fri, 23 Jan 2026 23:50:04 +0530 Subject: [PATCH 7/7] Fx error fail --- Lib/test/test_ctypes/test_pointers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_ctypes/test_pointers.py b/Lib/test/test_ctypes/test_pointers.py index cdd67f637568c1..771cc8fbe0ec93 100644 --- a/Lib/test/test_ctypes/test_pointers.py +++ b/Lib/test/test_ctypes/test_pointers.py @@ -412,7 +412,7 @@ class BadType(ctypes._Pointer): func.argtypes = (BadType,) with self.assertRaises(ctypes.ArgumentError): - func(None) + func(object()) class PointerTypeCacheTestCase(unittest.TestCase): # dummy tests to check warnings and base behavior