From e5b61d34f65cabfbe88f3f1709a1f9cff86585de Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 6 Apr 2017 10:07:53 +0900 Subject: Fixed possible SEGV in `Kernel#block_given?`; ref #3593 --- src/kernel.c | 52 +++++++++++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 29 deletions(-) (limited to 'src/kernel.c') diff --git a/src/kernel.c b/src/kernel.c index 5ac0a3774..ef5bc0839 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -136,44 +136,38 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self) { mrb_callinfo *ci = mrb->c->ci; mrb_value *bp; - mrb_bool given_p; bp = ci->stackent + 1; ci--; if (ci <= mrb->c->cibase) { - given_p = FALSE; + return mrb_false_value(); } - else { - /* block_given? called within block; check upper scope */ - if (ci->proc->env) { - struct REnv *e = ci->proc->env; - mrb_value *sp; + /* block_given? called within block; check upper scope */ + if (ci->proc->env) { + struct REnv *e = ci->proc->env; - while (e->c) { - e = (struct REnv*)e->c; - } - sp = e->stack; - if (sp) { - /* top-level does not have block slot (alway false) */ - if (sp == mrb->c->stbase) - return mrb_false_value(); - if (e->cioff < 0) { - /* use saved block arg position */ - bp = &e->stack[-e->cioff]; - } - else { - ci = mrb->c->cibase + e->cioff; - bp = ci[1].stackent + 1; - } - } + while (e->c) { + e = (struct REnv*)e->c; } - if (ci->argc > 0) { - bp += ci->argc; + /* top-level does not have block slot (always false) */ + if (e->stack == mrb->c->stbase) + return mrb_false_value(); + if (e->stack && e->cioff < 0) { + /* use saved block arg position */ + bp = &e->stack[-e->cioff]; + ci = 0; /* no callinfo available */ + } + else { + ci = mrb->c->cibase + e->cioff; + bp = ci[1].stackent + 1; } - given_p = !mrb_nil_p(*bp); } - - return mrb_bool_value(given_p); + if (ci && ci->argc > 0) { + bp += ci->argc; + } + if (mrb_nil_p(*bp)) + return mrb_false_value(); + return mrb_true_value(); } /* 15.3.1.3.7 */ -- cgit v1.2.3