mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
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
```
This commit is contained in:
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user