summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2020-09-01 18:06:49 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2020-10-12 18:20:10 +0900
commit4cf1da9542d6554ec23de6324c5f2d5eebe138c9 (patch)
treeecaa1f4ecd92243e2a6939a10ee02c25c494429e
parentb01207ea94095bc855b8e6fef0dc65d7eae0d8ad (diff)
downloadmruby-4cf1da9542d6554ec23de6324c5f2d5eebe138c9.tar.gz
mruby-4cf1da9542d6554ec23de6324c5f2d5eebe138c9.zip
Separate jump destination check in `OP_R_RETURN`.
In the past code, the current `callinfo (ci)` was modified, thus it was possible to pop `ci` beyond the `cibase`, that could cause out of memory bound access for the code like the following: ```ruby def m2 lambda { Proc.new { return :return # return from the method } }.call.call :never_reached end p m2 ```
-rw-r--r--src/vm.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/src/vm.c b/src/vm.c
index bff13af10..b282af260 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -2029,11 +2029,20 @@ RETRY_TRY_BLOCK:
goto L_RAISE;
}
}
+ /* check jump destination */
while (cibase <= ci && ci->proc != dst) {
- if (ci->acc < 0) {
+ if (ci->acc < 0) { /* jump cross C boudary */
localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
goto L_RAISE;
}
+ ci--;
+ }
+ if (ci <= cibase) { /* no jump destination */
+ localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
+ goto L_RAISE;
+ }
+ ci = mrb->c->ci;
+ while (cibase <= ci && ci->proc != dst) {
CHECKPOINT_RESTORE(RBREAK_TAG_RETURN_BLOCK) {
cibase = mrb->c->cibase;
dst = top_proc(mrb, proc);
@@ -2045,12 +2054,8 @@ RETRY_TRY_BLOCK:
pc = ci->pc;
ci = cipop(mrb);
}
- mrb->exc = NULL; /* clear break object */
proc = ci->proc;
- if (ci <= cibase) {
- localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
- goto L_RAISE;
- }
+ mrb->exc = NULL; /* clear break object */
break;
}
/* fallthrough */