diff --git a/Lib/test/test_ctypes/test_as_parameter.py b/Lib/test/test_ctypes/test_as_parameter.py index 27a5d3ac06430b2..cb25f0b0e2548e2 100644 --- a/Lib/test/test_ctypes/test_as_parameter.py +++ b/Lib/test/test_ctypes/test_as_parameter.py @@ -199,8 +199,16 @@ class A: a = A() a._as_parameter_ = a - with self.assertRaises(RecursionError): - c_int.from_param(a) + for c_type in ( + ctypes.c_wchar_p, + ctypes.c_char_p, + ctypes.c_void_p, + ctypes.c_int, # PyCSimpleType + POINT, # CDataType + ): + with self.subTest(c_type=c_type): + with self.assertRaises(RecursionError): + c_type.from_param(a) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/Misc/NEWS.d/next/Library/2024-12-12-16-59-42.gh-issue-127870._NFG-3.rst b/Misc/NEWS.d/next/Library/2024-12-12-16-59-42.gh-issue-127870._NFG-3.rst new file mode 100644 index 000000000000000..99b2df000320829 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-12-12-16-59-42.gh-issue-127870._NFG-3.rst @@ -0,0 +1,2 @@ +Detect recursive calls in ctypes ``_as_parameter_`` handling. +Patch by Victor Stinner. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index b6d45e926476843..9bcf79fddfffb7d 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -847,8 +847,13 @@ CDataType_from_param(PyObject *type, PyObject *value) return NULL; } if (as_parameter) { + if (_Py_EnterRecursiveCall(" while processing _as_parameter_")) { + Py_DECREF(as_parameter); + return NULL; + } value = CDataType_from_param(type, as_parameter); Py_DECREF(as_parameter); + _Py_LeaveRecursiveCall(); return value; } PyErr_Format(PyExc_TypeError, @@ -1716,8 +1721,13 @@ c_wchar_p_from_param(PyObject *type, PyObject *value) return NULL; } if (as_parameter) { + if (_Py_EnterRecursiveCall(" while processing _as_parameter_")) { + Py_DECREF(as_parameter); + return NULL; + } value = c_wchar_p_from_param(type, as_parameter); Py_DECREF(as_parameter); + _Py_LeaveRecursiveCall(); return value; } /* XXX better message */ @@ -1780,8 +1790,13 @@ c_char_p_from_param(PyObject *type, PyObject *value) return NULL; } if (as_parameter) { + if (_Py_EnterRecursiveCall(" while processing _as_parameter_")) { + Py_DECREF(as_parameter); + return NULL; + } value = c_char_p_from_param(type, as_parameter); Py_DECREF(as_parameter); + _Py_LeaveRecursiveCall(); return value; } /* XXX better message */ @@ -1915,8 +1930,13 @@ c_void_p_from_param(PyObject *type, PyObject *value) return NULL; } if (as_parameter) { + if (_Py_EnterRecursiveCall(" while processing _as_parameter_")) { + Py_DECREF(as_parameter); + return NULL; + } value = c_void_p_from_param(type, as_parameter); Py_DECREF(as_parameter); + _Py_LeaveRecursiveCall(); return value; } /* XXX better message */ @@ -2275,9 +2295,9 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value) return NULL; } value = PyCSimpleType_from_param(type, as_parameter); - _Py_LeaveRecursiveCall(); Py_DECREF(as_parameter); Py_XDECREF(exc); + _Py_LeaveRecursiveCall(); return value; } if (exc) {