bpo-13097: ctypes: limit callback to 1024 arguments (GH-19914)
ctypes now raises an ArgumentError when a callback is invoked with more than 1024 arguments. The ctypes module allocates arguments on the stack in ctypes_callproc() using alloca(), which is problematic when large numbers of arguments are passed. Instead of a stack overflow, this commit raises an ArgumentError if more than 1024 parameters are passed.
This commit is contained in:
parent
fe2978b3b9
commit
29a1384c04
|
@ -287,6 +287,21 @@ class SampleCallbacksTestCase(unittest.TestCase):
|
|||
self.assertEqual(s.second, check.second)
|
||||
self.assertEqual(s.third, check.third)
|
||||
|
||||
def test_callback_too_many_args(self):
|
||||
def func(*args):
|
||||
return len(args)
|
||||
|
||||
CTYPES_MAX_ARGCOUNT = 1024
|
||||
proto = CFUNCTYPE(c_int, *(c_int,) * CTYPES_MAX_ARGCOUNT)
|
||||
cb = proto(func)
|
||||
args1 = (1,) * CTYPES_MAX_ARGCOUNT
|
||||
self.assertEqual(cb(*args1), CTYPES_MAX_ARGCOUNT)
|
||||
|
||||
args2 = (1,) * (CTYPES_MAX_ARGCOUNT + 1)
|
||||
with self.assertRaises(ArgumentError):
|
||||
cb(*args2)
|
||||
|
||||
|
||||
################################################################
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
``ctypes`` now raises an ``ArgumentError`` when a callback is invoked with more than 1024 arguments.
|
|
@ -1072,6 +1072,14 @@ GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk)
|
|||
#define IS_PASS_BY_REF(x) (x > 8 || !POW2(x))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* bpo-13097: Max number of arguments _ctypes_callproc will accept.
|
||||
*
|
||||
* This limit is enforced for the `alloca()` call in `_ctypes_callproc`,
|
||||
* to avoid allocating a massive buffer on the stack.
|
||||
*/
|
||||
#define CTYPES_MAX_ARGCOUNT 1024
|
||||
|
||||
/*
|
||||
* Requirements, must be ensured by the caller:
|
||||
* - argtuple is tuple of arguments
|
||||
|
@ -1107,6 +1115,13 @@ PyObject *_ctypes_callproc(PPROC pProc,
|
|||
++argcount;
|
||||
#endif
|
||||
|
||||
if (argcount > CTYPES_MAX_ARGCOUNT)
|
||||
{
|
||||
PyErr_Format(PyExc_ArgError, "too many arguments (%zi), maximum is %i",
|
||||
argcount, CTYPES_MAX_ARGCOUNT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
args = (struct argument *)alloca(sizeof(struct argument) * argcount);
|
||||
if (!args) {
|
||||
PyErr_NoMemory();
|
||||
|
|
Loading…
Reference in New Issue