summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2017-11-04 03:01:37 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2017-11-04 03:01:37 +0900
commitab27abe0834bc9da38d4a4d895514a66ea53fe84 (patch)
tree434603051ac33b1cf9e3c76dcf9f5db1ee8ce86a /src
parente7fe6ee2638dee438c1d79ab16a0403aebec0a60 (diff)
downloadmruby-ab27abe0834bc9da38d4a4d895514a66ea53fe84.tar.gz
mruby-ab27abe0834bc9da38d4a4d895514a66ea53fe84.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/kernel.c10
1 files changed, 8 insertions, 2 deletions
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))