diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-01-12 23:08:58 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-01-12 23:08:58 +0900 |
| commit | a3571240e5fdbdac9210be27e2445e3f82239f44 (patch) | |
| tree | a32da262487f55eacf2ae1b4ef78558e8e96398f | |
| parent | 38acb9ec36bdd56123e6680885499fbf7f729f21 (diff) | |
| download | mruby-a3571240e5fdbdac9210be27e2445e3f82239f44.tar.gz mruby-a3571240e5fdbdac9210be27e2445e3f82239f44.zip | |
Add proper stack size calculation; fix #3398
This issue was reported by https://hackerone.com/ssarong
| -rw-r--r-- | src/vm.c | 23 |
1 files changed, 19 insertions, 4 deletions
@@ -373,7 +373,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc mrb_method_missing(mrb, mid, self, args); } undef = mid; - n++; argc++; + argc++; } ci = cipush(mrb); ci->mid = mid; @@ -389,8 +389,18 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc ci->nregs = argc + 2; stack_extend(mrb, ci->nregs, 0); } + else if (argc >= CALL_MAXARGS) { + mrb_value args = mrb_ary_new_from_values(mrb, argc, argv); + stack_extend(mrb, ci->nregs, 0); + mrb->c->stack[1] = args; + if (undef) { + mrb_ary_unshift(mrb, mrb->c->stack[1], mrb_symbol_value(undef)); + } + ci->argc = -1; + argc = 1; + } else { - ci->nregs = p->body.irep->nregs + n; + ci->nregs = p->body.irep->nregs + argc; stack_extend(mrb, ci->nregs, argc+2); } if (voff >= 0) { @@ -403,7 +413,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc stack_copy(mrb->c->stack+2, argv, argc-1); } } - else if (argc > 0) { + else if (ci->argc > 0) { stack_copy(mrb->c->stack+1, argv, argc); } mrb->c->stack[argc+1] = blk; @@ -2478,7 +2488,12 @@ RETRY_TRY_BLOCK: MRB_API mrb_value mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) { - return mrb_vm_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */ + if (mrb->c->ci->argc < 0) { + return mrb_vm_run(mrb, proc, self, 3); /* receiver, args and block) */ + } + else { + return mrb_vm_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */ + } } MRB_API mrb_value |
