dearblue · GitHub

VM inrush could invalidate addresses stored in dbg->regs by stack_extend().


To confirm the problem, apply the following patch to the current master and try rake test.

diff --git a/src/vm.c b/src/vm.c
index 1e7623478..2261acdf3 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -204,6 +204,16 @@ stack_extend(mrb_state *mrb, mrb_int room)
   if (!mrb->c->ci->stack || mrb->c->ci->stack + room >= mrb->c->stend) {
     stack_extend_alloc(mrb, room);
   }
+  else {
+    ptrdiff_t stsize = mrb->c->stend - mrb->c->stbase;
+    mrb_value *newstack = (mrb_value*)mrb_malloc(mrb, stsize * sizeof(mrb_value));
+    memcpy(newstack, mrb->c->stbase, stsize * sizeof(mrb_value));
+    memset(mrb->c->stbase, -1, stsize * sizeof(mrb_value));
+    mrb_free(mrb, mrb->c->stbase);
+    envadjust(mrb, mrb->c->stbase, newstack, stsize);
+    mrb->c->stbase = newstack;
+    mrb->c->stend = mrb->c->stbase + stsize;
+  }
 }
 MRB_API void

Here is an excerpt from one of the errors:

NoMethodError: mruby-bin-debugger(print) normal => undefined method `start_with?' for nil:NilClass (mrbgems: mruby-bin-debugger)
backtrace:
        /var/tmp/mruby/test/assert.rb:241:in `_assert_operator'
        /var/tmp/mruby/test/assert.rb:237:in `assert_operator'
        /var/tmp/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb:32:in `block (2 levels) in test'
        /var/tmp/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb:28:in `each'
        /var/tmp/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb:28:in `block in test'
        /var/tmp/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb:24:in `each'
        /var/tmp/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb:24:in `test'
        /var/tmp/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb:87:in `block in <top (required)>'
        /var/tmp/mruby/test/assert.rb:101:in `assert'
        /var/tmp/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb:70:in `<top (required)>'
        /var/tmp/mruby/test/bintest.rb:52:in `load'
        /var/tmp/mruby/test/bintest.rb:52:in `block (2 levels) in <main>'
        /var/tmp/mruby/test/bintest.rb:50:in `each'
        /var/tmp/mruby/test/bintest.rb:50:in `block in <main>'
        /var/tmp/mruby/test/bintest.rb:40:in `each'
        /var/tmp/mruby/test/bintest.rb:40:in `<main>'

Read the original on github.com ↗