From ab27abe0834bc9da38d4a4d895514a66ea53fe84 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 4 Nov 2017 03:01:37 +0900 Subject: The `bidx` saved in `env` may be useless; fix #3841 When `block_given?` is called from a block given to `define_method` as a method body, the `bidx` may not be within `env` saved closure. In this case, it causes heap buffer overflow. --- src/kernel.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/kernel.c b/src/kernel.c index 1e5a74222..929ffd26a 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -153,13 +153,19 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self) if (p == NULL) return mrb_false_value(); if (MRB_PROC_ENV_P(p)) { struct REnv *e = MRB_PROC_ENV(p); + int bidx; + /* top-level does not have block slot (always false) */ if (e->stack == mrb->c->stbase) return mrb_false_value(); /* use saved block arg position */ - bp = &e->stack[MRB_ENV_BIDX(e)]; + bidx = MRB_ENV_BIDX(e); + /* bidx may be useless (e.g. define_method) */ + if (bidx >= MRB_ENV_STACK_LEN(e)) + return mrb_false_value(); + bp = &e->stack[bidx]; } - if (ci && ci->argc > 0) { + else if (ci && ci->argc > 0) { bp += ci->argc; } if (mrb_nil_p(*bp)) -- cgit v1.2.3