summaryrefslogtreecommitdiffhomepage
path: root/eval.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2020-10-18 17:46:42 +0200
committerJo-Philipp Wich <jo@mein.io>2020-10-18 18:09:11 +0200
commitd815d0e0ee00de41e792246ba1baddf1d68b0f59 (patch)
tree20d31fdfc9f4a531cc32c27fec7c5f701840899e /eval.c
parent279d0b5d27f406bb60cb7e9ea2222a3c83eb7980 (diff)
eval: fix segmentation faults with self-invoking functions
Store the invocation scope and function context in the call stack frame and not in the function object to properly deal with recursive invocations. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c21
1 files changed, 9 insertions, 12 deletions
diff --git a/eval.c b/eval.c
index 1eff9fc..2230bb9 100644
--- a/eval.c
+++ b/eval.c
@@ -985,6 +985,7 @@ ut_invoke(struct ut_state *state, uint32_t off, struct json_object *this,
callstack.source = state->source;
callstack.funcname = state->function ? state->function->name : NULL;
callstack.off = op ? op->off : 0;
+ callstack.ctx = json_object_get(this ? this : state->ctx);
state->callstack = &callstack;
/* is native function */
@@ -996,19 +997,19 @@ ut_invoke(struct ut_state *state, uint32_t off, struct json_object *this,
/* is utpl function */
else {
fn = tag->tag.data;
- fn->scope = ut_new_scope(state, fn->parent_scope);
- fn->scope->ctx = json_object_get(this ? this : state->ctx);
+
+ callstack.scope = ut_new_scope(state, fn->parent_scope);
sc = state->scope;
- state->scope = ut_acquire_scope(fn->scope);
+ state->scope = ut_acquire_scope(callstack.scope);
prev_fn = state->function;
state->function = fn;
if (fn->args)
for (arridx = 0; arridx < json_object_array_length(fn->args); arridx++)
- ut_setval(fn->scope->scope, json_object_array_get_idx(fn->args, arridx),
+ ut_setval(callstack.scope->scope, json_object_array_get_idx(fn->args, arridx),
argvals ? json_object_array_get_idx(argvals, arridx) : NULL);
rv = ut_execute_op_sequence(state, fn->entry);
@@ -1033,17 +1034,13 @@ ut_invoke(struct ut_state *state, uint32_t off, struct json_object *this,
ut_release_scope(state->scope);
state->scope = sc;
- /* ... and remove the "this" context... */
- json_object_put(fn->scope->ctx);
- fn->scope->ctx = NULL;
-
- /* ... and reset the function scope... */
- ut_release_scope(fn->scope);
- fn->scope = NULL;
+ /* ... and release it */
+ ut_release_scope(callstack.scope);
state->function = prev_fn;
}
+ json_object_put(callstack.ctx);
state->callstack = callstack.next;
return rv;
@@ -1369,7 +1366,7 @@ ut_execute_function(struct ut_state *state, uint32_t off)
static struct json_object *
ut_execute_this(struct ut_state *state, uint32_t off)
{
- return json_object_get(state->scope->ctx);
+ return json_object_get(state->callstack->ctx);
}
static struct json_object *