diff options
author | Jo-Philipp Wich <jo@mein.io> | 2020-12-07 15:26:41 +0100 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2020-12-07 15:26:41 +0100 |
commit | bd4869f54fecb0f08865fd587cc62e300599e5af (patch) | |
tree | 188c656d8791ace87af4c0ff5f2d72d011b288e4 | |
parent | 30d3682b7a35496110044bfe2c02a48eedf52a9f (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.c | 10 |
1 files changed, 7 insertions, 3 deletions
@@ -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: |