Skip to content

Commit e083505

Browse files
[3.14] gh-159739: Detect recursive untyped ctypes arguments (GH-160194) (#160351)
_as_parameter_ chains were recursion-checked for typed arguments but not for foreign calls without argtypes. A cyclic chain could exhaust the C stack and crash before the function was called. Apply the same recursion guard to untyped conversion. Backport to 3.15 and 3.14. (cherry picked from commit 3e19e04) Co-authored-by: Jelle Zijlstra <jelle@openai.com>
1 parent a99e929 commit e083505

3 files changed

Lines changed: 12 additions & 2 deletions

File tree

‎Lib/test/test_ctypes/test_as_parameter.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ class A:
213213
with self.assertRaises(RecursionError):
214214
c_type.from_param(a)
215215

216+
function = CDLL(_ctypes_test.__file__)._testfunc_p_p
217+
with self.assertRaisesRegex(ArgumentError, 'RecursionError'):
218+
function(a)
219+
216220

217221
class AsParamWrapper:
218222
def __init__(self, param):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Detect recursive ``_as_parameter_`` chains for :mod:`ctypes` calls without argument types.

‎Modules/_ctypes/callproc.c‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ module _ctypes
9999
#define DONT_USE_SEH
100100
#endif
101101

102+
#include "pycore_ceval.h" // _Py_EnterRecursiveCall()
102103
#include "pycore_runtime.h" // _PyRuntime
103104
#include "pycore_global_objects.h"// _Py_ID()
104105
#include "pycore_traceback.h" // _PyTraceback_Add()
@@ -751,8 +752,12 @@ static int ConvParam(ctypes_state *st,
751752
attribute)
752753
*/
753754
if (arg) {
754-
int result;
755-
result = ConvParam(st, arg, index, pa);
755+
if (_Py_EnterRecursiveCall(" while processing _as_parameter_")) {
756+
Py_DECREF(arg);
757+
return -1;
758+
}
759+
int result = ConvParam(st, arg, index, pa);
760+
_Py_LeaveRecursiveCall();
756761
Py_DECREF(arg);
757762
return result;
758763
}

0 commit comments

Comments
 (0)