summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/ctypes/test/test_callbacks.py15
-rw-r--r--Misc/NEWS.d/next/Library/2020-05-06-02-01-25.bpo-13097.Wh5xSK.rst1
-rw-r--r--Modules/_ctypes/callproc.c15
3 files changed, 31 insertions, 0 deletions
diff --git a/Lib/ctypes/test/test_callbacks.py b/Lib/ctypes/test/test_callbacks.py
index f622093..937a06d 100644
--- a/Lib/ctypes/test/test_callbacks.py
+++ b/Lib/ctypes/test/test_callbacks.py
@@ -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__':
diff --git a/Misc/NEWS.d/next/Library/2020-05-06-02-01-25.bpo-13097.Wh5xSK.rst b/Misc/NEWS.d/next/Library/2020-05-06-02-01-25.bpo-13097.Wh5xSK.rst
new file mode 100644
index 0000000..a7f5f58
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-05-06-02-01-25.bpo-13097.Wh5xSK.rst
@@ -0,0 +1 @@
+``ctypes`` now raises an ``ArgumentError`` when a callback is invoked with more than 1024 arguments. \ No newline at end of file
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
index 4027bdb..e0a110d 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -1074,6 +1074,14 @@ GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk)
#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
* - argtypes is either NULL, or a tuple of the same size as argtuple
@@ -1108,6 +1116,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();