diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-11-04 03:01:37 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-11-04 03:01:37 +0900 |
| commit | ab27abe0834bc9da38d4a4d895514a66ea53fe84 (patch) | |
| tree | 434603051ac33b1cf9e3c76dcf9f5db1ee8ce86a /src | |
| parent | e7fe6ee2638dee438c1d79ab16a0403aebec0a60 (diff) | |
| download | mruby-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.c | 10 |
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)) |
