Skip to content

Commit 19b727b

Browse files
committed
gh-127870: Fix ctypes _as_parameter_ handling
Detect recursive calls in ctypes _as_parameter_ handling: add Py_EnterRecursiveCall() and Py_LeaveRecursiveCall() calls.
1 parent 487fdbe commit 19b727b

File tree

3 files changed

+34
-3
lines changed

3 files changed

+34
-3
lines changed

Lib/test/test_ctypes/test_as_parameter.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
c_short, c_int, c_long, c_longlong,
66
c_byte, c_wchar, c_float, c_double,
77
ArgumentError)
8+
import ctypes
89
from test.support import import_helper
910
_ctypes_test = import_helper.import_module("_ctypes_test")
1011

@@ -198,8 +199,16 @@ class A:
198199

199200
a = A()
200201
a._as_parameter_ = a
201-
with self.assertRaises(RecursionError):
202-
c_int.from_param(a)
202+
for c_type in (
203+
ctypes.c_wchar_p,
204+
ctypes.c_char_p,
205+
ctypes.c_void_p,
206+
ctypes.c_int, # PyCSimpleType
207+
POINT, # CDataType
208+
):
209+
with self.subTest(c_type=c_type):
210+
with self.assertRaises(RecursionError):
211+
c_type.from_param(a)
203212

204213

205214
class AsParamWrapper:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Detect recursive calls in ctypes ``_as_parameter_`` handling.
2+
Patch by Victor Stinner.

Modules/_ctypes/_ctypes.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1052,8 +1052,13 @@ CDataType_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value)
10521052
return NULL;
10531053
}
10541054
if (as_parameter) {
1055+
if (_Py_EnterRecursiveCall(" while processing _as_parameter_")) {
1056+
Py_DECREF(as_parameter);
1057+
return NULL;
1058+
}
10551059
value = CDataType_from_param_impl(type, cls, as_parameter);
10561060
Py_DECREF(as_parameter);
1061+
_Py_LeaveRecursiveCall();
10571062
return value;
10581063
}
10591064
PyErr_Format(PyExc_TypeError,
@@ -1843,8 +1848,13 @@ c_wchar_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value)
18431848
return NULL;
18441849
}
18451850
if (as_parameter) {
1851+
if (_Py_EnterRecursiveCall(" while processing _as_parameter_")) {
1852+
Py_DECREF(as_parameter);
1853+
return NULL;
1854+
}
18461855
value = c_wchar_p_from_param_impl(type, cls, as_parameter);
18471856
Py_DECREF(as_parameter);
1857+
_Py_LeaveRecursiveCall();
18481858
return value;
18491859
}
18501860
PyErr_Format(PyExc_TypeError,
@@ -1927,8 +1937,13 @@ c_char_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value)
19271937
return NULL;
19281938
}
19291939
if (as_parameter) {
1940+
if (_Py_EnterRecursiveCall(" while processing _as_parameter_")) {
1941+
Py_DECREF(as_parameter);
1942+
return NULL;
1943+
}
19301944
value = c_char_p_from_param_impl(type, cls, as_parameter);
19311945
Py_DECREF(as_parameter);
1946+
_Py_LeaveRecursiveCall();
19321947
return value;
19331948
}
19341949
PyErr_Format(PyExc_TypeError,
@@ -2079,8 +2094,13 @@ c_void_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value)
20792094
return NULL;
20802095
}
20812096
if (as_parameter) {
2097+
if (_Py_EnterRecursiveCall(" while processing _as_parameter_")) {
2098+
Py_DECREF(as_parameter);
2099+
return NULL;
2100+
}
20822101
value = c_void_p_from_param_impl(type, cls, as_parameter);
20832102
Py_DECREF(as_parameter);
2103+
_Py_LeaveRecursiveCall();
20842104
return value;
20852105
}
20862106
PyErr_Format(PyExc_TypeError,
@@ -2447,9 +2467,9 @@ PyCSimpleType_from_param_impl(PyObject *type, PyTypeObject *cls,
24472467
return NULL;
24482468
}
24492469
value = PyCSimpleType_from_param_impl(type, cls, as_parameter);
2450-
_Py_LeaveRecursiveCall();
24512470
Py_DECREF(as_parameter);
24522471
Py_XDECREF(exc);
2472+
_Py_LeaveRecursiveCall();
24532473
return value;
24542474
}
24552475
if (exc) {

0 commit comments

Comments
 (0)