diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-04-06 10:07:53 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-04-06 10:07:53 +0900 |
| commit | e5b61d34f65cabfbe88f3f1709a1f9cff86585de (patch) | |
| tree | 58b863691c40319cbd6f671db291731cd61ef30f /src/kernel.c | |
| parent | 5e79bc9377f9be27b04c07a533525ad75086a5af (diff) | |
| download | mruby-e5b61d34f65cabfbe88f3f1709a1f9cff86585de.tar.gz mruby-e5b61d34f65cabfbe88f3f1709a1f9cff86585de.zip | |
Fixed possible SEGV in `Kernel#block_given?`; ref #3593
Diffstat (limited to 'src/kernel.c')
| -rw-r--r-- | src/kernel.c | 52 |
1 files changed, 23 insertions, 29 deletions
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 */ |
