summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Lechner <david@pybricks.com>2022-08-05 18:52:13 -0500
committerDavid Lechner <david@pybricks.com>2022-08-06 11:32:58 -0500
commit6baeded32236feb9ba57ce78477fd1ee80fb4697 (patch)
tree2b61e0bb8658ebf0ab53aaf8b3ef575a07bfc7f0
parent9dfabcd6d3d080aced888e8474e921f11dc979bb (diff)
py/runtime: Fix crash in star arg unpacking.
The reallocation trigger for unpacking star args with unknown length did not take into account the number of fixed args remaining. So it was possible that the unpacked iterators could take up exactly the memory allocated then nothing would be left for fixed args after the star args. This causes a segfault crash. This is fixed by taking into account the remaining number of fixed args in the check to decide whether to realloc yet or not. Signed-off-by: David Lechner <david@pybricks.com>
-rw-r--r--py/runtime.c2
-rw-r--r--tests/basics/fun_callstardblstar.py4
2 files changed, 5 insertions, 1 deletions
diff --git a/py/runtime.c b/py/runtime.c
index 2c3b3ddde..ea3553db7 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -814,7 +814,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
mp_obj_t iterable = mp_getiter(arg, &iter_buf);
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
- if (args2_len >= args2_alloc) {
+ if (args2_len + (n_args - i) >= args2_alloc) {
args2 = mp_nonlocal_realloc(args2, args2_alloc * sizeof(mp_obj_t),
args2_alloc * 2 * sizeof(mp_obj_t));
args2_alloc *= 2;
diff --git a/tests/basics/fun_callstardblstar.py b/tests/basics/fun_callstardblstar.py
index f395df333..c08e46f66 100644
--- a/tests/basics/fun_callstardblstar.py
+++ b/tests/basics/fun_callstardblstar.py
@@ -37,3 +37,7 @@ f2(*iter(range(4)), **{'a': 1})
# case where *args is not a tuple/list and takes up most of the memory allocated for **kwargs
f2(*iter(range(100)), **{str(i): i for i in range(100)})
+
+# regression test - iterable with unknown len() was exactly using preallocated
+# memory causing args 4 and 5 to overflow the allocated arg array
+print(1, *iter((1, 2, 3)), *iter((1, 2, 3)), 4, 5, sep=",")