summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2020-12-07 15:26:41 +0100
committerJo-Philipp Wich <jo@mein.io>2020-12-07 15:26:41 +0100
commitbd4869f54fecb0f08865fd587cc62e300599e5af (patch)
tree188c656d8791ace87af4c0ff5f2d72d011b288e4
parent30d3682b7a35496110044bfe2c02a48eedf52a9f (diff)
eval: fix use-after-free in uc_invoke() error path
Since we're putting the intermediate JSON return value, the associated tag info will get freed as well, resulting in use-after-free when raising a syntax error due to usage of continue or break outside of loop structures. Read the tag type and offset values before releasing the intermediate `rv` value. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r--eval.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/eval.c b/eval.c
index 2f7d968..778a5f1 100644
--- a/eval.c
+++ b/eval.c
@@ -1050,7 +1050,9 @@ uc_invoke(struct uc_state *state, uint32_t off, struct json_object *this,
struct uc_function *fn, *prev_fn;
size_t arridx, arglen;
struct uc_scope *sc;
+ uint32_t tag_off;
uc_c_fn *fptr;
+ int tag_type;
bool rest;
if (!tag)
@@ -1115,14 +1117,16 @@ uc_invoke(struct uc_state *state, uint32_t off, struct json_object *this,
rv = uc_execute_op_sequence(state, fn->entry);
tag = json_object_get_userdata(rv);
+ tag_off = tag ? tag->off : 0;
+ tag_type = tag ? tag->type : 0;
- switch (tag ? tag->type : 0) {
+ switch (tag_type) {
case T_BREAK:
case T_CONTINUE:
json_object_put(rv);
- rv = uc_new_exception(state, tag->off,
+ rv = uc_new_exception(state, OP_POS(tag_off),
"Syntax error: %s statement must be inside loop",
- uc_get_tokenname(tag->type));
+ uc_get_tokenname(tag_type));
break;
case T_RETURN: