https://github.com/python/cpython/commit/e083505a1b91f53f81641470ba32cf25568542ec
commit: e083505a1b91f53f81641470ba32cf25568542ec
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: JelleZijlstra <[email protected]>
date: 2026-10-22T22:25:57Z
summary:

[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 3e19e0408d9791c235c6c85818de1b9b2eb93dfa)

Co-authored-by: Jelle Zijlstra <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-10-21-21-26-10.gh-issue-159739.b4ueJ7.rst
M Lib/test/test_ctypes/test_as_parameter.py
M Modules/_ctypes/callproc.c

diff --git a/Lib/test/test_ctypes/test_as_parameter.py 
b/Lib/test/test_ctypes/test_as_parameter.py
index abbfb6efdcea55..d081f7ccb0eb07 100644
--- a/Lib/test/test_ctypes/test_as_parameter.py
+++ b/Lib/test/test_ctypes/test_as_parameter.py
@@ -213,6 +213,10 @@ class A:
                 with self.assertRaises(RecursionError):
                     c_type.from_param(a)
 
+        function = CDLL(_ctypes_test.__file__)._testfunc_p_p
+        with self.assertRaisesRegex(ArgumentError, 'RecursionError'):
+            function(a)
+
 
 class AsParamWrapper:
     def __init__(self, param):
diff --git 
a/Misc/NEWS.d/next/Library/2026-10-21-21-26-10.gh-issue-159739.b4ueJ7.rst 
b/Misc/NEWS.d/next/Library/2026-10-21-21-26-10.gh-issue-159739.b4ueJ7.rst
new file mode 100644
index 00000000000000..6230801bbc0927
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-10-21-21-26-10.gh-issue-159739.b4ueJ7.rst
@@ -0,0 +1 @@
+Detect recursive ``_as_parameter_`` chains for :mod:`ctypes` calls without 
argument types.
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
index 27b99211ce6217..3956f504740167 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -99,6 +99,7 @@ module _ctypes
 #define DONT_USE_SEH
 #endif
 
+#include "pycore_ceval.h"         // _Py_EnterRecursiveCall()
 #include "pycore_runtime.h"       // _PyRuntime
 #include "pycore_global_objects.h"// _Py_ID()
 #include "pycore_traceback.h"     // _PyTraceback_Add()
@@ -751,8 +752,12 @@ static int ConvParam(ctypes_state *st,
            attribute)
         */
         if (arg) {
-            int result;
-            result = ConvParam(st, arg, index, pa);
+            if (_Py_EnterRecursiveCall(" while processing _as_parameter_")) {
+                Py_DECREF(arg);
+                return -1;
+            }
+            int result = ConvParam(st, arg, index, pa);
+            _Py_LeaveRecursiveCall();
             Py_DECREF(arg);
             return result;
         }

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to