summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2017-05-29 10:33:43 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2017-05-29 10:33:43 +0900
commit02670ffa8d7e178164cc590c5ca01fe090a19ced (patch)
tree105ac4c2f46de500e9f0cba869e9783b3133a04b /src
parent9f634a6f8b78ac9099238407cf15d4abca9b808c (diff)
downloadmruby-02670ffa8d7e178164cc590c5ca01fe090a19ced.tar.gz
mruby-02670ffa8d7e178164cc590c5ca01fe090a19ced.zip
Protect the returning value in OP_RETURN; fix #3669
Even though the returning value is retrieved from the stack, it may be freed if GC is caused during stack rewinding (e.g. ensure calls).
Diffstat (limited to 'src')
-rw-r--r--src/vm.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/src/vm.c b/src/vm.c
index 5ec345bb0..2dc51201f 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -1812,6 +1812,7 @@ RETRY_TRY_BLOCK:
int acc, eidx = mrb->c->ci->eidx;
mrb_value v = regs[GETARG_A(i)];
+ mrb_gc_protect(mrb, v);
switch (GETARG_B(i)) {
case OP_R_RETURN:
/* Fall through to OP_R_NORMAL otherwise */
@@ -1888,6 +1889,7 @@ RETRY_TRY_BLOCK:
while (eidx > mrb->c->ci[-1].eidx) {
ecall(mrb, --eidx);
}
+ ARENA_RESTORE(mrb, ai);
mrb->c->vmexec = FALSE;
mrb->jmp = prev_jmp;
return v;
@@ -1913,6 +1915,7 @@ RETRY_TRY_BLOCK:
ecall(mrb, --eidx);
}
if (mrb->c->vmexec && !mrb->c->ci->target_class) {
+ ARENA_RESTORE(mrb, ai);
mrb->c->vmexec = FALSE;
mrb->jmp = prev_jmp;
return v;
@@ -1922,6 +1925,7 @@ RETRY_TRY_BLOCK:
mrb->c->stack = ci->stackent;
cipop(mrb);
if (acc == CI_ACC_SKIP || acc == CI_ACC_DIRECT) {
+ ARENA_RESTORE(mrb, ai);
mrb->jmp = prev_jmp;
return v;
}
@@ -1933,6 +1937,7 @@ RETRY_TRY_BLOCK:
syms = irep->syms;
regs[acc] = v;
+ ARENA_RESTORE(mrb, ai);
}
JUMP;
}