summaryrefslogtreecommitdiffhomepage
path: root/src/kernel.c
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2017-04-06 10:07:53 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2017-04-06 10:07:53 +0900
commite5b61d34f65cabfbe88f3f1709a1f9cff86585de (patch)
tree58b863691c40319cbd6f671db291731cd61ef30f /src/kernel.c
parent5e79bc9377f9be27b04c07a533525ad75086a5af (diff)
downloadmruby-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.c52
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 */