summaryrefslogtreecommitdiff
path: root/cffi/recompiler.py
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 /cffi/recompiler.py
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 'cffi/recompiler.py')
-rw-r--r--cffi/recompiler.py30
1 files changed, 19 insertions, 11 deletions
diff --git a/cffi/recompiler.py b/cffi/recompiler.py
index c3a3845..d66ff7f 100644
--- a/cffi/recompiler.py
+++ b/cffi/recompiler.py
@@ -560,23 +560,24 @@ class Recompiler:
tovar, tp.get_c_name(''), errvalue))
self._prnt(' %s;' % errcode)
- def _extra_local_variables(self, tp, localvars):
+ def _extra_local_variables(self, tp, localvars, freelines):
if isinstance(tp, model.PointerType):
localvars.add('Py_ssize_t datasize')
+ localvars.add('struct _cffi_freeme_s *large_args_free = NULL')
+ freelines.add('if (large_args_free != NULL)'
+ ' _cffi_free_array_arguments(large_args_free);')
def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode):
self._prnt(' datasize = _cffi_prepare_pointer_call_argument(')
self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % (
self._gettypenum(tp), fromvar, tovar))
self._prnt(' if (datasize != 0) {')
- self._prnt(' if (datasize < 0)')
- self._prnt(' %s;' % errcode)
- self._prnt(' %s = (%s)alloca((size_t)datasize);' % (
+ self._prnt(' %s = ((size_t)datasize) <= 640 ? '
+ '(%s)alloca((size_t)datasize) : NULL;' % (
tovar, tp.get_c_name('')))
- self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,))
- self._prnt(' if (_cffi_convert_array_from_object('
- '(char *)%s, _cffi_type(%d), %s) < 0)' % (
- tovar, self._gettypenum(tp), fromvar))
+ self._prnt(' if (_cffi_convert_array_argument(_cffi_type(%d), %s, '
+ '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar))
+ self._prnt(' datasize, &large_args_free) < 0)')
self._prnt(' %s;' % errcode)
self._prnt(' }')
@@ -699,9 +700,10 @@ class Recompiler:
prnt(' %s;' % arg)
#
localvars = set()
+ freelines = set()
for type in tp.args:
- self._extra_local_variables(type, localvars)
- for decl in localvars:
+ self._extra_local_variables(type, localvars, freelines)
+ for decl in sorted(localvars):
prnt(' %s;' % (decl,))
#
if not isinstance(tp.result, model.VoidType):
@@ -709,6 +711,7 @@ class Recompiler:
context = 'result of %s' % name
result_decl = ' %s;' % tp.result.get_c_name(' result', context)
prnt(result_decl)
+ prnt(' PyObject *pyresult;')
else:
result_decl = None
result_code = ''
@@ -742,9 +745,14 @@ class Recompiler:
if numargs == 0:
prnt(' (void)noarg; /* unused */')
if result_code:
- prnt(' return %s;' %
+ prnt(' pyresult = %s;' %
self._convert_expr_from_c(tp.result, 'result', 'result type'))
+ for freeline in freelines:
+ prnt(' ' + freeline)
+ prnt(' return pyresult;')
else:
+ for freeline in freelines:
+ prnt(' ' + freeline)
prnt(' Py_INCREF(Py_None);')
prnt(' return Py_None;')
prnt('}')