mruby/mruby — pull request #1608 by nanamiwang (2013-12-15 15:15:00+00:00)
Title: Fixed callinfo buffer overflow while calling ensure handlers

A crash occured while testing a ruby script that accessing undefined variable.
OS: Windows7 X64
Compiler: MinGW gcc v 4.7.1

Steps to repeat this issue:
echo p undefined_var >> 1.rb
mruby 1.rb

GDB output:
Program received signal SIGSEGV, Segmentation fault.
0x0042e132 in ecall (mrb=0x2e24d0, i=-1) at e:/nanami/mruby/mruby/src/vm.c:264
264 p = mrb->c->ensure[i];
(gdb) bt
#0 0x0042e132 in ecall (mrb=0x2e24d0, i=-1) at e:/nanami/mruby/mruby/src/vm.c:264
#1 0x0043185a in mrb_context_run (mrb=0x2e24d0, proc=0x2e3da8, self=..., stack_keep=0)
at e:/nanami/mruby/mruby/src/vm.c:1291
#2 0x0041d151 in load_exec (mrb=0x2e24d0, p=0x6b9eb8, c=0x6b9cf8) at src/parse.y:5397
#3 0x0041d1c7 in mrb_load_file_cxt (mrb=0x2e24d0, f=0x76a12960, c=0x6b9cf8) at src/parse.y:5406
#4 0x00401a6e in main (argc=2, argv=0x2e1798)
at e:/nanami/mruby/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c:218
(gdb) f 1
#1 0x0043185a in mrb_context_run (mrb=0x2e24d0, proc=0x2e3da8, self=..., stack_keep=0)
at e:/nanami/mruby/mruby/src/vm.c:1291
1291 ecall(mrb, --eidx);
(gdb) list
1286 if (ci[1].acc == CI_ACC_SKIP && prev_jmp) {
1287 mrb->jmp = prev_jmp;
1288 mrb_longjmp(mrb);
1289 }
1290 while (eidx > ci[-1].eidx) {
1291 ecall(mrb, --eidx);
1292 }
1293 if (ci == mrb->c->cibase) {
1294 if (ci->ridx == 0) {
1295 regs = mrb->c->stack = mrb->c->stbase;
(gdb) p/x ci[-1]
$1 = {mid = 0x0, proc = 0x0, stackidx = 0x0, nregs = 0x0, argc = 0x0, pc = 0x0, err = 0xabababab,
acc = 0xabababab, target_class = 0x0, ridx = 0x0, eidx = 0xc7de186f, env = 0x1801d5c2}
(gdb) p/x ci
$4 = 0x6abb90
(gdb) p/x mrb->c->ci
$2 = 0x6abb90
(gdb) p/x mrb->c->cibase
$3 = 0x6abb90

The root cause is that while raising "NoMethodError" exception, after cipop func call, mrb->c->ci reachs to mrb->c->cibase address, so ci[-1] will point to a invalid heap address.