From 36f822d9afe7f824b836b07e353d7fc1e91fba50 Mon Sep 17 00:00:00 2001 From: dearblue Date: Fri, 20 Jan 2023 21:26:21 +0900 Subject: [PATCH 1/9] Fixed `Kernel#.eval` crash when given a custom defined `Binding` instance ```console % bin/mruby -e 'class Binding; end; eval "1", Binding.new' zsh: segmentation fault (core dumped) bin/mruby -e 'class Binding; end; eval "1", Binding.new' ``` --- mrbgems/mruby-eval/src/eval.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c index 19145300e..ff65b0fa1 100644 --- a/mrbgems/mruby-eval/src/eval.c +++ b/mrbgems/mruby-eval/src/eval.c @@ -29,14 +29,14 @@ create_proc_from_string(mrb_state *mrb, const char *s, mrb_int len, mrb_value bi mrb_obj_class(mrb, binding)); } scope_obj = mrb_iv_get(mrb, binding, MRB_SYM(proc)); - mrb_assert(mrb_proc_p(scope_obj)); + mrb_check_type(mrb, scope_obj, MRB_TT_PROC); scope = mrb_proc_ptr(scope_obj); if (MRB_PROC_CFUNC_P(scope)) { e = NULL; } else { mrb_value env = mrb_iv_get(mrb, binding, MRB_SYM(env)); - mrb_assert(mrb_env_p(env)); + mrb_check_type(mrb, env, MRB_TT_ENV); e = (struct REnv *)mrb_obj_ptr(env); mrb_assert(e != NULL); } From b0e537c05c98f150c00c73008125c5709b6ef5fc Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 22 Jan 2023 09:20:10 +0900 Subject: [PATCH 2/9] Replaced `NO_IO_POPEN` with `MRB_NO_IO_POPEN` ref. commit 9deb52c7b2ba6028d996172bfdd6cf8a0405ce1c --- mrbgems/mruby-io/src/io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mrbgems/mruby-io/src/io.c b/mrbgems/mruby-io/src/io.c index 5ef60d039..8ba4760ac 100644 --- a/mrbgems/mruby-io/src/io.c +++ b/mrbgems/mruby-io/src/io.c @@ -339,7 +339,7 @@ io_alloc(mrb_state *mrb) #define NOFILE 64 #endif -#ifdef NO_IO_POPEN +#ifdef MRB_NO_IO_POPEN # define io_s_popen mrb_notimplement_m #else static int @@ -770,7 +770,7 @@ fptr_finalize(mrb_state *mrb, struct mrb_io *fptr, int quiet) fptr->fd2 = -1; } -#ifndef NO_IO_POPEN +#ifndef MRB_NO_IO_POPEN if (fptr->pid != 0) { #if !defined(_WIN32) && !defined(_WIN64) pid_t pid; From a223778ee8e380a35e7c0d75ff25e90677db05f5 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 22 Jan 2023 20:45:57 +0900 Subject: [PATCH 3/9] Update mruby3.2.md for changes behavior of `mrb_vm_run()` --- doc/mruby3.2.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/doc/mruby3.2.md b/doc/mruby3.2.md index 1cf97a87b..8585b6321 100644 --- a/doc/mruby3.2.md +++ b/doc/mruby3.2.md @@ -36,6 +36,24 @@ - mruby-set from [https://github.com/yui-knk/mruby-set.git] - mruby-dir from [https://github.com/iij/mruby-dir.git] +# Breaking Changes + +## `mrb_vm_run()` may detach top-level local variables referenced from blocks + +When the `mrb_vm_run()` function (including `mrb_top_run()`) is called, +the previous top-level local variables referenced from blocks is detached under either of the following conditions. + +- If the `stack_keep` parameter is given as 0. +- If the number of variables in `irep` to be executed is less than the number of previous top-level local variables. + +This change also affects API functions such as `mrb_load_string()` and `mrb_load_file()`. +The conditions under which the previous top-level local variables referenced from blocks is detached in these functions are as follows: + +- If the function has no `mrbc_context` pointer parameter, or the `mrbc_context` pointer parameter is set to `NULL`. +- If the number of variables held in the `mrbc_context` pointer is less than the number of previous top-level local variables. + +Intentional reliance on previous behavior may cause compatibility problems in your application. + # CVEs Following CVEs are fixed. From 998ef1711aa8b4b397c7acc0d787dcdc1ea5cd93 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 22 Jan 2023 20:52:09 +0900 Subject: [PATCH 4/9] Update mruby3.2.md for new `mruby-data` gem --- doc/mruby3.2.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/mruby3.2.md b/doc/mruby3.2.md index 1cf97a87b..708da438b 100644 --- a/doc/mruby3.2.md +++ b/doc/mruby3.2.md @@ -35,6 +35,7 @@ - mruby-errno from [https://github.com/iij/mruby-errno.git] - mruby-set from [https://github.com/yui-knk/mruby-set.git] - mruby-dir from [https://github.com/iij/mruby-dir.git] +- mruby-data # CVEs From 6b0efd43dac6f6c94930a823b37c9c5873ec1436 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 19 Jan 2023 11:34:42 +0900 Subject: [PATCH 5/9] NEWS: copy entries from doc/mruby3.2.md --- NEWS | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index db4253988..34cf84528 100644 --- a/NEWS +++ b/NEWS @@ -1,12 +1,64 @@ NEWS ---- -This document is a list of user visible feature changes made between -releases except for bug fixes. +# User visible changes in `mruby3.2` -Note that each entry is kept so brief that no reason behind or -reference information is supplied with. For a full list of changes -with all sufficient information, see the ChangeLog file. +# The language +- Now `a::B = c` should evaluate `a` then `c`. +- Anonymous arguments `*`, `**`, `&` can be passed for forwarding. +- Multi-precision integer is available now via `mruby-bigint` gem. -** Information about first release v1.0.0 +# mruby VM and bytecode + +- `OP_ARYDUP` was renamed to `OP_ARYSPLAT`. The instruction name + was changed but instruction number and basic behavior have not + changed (except that `ARYDUP nil` makes `[]`). + +# Tools + +## `mruby` + +- `-b` only specifies the script is the binary. The files loaded by `-r` are not affected by the option. +- `mruby` now loads complied binary if the suffix is `.mrb`. + +## `mrbc` + +- Add `--no-optimize` option to disable optimization. + +# mrbgems + +## mruby-class-ext + +- Add `Class#subclasses` method. +- Add `Module#undefined_instance_methods` method. + +## New bundled gems + +- mruby-errno from [https://github.com/iij/mruby-errno.git] +- mruby-set from [https://github.com/yui-knk/mruby-set.git] +- mruby-dir from [https://github.com/iij/mruby-dir.git] + +# CVEs + +Following CVEs are fixed. + +- [CVE-2022-0080](https://nvd.nist.gov/vuln/detail/CVE-2022-0080) +- [CVE-2022-0240](https://nvd.nist.gov/vuln/detail/CVE-2022-0240) +- [CVE-2022-0326](https://nvd.nist.gov/vuln/detail/CVE-2022-0326) +- [CVE-2022-0631](https://nvd.nist.gov/vuln/detail/CVE-2022-0631) +- [CVE-2022-0481](https://nvd.nist.gov/vuln/detail/CVE-2022-0481) +- [CVE-2022-0525](https://nvd.nist.gov/vuln/detail/CVE-2022-0525) +- [CVE-2022-0570](https://nvd.nist.gov/vuln/detail/CVE-2022-0570) +- [CVE-2022-0614](https://nvd.nist.gov/vuln/detail/CVE-2022-0614) +- [CVE-2022-0623](https://nvd.nist.gov/vuln/detail/CVE-2022-0623) +- [CVE-2022-0630](https://nvd.nist.gov/vuln/detail/CVE-2022-0630) +- [CVE-2022-0631](https://nvd.nist.gov/vuln/detail/CVE-2022-0631) +- [CVE-2022-0632](https://nvd.nist.gov/vuln/detail/CVE-2022-0632) +- [CVE-2022-0717](https://nvd.nist.gov/vuln/detail/CVE-2022-0717) +- [CVE-2022-0890](https://nvd.nist.gov/vuln/detail/CVE-2022-0890) +- [CVE-2022-1106](https://nvd.nist.gov/vuln/detail/CVE-2022-1106) +- [CVE-2022-1212](https://nvd.nist.gov/vuln/detail/CVE-2022-1212) +- [CVE-2022-1276](https://nvd.nist.gov/vuln/detail/CVE-2022-1276) +- [CVE-2022-1286](https://nvd.nist.gov/vuln/detail/CVE-2022-1286) +- [CVE-2022-1934](https://nvd.nist.gov/vuln/detail/CVE-2022-1934) From 079244c36a60ce13f77298e200b1a9411b868c30 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 20 Jan 2023 18:34:36 +0900 Subject: [PATCH 6/9] src/class.c: add new function `mrb_vm_find_method` The function skips `cp` dereference, and improve performance of method calls slightly. --- include/mruby/internal.h | 1 + src/class.c | 11 ++++++++--- src/vm.c | 8 ++++---- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/include/mruby/internal.h b/include/mruby/internal.h index ac5ecfbc2..db64fd38f 100644 --- a/include/mruby/internal.h +++ b/include/mruby/internal.h @@ -22,6 +22,7 @@ mrb_value mrb_class_find_path(mrb_state*, struct RClass*); mrb_value mrb_mod_to_s(mrb_state *, mrb_value); void mrb_method_added(mrb_state *mrb, struct RClass *c, mrb_sym mid); mrb_noreturn void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args); +mrb_method_t mrb_vm_find_method(mrb_state *mrb, struct RClass *c, struct RClass **cp, mrb_sym mid); #endif /* debug */ diff --git a/src/class.c b/src/class.c index f990c37ee..86ca88e6c 100644 --- a/src/class.c +++ b/src/class.c @@ -1765,11 +1765,10 @@ mc_clear_by_id(mrb_state *mrb, mrb_sym id) } #endif -MRB_API mrb_method_t -mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid) +mrb_method_t +mrb_vm_find_method(mrb_state *mrb, struct RClass *c, struct RClass **cp, mrb_sym mid) { mrb_method_t m; - struct RClass *c = *cp; #ifndef MRB_NO_METHOD_CACHE struct RClass *oc = c; int h = kh_int_hash_func(mrb, ((intptr_t)oc) ^ mid) & (MRB_METHOD_CACHE_SIZE-1); @@ -1814,6 +1813,12 @@ mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid) return m; /* no method */ } +MRB_API mrb_method_t +mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid) +{ + return mrb_vm_find_method(mrb, *cp, cp, mid); +} + MRB_API mrb_method_t mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid) { diff --git a/src/vm.c b/src/vm.c index 323324d39..475f02ab1 100644 --- a/src/vm.c +++ b/src/vm.c @@ -562,7 +562,7 @@ prepare_missing(mrb_state *mrb, mrb_callinfo *ci, mrb_value recv, mrb_sym mid, m if (mid != missing) { ci->u.target_class = mrb_class(mrb, recv); } - m = mrb_method_search_vm(mrb, &ci->u.target_class, missing); + m = mrb_vm_find_method(mrb, ci->u.target_class, &ci->u.target_class, missing); if (MRB_METHOD_UNDEF_P(m)) goto method_missing; /* just in case */ mrb_stack_extend(mrb, 4); @@ -662,7 +662,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc ci = cipush(mrb, n, CINFO_DIRECT, NULL, NULL, BLK_PTR(blk), 0, 0); funcall_args_capture(mrb, 0, argc, argv, blk, ci); ci->u.target_class = mrb_class(mrb, self); - m = mrb_method_search_vm(mrb, &ci->u.target_class, mid); + m = mrb_vm_find_method(mrb, ci->u.target_class, &ci->u.target_class, mid); if (MRB_METHOD_UNDEF_P(m)) { m = prepare_missing(mrb, ci, self, mid, mrb_nil_value(), FALSE); } @@ -816,7 +816,7 @@ mrb_f_send(mrb_state *mrb, mrb_value self) } c = mrb_class(mrb, self); - m = mrb_method_search_vm(mrb, &c, name); + m = mrb_vm_find_method(mrb, c, &c, name); if (MRB_METHOD_UNDEF_P(m)) { /* call method_mising */ goto funcall; } @@ -1769,7 +1769,7 @@ RETRY_TRY_BLOCK: ci = cipush(mrb, a, CINFO_DIRECT, NULL, NULL, BLK_PTR(blk), 0, c); recv = regs[0]; ci->u.target_class = (insn == OP_SUPER) ? CI_TARGET_CLASS(ci - 1)->super : mrb_class(mrb, recv); - m = mrb_method_search_vm(mrb, &ci->u.target_class, mid); + m = mrb_vm_find_method(mrb, ci->u.target_class, &ci->u.target_class, mid); if (MRB_METHOD_UNDEF_P(m)) { m = prepare_missing(mrb, ci, recv, mid, blk, (insn == OP_SUPER)); } From 4d5aadfc840f16b5759ba40569a9b536a8f030cf Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 21 Jan 2023 23:23:09 +0900 Subject: [PATCH 7/9] class.c (create_method_value): refactor `mrb_method_t` creation --- src/class.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/src/class.c b/src/class.c index 86ca88e6c..6cd40cfd3 100644 --- a/src/class.c +++ b/src/class.c @@ -244,6 +244,23 @@ mt_free(mrb_state *mrb, mt_tbl *t) mrb_free(mrb, t); } +static inline mrb_method_t +create_method_value(mrb_state *mrb, mrb_sym key, union mt_ptr val) +{ + mrb_method_t m; + + if (key & MT_FUNC_P) { + MRB_METHOD_FROM_FUNC(m, val.func); + } + else { + MRB_METHOD_FROM_PROC(m, val.proc); + } + if (key & MT_NOARG_P) { + MRB_METHOD_NOARG_SET(m); + } + return m; +} + MRB_API void mrb_mt_foreach(mrb_state *mrb, struct RClass *c, mrb_mt_foreach_func *fn, void *p) { @@ -259,19 +276,7 @@ mrb_mt_foreach(mrb_state *mrb, struct RClass *c, mrb_mt_foreach_func *fn, void * for (i=0; ialloc; i++) { mrb_sym key = keys[i]; if (MT_KEY_SYM(key)) { - mrb_method_t m; - - if (key & MT_FUNC_P) { - MRB_METHOD_FROM_FUNC(m, vals[i].func); - } - else { - MRB_METHOD_FROM_PROC(m, vals[i].proc); - } - if (key & MT_NOARG_P) { - MRB_METHOD_NOARG_SET(m); - } - - if (fn(mrb, MT_KEY_SYM(key), m, p) != 0) + if (fn(mrb, MT_KEY_SYM(key), create_method_value(mrb, key, vals[i]), p) != 0) return; } } @@ -1789,15 +1794,7 @@ mrb_vm_find_method(mrb_state *mrb, struct RClass *c, struct RClass **cp, mrb_sym if (ret) { if (ptr.proc == 0) break; *cp = c; - if (ret & MT_FUNC_P) { - MRB_METHOD_FROM_FUNC(m, ptr.func); - } - else { - MRB_METHOD_FROM_PROC(m, ptr.proc); - } - if (ret & MT_NOARG_P) { - MRB_METHOD_NOARG_SET(m); - } + m = create_method_value(mrb, ret, ptr); #ifndef MRB_NO_METHOD_CACHE mc->c = oc; mc->c0 = c; From be5266fbe6eafef400874bb62b87bcfea07be425 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Jan 2023 07:25:52 +0900 Subject: [PATCH 8/9] mruby-io/test: test gets with RS multiple times; ref #5913 --- mrbgems/mruby-io/test/io.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/mrbgems/mruby-io/test/io.rb b/mrbgems/mruby-io/test/io.rb index 610216ab0..024a71acd 100644 --- a/mrbgems/mruby-io/test/io.rb +++ b/mrbgems/mruby-io/test/io.rb @@ -369,6 +369,7 @@ assert('IO#gets') do # gets with rs io.pos = 0 assert_equal $mrbtest_io_msg[0, 6], io.gets(' '), "gets with rs" + assert_equal $mrbtest_io_msg[6, 3], io.gets(' '), "gets with rs(2)" # gets with rs, limit io.pos = 0 From aefc5befbda405527f0fc19f4f357b5467631ba4 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Jan 2023 07:27:18 +0900 Subject: [PATCH 9/9] mruby-io/io.c: fix issues with gets; fix #5913 - gets with RS multiple times - gets with RS with limit - gets with limit bigger than buffer size --- mrbgems/mruby-io/src/io.c | 51 +++++++++++++++------------------------ 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/mrbgems/mruby-io/src/io.c b/mrbgems/mruby-io/src/io.c index 8ba4760ac..ebe19930a 100644 --- a/mrbgems/mruby-io/src/io.c +++ b/mrbgems/mruby-io/src/io.c @@ -1714,10 +1714,10 @@ io_find_index(struct mrb_io *fptr, const char *rs, mrb_int rslen) mrb_assert(rslen > 0); const char c = rs[0]; const mrb_int limit = buf->len - rslen; - for (mrb_int i=buf->start; imem[i] == c) { - if (memcmp(buf->mem+i, rs, rslen) == 0) - return i; + const char *p = buf->mem+buf->start; + for (mrb_int i=0; ilen >= limit) { + for (;;) { + if (rs_given) { /* with RS */ + int rslen = RSTRING_LEN(rs); + mrb_int idx = io_find_index(fptr, RSTRING_PTR(rs), rslen); + if (idx >= 0) { /* found */ + mrb_int n = idx+rslen; + if (limit_given && limit < n) { + n = limit; + } + io_buf_cat(mrb, outbuf, fptr, n); + return outbuf; + } + } + if (limit_given) { + if (limit <= buf->len) { io_buf_cat(mrb, outbuf, fptr, limit); return outbuf; } - io_buf_cat_all(mrb, outbuf, fptr); - io_buf_fill(mrb, fptr); - if (fptr->eof) { - if (RSTRING_LEN(outbuf) == 0) return mrb_nil_value(); - return outbuf; - } - } - } - - for (;;) { /* with RS */ - int rslen = RSTRING_LEN(rs); - mrb_int idx = io_find_index(fptr, RSTRING_PTR(rs), rslen); - if (idx >= 0) { /* found */ - mrb_int n = idx+rslen; - if (limit_given && limit < n) { - n = limit; - } - io_buf_cat(mrb, outbuf, fptr, n); - return outbuf; - } - if (limit_given && buf->len < limit) { - io_buf_cat(mrb, outbuf, fptr, limit); - return outbuf; + limit -= buf->len; } io_buf_cat_all(mrb, outbuf, fptr); io_buf_fill(mrb, fptr);