diff options
author | Jo-Philipp Wich <jo@mein.io> | 2020-10-19 13:36:09 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2020-10-19 13:40:41 +0200 |
commit | 036ba87c5d18385c5da13c331658363ea0ba6afe (patch) | |
tree | ac89ce98fde5e88fac1833236513ac09a2b48c1a | |
parent | 898a28de86600b62ddd5f971b910eaadc222bbb7 (diff) |
eval: avoid ut_op deref after ut_execute_op() in ut_execute_local()
Since we're invoking ut_execute_op() to obtain the assignment value, the
operand pool might have been reallocated at a different memory address,
invalidating the label opcode pointer.
Obtain a reference to the underlying json label value and re-obtain
the assignment opcode pointer with each iteration to avoid dereferencing
stale pointers.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r-- | eval.c | 19 |
1 files changed, 10 insertions, 9 deletions
@@ -411,23 +411,24 @@ ut_execute_assign(struct ut_state *state, uint32_t off) static struct json_object * ut_execute_local(struct ut_state *state, uint32_t off) { - struct ut_op *as = ut_get_child(state, off, 0); - struct json_object *val, *rv = NULL; - struct ut_op *label; + struct ut_op *op = ut_get_op(state, off), *asop, *alop; + uint32_t as = op ? op->tree.operand[0] : 0; + struct json_object *label, *val, *rv = NULL; while (as) { - label = ut_get_op(state, as->tree.operand[0]); + asop = ut_get_op(state, as); + alop = asop ? ut_get_child(state, as, 0) : NULL; + as = asop ? asop->tree.next : 0; - if (label) { - val = as->tree.operand[1] ? ut_execute_op(state, as->tree.operand[1]) : NULL; + if (alop) { + label = alop->val; + val = asop->tree.operand[1] ? ut_execute_op(state, asop->tree.operand[1]) : NULL; if (ut_is_type(val, T_EXCEPTION)) return val; - rv = ut_setval(state->scope->scope, label->val, val); + rv = ut_setval(state->scope->scope, label, val); } - - as = ut_get_op(state, as->tree.next); } return rv; |