summaryrefslogtreecommitdiff
path: root/c/_cffi_backend.c
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2020-01-19 10:23:34 +0100
committerArmin Rigo <arigo@tunes.org>2020-01-19 10:23:34 +0100
commit4840f2bf291dfa58af123768a66b1a49e3af31a4 (patch)
treea16e1b0cccad87e87267dd092cdd2f79a4380653 /c/_cffi_backend.c
parent7c871d4fe57e7f6c5d034b22326bc439aa6c6538 (diff)
downloadcffi-4840f2bf291dfa58af123768a66b1a49e3af31a4.tar.gz
Issue #440
Limit the amount of memory that is requested from alloca() for temporary conversion of arguments. Non-small requests are instead handled with PyObject_Malloc() and PyObject_Free().
Diffstat (limited to 'c/_cffi_backend.c')
-rw-r--r--c/_cffi_backend.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
index 212a019..6826780 100644
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -2991,6 +2991,10 @@ cdata_call(CDataObject *cd, PyObject *args, PyObject *kwds)
CTypeDescrObject *fresult;
char *resultdata;
char *errormsg;
+ struct freeme_s {
+ struct freeme_s *next;
+ union_alignment alignment;
+ } *freeme = NULL;
if (!(cd->c_type->ct_flags & CT_FUNCTIONPTR)) {
PyErr_Format(PyExc_TypeError, "cdata '%s' is not callable",
@@ -3111,7 +3115,21 @@ cdata_call(CDataObject *cd, PyObject *args, PyObject *kwds)
else if (datasize < 0)
goto error;
else {
- tmpbuf = alloca(datasize);
+ if (datasize <= 512) {
+ tmpbuf = alloca(datasize);
+ }
+ else {
+ struct freeme_s *fp = (struct freeme_s *)PyObject_Malloc(
+ offsetof(struct freeme_s, alignment) +
+ (size_t)datasize);
+ if (fp == NULL) {
+ PyErr_NoMemory();
+ goto error;
+ }
+ fp->next = freeme;
+ freeme = fp;
+ tmpbuf = (char *)&fp->alignment;
+ }
memset(tmpbuf, 0, datasize);
*(char **)data = tmpbuf;
if (convert_array_from_object(tmpbuf, argtype, obj) < 0)
@@ -3156,6 +3174,11 @@ cdata_call(CDataObject *cd, PyObject *args, PyObject *kwds)
/* fall-through */
error:
+ while (freeme != NULL) {
+ void *p = (void *)freeme;
+ freeme = freeme->next;
+ PyObject_Free(p);
+ }
if (buffer)
PyObject_Free(buffer);
if (fvarargs != NULL) {