mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b82843e72 | |||
| b40ab7bfee | |||
| aefc5befbd | |||
| be5266fbe6 | |||
| 4d5aadfc84 | |||
| 079244c36a | |||
| 6b0efd43da | |||
| 2e9f62b12c | |||
| 3c02c517ca | |||
| 998ef1711a | |||
| a223778ee8 | |||
| 882bb0662a | |||
| b0e537c05c | |||
| 97fe582d41 | |||
| 36f822d9af |
@@ -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)
|
||||
|
||||
@@ -20,7 +20,7 @@ of the Ministry of Economy, Trade and Industry of Japan.
|
||||
|
||||
## How to get mruby
|
||||
|
||||
The release candidate version 3.2.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/3.2.0-rc2.zip](https://github.com/mruby/mruby/archive/3.2.0-rc2.zip)
|
||||
The release candidate version 3.2.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/3.2.0-rc3.zip](https://github.com/mruby/mruby/archive/3.2.0-rc3.zip)
|
||||
|
||||
The latest development version of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/zipball/master](https://github.com/mruby/mruby/zipball/master)
|
||||
|
||||
|
||||
@@ -35,6 +35,25 @@
|
||||
- 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
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -57,7 +57,7 @@ MRB_BEGIN_DECL
|
||||
/*
|
||||
* Patch level string. (optional)
|
||||
*/
|
||||
#define MRUBY_PATCHLEVEL_STR "RC2"
|
||||
#define MRUBY_PATCHLEVEL_STR "RC3"
|
||||
|
||||
#ifndef MRUBY_PATCHLEVEL_STR
|
||||
# if MRUBY_PATCHLEVEL < 0
|
||||
@@ -90,7 +90,7 @@ MRB_BEGIN_DECL
|
||||
/*
|
||||
* Release day.
|
||||
*/
|
||||
#define MRUBY_RELEASE_DAY 18
|
||||
#define MRUBY_RELEASE_DAY 23
|
||||
|
||||
/*
|
||||
* Release date as a string.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+22
-33
@@ -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;
|
||||
@@ -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; i<limit; i++) {
|
||||
if (buf->mem[i] == c) {
|
||||
if (memcmp(buf->mem+i, rs, rslen) == 0)
|
||||
return i;
|
||||
const char *p = buf->mem+buf->start;
|
||||
for (mrb_int i=0; i<limit; i++) {
|
||||
if (p[i] == c && (rslen == 1 || memcmp(p+i, rs, rslen) == 0)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
@@ -1783,36 +1783,25 @@ io_gets(mrb_state *mrb, mrb_value io)
|
||||
outbuf = mrb_str_new(mrb, NULL, 0);
|
||||
}
|
||||
|
||||
if (!rs_given) { /* no RS; only limit */
|
||||
mrb_assert(limit_given);
|
||||
for (;;) {
|
||||
if (buf->len >= 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);
|
||||
|
||||
@@ -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
|
||||
|
||||
+27
-25
@@ -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; i<t->alloc; 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;
|
||||
}
|
||||
}
|
||||
@@ -1765,11 +1770,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);
|
||||
@@ -1790,15 +1794,7 @@ mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid)
|
||||
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;
|
||||
@@ -1814,6 +1810,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)
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user