dearblue · GitHub

For information.

There is a problem in the scenario where OP_STOP is issued with an exception object, or where a break object is entered into mrb->exc by unwind while processing OP_STOP.

However, since OP_STOP is never used when it is generated, I don't think there is a problem.
The patch is already written and will be sent as another PR if this PR is accepted or rejected.

diff --git a/src/vm.c b/src/vm.c
index 4e8283e18..9f80fce46 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -3078,18 +3078,22 @@ RETRY_TRY_BLOCK:
     CASE(OP_STOP, Z) {
       /*        stop VM */
+      mrb_value v;
+      v = mrb->exc ? mrb_obj_value(mrb->exc) : mrb_nil_value();
       CHECKPOINT_RESTORE(RBREAK_TAG_STOP) {
-        /* do nothing */
+        struct RBreak *brk = (struct RBreak*)mrb->exc;
+        v = mrb_break_value_get(brk);
       }
       CHECKPOINT_MAIN(RBREAK_TAG_STOP) {
-        UNWIND_ENSURE(mrb, mrb->c->ci, mrb->c->ci->pc, RBREAK_TAG_STOP, mrb->c->ci, mrb_nil_value());
+        UNWIND_ENSURE(mrb, mrb->c->ci, mrb->c->ci->pc, RBREAK_TAG_STOP, mrb->c->ci, v);
       }
       CHECKPOINT_END(RBREAK_TAG_STOP);
       mrb->jmp = prev_jmp;
-      if (mrb->exc) {
-        mrb_assert(mrb->exc->tt == MRB_TT_EXCEPTION);
-        return mrb_obj_value(mrb->exc);
+      if (!mrb_nil_p(v)) {
+        mrb->exc = mrb_obj_ptr(v);
+        return v;
       }
+      mrb->exc = NULL;
       return regs[irep->nlocals];
     }
   }

Read the original on github.com ↗