[3.12] gh-127870: Detect recursive calls in ctypes _as_parameter_ handling (#127872) (#127918)

gh-127870: Detect recursive calls in ctypes _as_parameter_ handling (#127872)

(cherry picked from commit 6ff38fc4e2)
This commit is contained in:
Victor Stinner 2024-12-13 14:21:30 +01:00 committed by GitHub
parent 6544f99463
commit 21c056ec27
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 34 additions and 5 deletions

View file

@ -1,3 +1,4 @@
import ctypes
import unittest import unittest
from ctypes import * from ctypes import *
from test.test_ctypes import need_symbol from test.test_ctypes import need_symbol
@ -192,15 +193,21 @@ class BasicWrapTestCase(unittest.TestCase):
(9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
def test_recursive_as_param(self): def test_recursive_as_param(self):
from ctypes import c_int
class A: class A:
pass pass
a = A() a = A()
a._as_parameter_ = a a._as_parameter_ = a
with self.assertRaises(RecursionError): for c_type in (
c_int.from_param(a) 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)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -0,0 +1,2 @@
Detect recursive calls in ctypes ``_as_parameter_`` handling.
Patch by Victor Stinner.

View file

@ -847,8 +847,13 @@ CDataType_from_param(PyObject *type, PyObject *value)
return NULL; return NULL;
} }
if (as_parameter) { if (as_parameter) {
if (_Py_EnterRecursiveCall(" while processing _as_parameter_")) {
Py_DECREF(as_parameter);
return NULL;
}
value = CDataType_from_param(type, as_parameter); value = CDataType_from_param(type, as_parameter);
Py_DECREF(as_parameter); Py_DECREF(as_parameter);
_Py_LeaveRecursiveCall();
return value; return value;
} }
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
@ -1716,8 +1721,13 @@ c_wchar_p_from_param(PyObject *type, PyObject *value)
return NULL; return NULL;
} }
if (as_parameter) { 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); value = c_wchar_p_from_param(type, as_parameter);
Py_DECREF(as_parameter); Py_DECREF(as_parameter);
_Py_LeaveRecursiveCall();
return value; return value;
} }
/* XXX better message */ /* XXX better message */
@ -1780,8 +1790,13 @@ c_char_p_from_param(PyObject *type, PyObject *value)
return NULL; return NULL;
} }
if (as_parameter) { 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); value = c_char_p_from_param(type, as_parameter);
Py_DECREF(as_parameter); Py_DECREF(as_parameter);
_Py_LeaveRecursiveCall();
return value; return value;
} }
/* XXX better message */ /* XXX better message */
@ -1915,8 +1930,13 @@ c_void_p_from_param(PyObject *type, PyObject *value)
return NULL; return NULL;
} }
if (as_parameter) { 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); value = c_void_p_from_param(type, as_parameter);
Py_DECREF(as_parameter); Py_DECREF(as_parameter);
_Py_LeaveRecursiveCall();
return value; return value;
} }
/* XXX better message */ /* XXX better message */
@ -2275,9 +2295,9 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value)
return NULL; return NULL;
} }
value = PyCSimpleType_from_param(type, as_parameter); value = PyCSimpleType_from_param(type, as_parameter);
_Py_LeaveRecursiveCall();
Py_DECREF(as_parameter); Py_DECREF(as_parameter);
Py_XDECREF(exc); Py_XDECREF(exc);
_Py_LeaveRecursiveCall();
return value; return value;
} }
if (exc) { if (exc) {