summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2024-12-13 12:53:47 (GMT)
committerGitHub <noreply@github.com>2024-12-13 12:53:47 (GMT)
commit6ff38fc4e2af8e795dc791be6ea596d2146d4119 (patch)
treee4a1d93431b8db928fc86d87b248164d39286b47
parente62e1ca4553dbcf9d7f89be24bebcbd9213f9ae5 (diff)
downloadcpython-6ff38fc4e2af8e795dc791be6ea596d2146d4119.zip
cpython-6ff38fc4e2af8e795dc791be6ea596d2146d4119.tar.gz
cpython-6ff38fc4e2af8e795dc791be6ea596d2146d4119.tar.bz2
gh-127870: Detect recursive calls in ctypes _as_parameter_ handling (#127872)
-rw-r--r--Lib/test/test_ctypes/test_as_parameter.py12
-rw-r--r--Misc/NEWS.d/next/Library/2024-12-12-16-59-42.gh-issue-127870._NFG-3.rst2
-rw-r--r--Modules/_ctypes/_ctypes.c22
3 files changed, 33 insertions, 3 deletions
diff --git a/Lib/test/test_ctypes/test_as_parameter.py b/Lib/test/test_ctypes/test_as_parameter.py
index cc62b1a..c5e1840 100644
--- a/Lib/test/test_ctypes/test_as_parameter.py
+++ b/Lib/test/test_ctypes/test_as_parameter.py
@@ -198,8 +198,16 @@ class BasicWrapTestCase(unittest.TestCase):
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)
class AsParamWrapper:
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 0000000..99b2df0
--- /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 34529bc..bb46998 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -1052,8 +1052,13 @@ CDataType_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value)
return NULL;
}
if (as_parameter) {
+ if (_Py_EnterRecursiveCall(" while processing _as_parameter_")) {
+ Py_DECREF(as_parameter);
+ return NULL;
+ }
value = CDataType_from_param_impl(type, cls, as_parameter);
Py_DECREF(as_parameter);
+ _Py_LeaveRecursiveCall();
return value;
}
PyErr_Format(PyExc_TypeError,
@@ -1843,8 +1848,13 @@ c_wchar_p_from_param_impl(PyObject *type, PyTypeObject *cls, 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_impl(type, cls, as_parameter);
Py_DECREF(as_parameter);
+ _Py_LeaveRecursiveCall();
return value;
}
PyErr_Format(PyExc_TypeError,
@@ -1927,8 +1937,13 @@ c_char_p_from_param_impl(PyObject *type, PyTypeObject *cls, 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_impl(type, cls, as_parameter);
Py_DECREF(as_parameter);
+ _Py_LeaveRecursiveCall();
return value;
}
PyErr_Format(PyExc_TypeError,
@@ -2079,8 +2094,13 @@ c_void_p_from_param_impl(PyObject *type, PyTypeObject *cls, 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_impl(type, cls, as_parameter);
Py_DECREF(as_parameter);
+ _Py_LeaveRecursiveCall();
return value;
}
PyErr_Format(PyExc_TypeError,
@@ -2447,9 +2467,9 @@ PyCSimpleType_from_param_impl(PyObject *type, PyTypeObject *cls,
return NULL;
}
value = PyCSimpleType_from_param_impl(type, cls, as_parameter);
- _Py_LeaveRecursiveCall();
Py_DECREF(as_parameter);
Py_XDECREF(exc);
+ _Py_LeaveRecursiveCall();
return value;
}
if (exc) {