Commit 6c097c71 authored by dearblue's avatar dearblue

Fix `SIGSEGV` with mruby-method + mruby-catch

Previously, the following code would cause a `SIGSEGV`.

```ruby
mm = method(:throw)
define_method(:throw, ->(*args) { mm.call(*args) })
catch { |tag| throw tag }
```

I think the reason is in the `mrb_yield_with_class()` function:
- Even if a C function is called, `CI_ACC_SKIP` is used
- `cipop()` is not done if globally jumping from a C function
parent 9492e389
......@@ -780,8 +780,25 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value
mrb->c->ci->stack[argc+1] = mrb_nil_value();
if (MRB_PROC_CFUNC_P(p)) {
val = MRB_PROC_CFUNC(p)(mrb, self);
struct mrb_jmpbuf *prev_jmp = mrb->jmp;
struct mrb_jmpbuf c_jmp;
int ai = mrb_gc_arena_save(mrb);
mrb_bool exc = FALSE;
MRB_TRY(&c_jmp) {
mrb->jmp = &c_jmp;
ci->acc = CI_ACC_DIRECT;
val = MRB_PROC_CFUNC(p)(mrb, self);
}
MRB_CATCH(&c_jmp) {
exc = TRUE;
}
MRB_END_EXC(&c_jmp);
mrb->jmp = prev_jmp;
mrb_gc_arena_restore(mrb, ai);
cipop(mrb);
if (exc) MRB_THROW(mrb->jmp);
}
else {
val = mrb_run(mrb, p, self);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment