Compare commits

..

15 Commits

Author SHA1 Message Date
mimaki 1bec339230 Update version and release date. (mruby 3.1.0 (2022-05-12)) 2022-05-12 12:19:10 +09:00
Yukihiro "Matz" Matsumoto 242a7f14e0 mruby3.1.md: update fixed CVE list. 2022-05-10 20:32:04 +09:00
Yukihiro "Matz" Matsumoto f13db72d26 load.c: add data boundary check for broken compiled binary. 2022-05-10 20:11:17 +09:00
Yukihiro "Matz" Matsumoto b82065aa92 load.c: should check if length of irep sections are valid. 2022-05-10 20:11:17 +09:00
Yukihiro "Matz" Matsumoto 11679e3f3a vm.c: check if target_class is NULL (when prepended).
Address CVE-2022-1427
2022-05-10 20:11:17 +09:00
Yukihiro "Matz" Matsumoto 82d3b3d11b vm.c: target class may be NULL.
Address CVE-2022-1201
2022-05-10 20:11:17 +09:00
Yukihiro "Matz" Matsumoto 2cbfc2f350 vm.c: vm.c: stack may be reallocated in functions calls; aaa28a5
`mrb_range_new()` also calls VM recursively.

Address CVE-2022-1106
2022-05-10 20:11:16 +09:00
Yukihiro "Matz" Matsumoto 6db4a58fbd vm.c: stack may be reallocated in functions calls.
Probably due to recursive VM calls via `mrb_funcall()`.

Address CVE-2022-1071
2022-05-10 19:24:46 +09:00
Yukihiro "Matz" Matsumoto 96cfde3488 fiber.c: should pack 15+ arguments in an array.
Address CVE-2022-0890
2022-05-10 19:24:46 +09:00
Yukihiro "Matz" Matsumoto 2e48070ab6 codegen.c: adjust stack position for OP_SUPER instruction.
Address CVE-2022-0632
2022-05-10 16:34:19 +09:00
Yukihiro "Matz" Matsumoto d823045af4 vm.c: packed arguments length may be zero for send method.
Address CVE-2022-0631
2022-05-10 16:32:03 +09:00
Yukihiro "Matz" Matsumoto c9ab1e601d codegen.c: fixed a bug in hash code generation with !val.
Address CVE-2022-0481
2022-05-10 14:56:53 +09:00
Yukihiro "Matz" Matsumoto beef5d37ad codegen.c: no OP_HASHADD required when val is false.
Address CVE-2022-0326
2022-05-10 14:55:58 +09:00
Yukihiro "Matz" Matsumoto 15f597e835 class.c: add obj->c check before prepare_singleton_class().
Address CVE-2022-0240
2022-05-10 14:54:45 +09:00
Yukihiro "Matz" Matsumoto 84b0ba3f8d doc/mruby3.1.md: update for the release. 2022-05-09 17:46:26 +09:00
11 changed files with 272 additions and 116 deletions
+1 -1
View File
@@ -6,7 +6,7 @@
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "mruby"
PROJECT_NUMBER = 3.0.0
PROJECT_NUMBER = 3.1.0
PROJECT_BRIEF = "mruby is the lightweight implementation of the Ruby language"
+1 -1
View File
@@ -20,7 +20,7 @@ of the Ministry of Economy, Trade and Industry of Japan.
## How to get mruby
The release candidate version 3.1.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/3.1.0-rc2.zip](https://github.com/mruby/mruby/archive/3.1.0-rc2.zip)
The stable version 3.1.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/3.1.0.zip](https://github.com/mruby/mruby/archive/3.1.0.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)
+1 -1
View File
@@ -38,7 +38,7 @@ To confirm mrdb was installed properly, run mrdb with the `--version` option:
```bash
$ mrdb --version
mruby 3.0.0 (2021-03-05)
mruby 3.1.0 (2022-05-12)
```
## 2.2 Basic Operation
+8 -8
View File
@@ -30,7 +30,7 @@ end
`ZeroDivisionError` is raised.
#### mruby [3.0.0 (2021-03-05)]
#### mruby [3.1.0 (2022-05-12)]
`RuntimeError` is raised instead of `ZeroDivisionError`. To re-raise the exception, you have to do:
@@ -66,7 +66,7 @@ p Liste.new "foobar"
` [] `
#### mruby [3.0.0 (2021-03-05)]
#### mruby [3.1.0 (2022-05-12)]
`ArgumentError` is raised.
@@ -96,7 +96,7 @@ false
true
```
#### mruby [3.0.0 (2021-03-05)]
#### mruby [3.1.0 (2022-05-12)]
```
true
@@ -133,7 +133,7 @@ p 'ok'
ok
```
#### mruby [3.0.0 (2021-03-05)]
#### mruby [3.1.0 (2022-05-12)]
```
test.rb:8: undefined method 'test_func' (NoMethodError)
@@ -155,7 +155,7 @@ defined?(Foo)
nil
```
#### mruby [3.0.0 (2021-03-05)]
#### mruby [3.1.0 (2022-05-12)]
`NameError` is raised.
@@ -172,7 +172,7 @@ alias $a $__a__
` nil `
#### mruby [3.0.0 (2021-03-05)]
#### mruby [3.1.0 (2022-05-12)]
Syntax error
@@ -194,7 +194,7 @@ end
`ArgumentError` is raised.
The re-defined `+` operator does not accept any arguments.
#### mruby [3.0.0 (2021-03-05)]
#### mruby [3.1.0 (2022-05-12)]
` 'ab' `
Behavior of the operator wasn't changed.
@@ -210,7 +210,7 @@ $ ruby -e 'puts Proc.new {}.binding'
#<Binding:0x00000e9deabb9950>
```
#### mruby [3.0.0 (2021-03-05)]
#### mruby [3.1.0 (2022-05-12)]
```
$ ./bin/mruby -e 'puts Proc.new {}.binding'
+149 -42
View File
@@ -1,48 +1,91 @@
# User visible changes in `mruby3.1` from `mruby3.0`
# Build System
# New Features
## `build_config` directory
## Core Language Features
Several configurations for new platforms are added:
### Keyword Arguments
* `cross-mingw-winetest.rb`
* `cross-mingw.rb`
* `nintendo_switch.rb`
* `serenity.rb`
CRuby3.0 compatible keyword arguments are introduced.
Keyword arguments are basically separated from ordinal arguments.
Some new configurations for added for convenience.
### Other Language Enhancement
* `minimal`: minimal configuration
* `host-f32`: compiles with `mrb_float` as 32 bit `float`
* `host-nofloat`: compiles with no float configuration
- Implement endless-def [Ruby:Feature#16746](https://bugs.ruby-lang.org/issues/16746)
- Replace `R-assignment` by `single-line pattern matching` [Ruby:Feature#15921](https://bugs.ruby-lang.org/issues/15921)
- Support squiggly heredocs. [#5246](https://github.com/mruby/mruby/pull/5246)
- Hash value omission [Ruby:Feature#14579](https://bugs.ruby-lang.org/issues/14579)
And `android_arm64-v8a.rb` was renamed to `android_arm64_v8a.rb` for consistency.
# Configuration Options Changed
## Configuration Options Changed
Some configuration macros are available:
* `MRB_WORDBOX_NO_FLOAT_TRUNCATE`: by default, float values are packed in the word if possible, but define this macro to allocate float values in the heap.
* `MRB_USE_RO_DATA_P_ETEXT`: define this macro if `_etext` is available on your platform.
* `MRB_NO_DEFAULT_RO_DATA_P`: define this macro to avoid using predefined `mrb_ro_data_p()` function
- `MRB_WORDBOX_NO_FLOAT_TRUNCATE`: by default, float values are packed in the word if possible, but define this macro to allocate float values in the heap.
- `MRB_USE_RO_DATA_P_ETEXT`: define this macro if `_etext` is available on your platform.
- `MRB_NO_DEFAULT_RO_DATA_P`: define this macro to avoid using predefined `mrb_ro_data_p()` function
# Language Changes
---
## Keyword Arguments
# Updated Features
CRuby3.0 compatible keyword arguments are introduced.
Keyword arguments are basically separated from ordinal arguments
## New build configurations
## New Methods
We have added several new build configurations in the `build_config` directory.
* `Array#product`
* `Array#repeated_combination`
* `Array#repeated_permutation`
* `Random.bytes`
* `Random#bytes`
- `cross-mingw-winetest.rb`
- `cross-mingw.rb`
- `nintendo_switch.rb`
- `serenity.rb`
- `minimal`: minimal configuration
- `host-f32`: compiles with `mrb_float` as 32 bit `float`
- `host-nofloat`: compiles with no float configuration
- `android_arm64_v8a.rb`: renamed from `android_arm64-v8a.rb`
# Internal Changes
## Core Libraries
### New Methods
- `Array#product`
- `Array#repeated_combination`
- `Array#repeated_permutation`
- `Kernel#__ENCODING__`
- `Random.bytes`
- `Random#bytes`
- `String#center`
### New Gem Enhancement
- `mrbgems/mruby-pack` now supports `M` directive (Q encoding)
- `mrbgems/mruby-pack` now supports `X` directive (back-up by bytes)
- `mrbgems/mruby-pack` now supports `@` directive (absolute position)
- `mrbgems/mruby-pack` now supports `w` directive (BER compression)
## Tools
- `mruby-config` now supports `--cc` and `--ld` options.
- Remove `OP_` prefix from `mruby -v` code dump output.
- Prohibit use of `OP_EXT{1,2,3}` by `mrbc` with `--no-ext-ops` option.
## Features for mruby Developer
- Add new specifier `c` to `mrb_get_args()` for receive Class/Module.
---
# Breaking Changes
## Incompatibly Changed Methods
- `Kernel#printf` (`mruby-sprintf`) Format specifiers `%a` and `%A` are removed.
- `Kernel#puts` (`mruby-print`) Now expand Array arguments.
## mruby VM and bytecode
Due to improvements in the binary format, mruby binaries are no longer backward compatible.
To run the mruby binaries on mruby 3.1, recompile with the mruby 3.1 `mrbc`.
- Upgrade mruby VM version `RITE_VM_VER` to `0300` (means mruby 3.0 or after).
- Upgrade mruby binary version `RITE_BINARY_FORMAT_VER` to `0300`.
## Reintroduced Instructions
@@ -53,18 +96,18 @@ Keyword arguments are basically separated from ordinal arguments
`mruby3.1` removed following instructions.
* `OP_LOADL16`
* `OP_LOADSYM16`
* `OP_STRING16`
* `OP_LAMBDA16`
* `OP_BLOCK16`
* `OP_METHOD16`
* `OP_EXEC16`
- `OP_LOADL16`
- `OP_LOADSYM16`
- `OP_STRING16`
- `OP_LAMBDA16`
- `OP_BLOCK16`
- `OP_METHOD16`
- `OP_EXEC16`
Those instructions are no longer needed by reintroduction of extension instructions.
* `OP_SENDV`
* `OP_SENDVB`
- `OP_SENDV`
- `OP_SENDVB`
Those instructions for method calls with variable number of arguments are no longer needed. They are covered by `OP_SEND` instruction with `n=15`.
@@ -72,10 +115,11 @@ Those instructions for method calls with variable number of arguments are no lon
`mruby3.1` introduces following new instructions.
* `OP_GETIDX`: takes 2 operands `a[b]`
* `OP_SETIDX`: takes 3 operands `a[b]=c`
* `OP_SSEND`: takes 3 operands `a=self.b(c...)`; see `OP_SEND`
* `OP_SSENDB`: takes 3 operands `a=self.b(c...){...}`; see `OP_SEND`
- `OP_GETIDX`: takes 1 operands `R[a][a+1]`
- `OP_SETIDX`: takes 1 operands `R[a][a+1]=R[a+2]`
- `OP_SSEND`: takes 3 operands `a=self.b(c...)`; see `OP_SEND`
- `OP_SSENDB`: takes 3 operands `a=self.b(c...){...}`; see `OP_SEND`
- `OP_SYMBOL`: takes 2 operands `R[a] = intern(Pool[b])`
### `OP_GETIDX` and `OP_SETIDX`
@@ -85,6 +129,10 @@ Execute `obj[int]` and `obj[int] = value` respectively, where `obj` is `string|a
They are similar to `OP_SEND` and `OP_SENDB` respectively. They initialize the `R[a]` by `self` first so that we can skip one `OP_LOADSELF` instruction for each call.
### `OP_SYMBOL`
Extracts the character string placed in the pool as a symbol.
## Changed Instructions
### `OP_SEND` and `OP_SENDB`
@@ -114,7 +162,7 @@ If the size of `mrb_float` and `mrb_int` are same, the last 2 bits in the `mrb_f
Previous NaN boxing packs values in NaN representation, but pointer retrievals are far more frequent than floating point number references. So we add constant offset to NaN representation to clear higher bits of pointer representation. This representation is called "Favor Pointer" NaN Boxing.
Also, previous NaN boxing limit the size of `mrb_int` to 4 bytes (32 bits) to fit in NaN values. Now we allocates integer values in the heap, if the value does not fit in the 32 bit range, just like we did in Word Boxing.
Also, previous NaN boxing limit the size of `mrb_int` to 4 bytes (32 bits) to fit in NaN values. Now we allocate integer values in the heap, if the value does not fit in the 32 bit range, just like we did in Word Boxing.
## Constant Folding
@@ -146,3 +194,62 @@ GETIV R1 :@foo
## `String#hash` now use `FNV1a` algorithm
For better and faster hash values.
---
# Major bug fixes
- Fix infinite recursive call bugs in integer division [98799aa6](https://github.com/mruby/mruby/commit/98799aa6)
- Fix to raise TypeError with super inside instance_eval / class_eval [#5476](https://github.com/mruby/mruby/pull/5476)
- Fix to call `method_added` hooks on method definitions; [#2339](https://github.com/mruby/mruby/pull/2339)
- Fix a potential buffer overflow in `time_zonename` [26340a88](https://github.com/mruby/mruby/commit/26340a88)
- Fix `Module.instance_eval` bug [#5528](https://github.com/mruby/mruby/pull/5528)
- Fix fix `M` packing bug [bfe2bd49](https://github.com/mruby/mruby/commit/bfe2bd49)
- Fix a bug regarding attribute assignment with kargs [de2b4bd0](https://github.com/mruby/mruby/commit/de2b4bd0)
- Fix SIGSEGV with mrbgems/mruby-method [#5580](https://github.com/mruby/mruby/pull/5580)
- Fix print error before cleanup in `codegen_error()` [#5603](https://github.com/mruby/mruby/pull/5603)
- Fix a bug in unpacking BER [#5611](https://github.com/mruby/mruby/pull/5611)
- Fix a bug with numbered parameters as arguments [#5605](https://github.com/mruby/mruby/pull/5605)
- Fix `mrb_ary_shift_m` initialization bug [27d1e013](https://github.com/mruby/mruby/commit/27d1e013)
- Fix keyword argument with `super` [#5628](https://github.com/mruby/mruby/pull/5628)
- Fix a bug with numbered parameters on toplevel [7e7f1b2f](https://github.com/mruby/mruby/commit/7e7f1b2f)
- Fix keyword argument bug [#5632](https://github.com/mruby/mruby/issues/5632)
- Fix multiple assignments in parameters [#5647](https://github.com/mruby/mruby/issues/5647)
- Fix keyword parameters not passing through super [#5660](https://github.com/mruby/mruby/issues/5660)
- Fix infinite loop from unclosed here-doc [#5676](https://github.com/mruby/mruby/issues/5676)
- Fix negative integer division bug [#5678](https://github.com/mruby/mruby/issues/5678)
# CVEs
## Fixed CVEs
Following CVEs are fixed in this release.
- [CVE-2021-4110](https://nvd.nist.gov/vuln/detail/CVE-2021-4110)
- [CVE-2021-4188](https://nvd.nist.gov/vuln/detail/CVE-2021-4188)
- [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-0481](https://nvd.nist.gov/vuln/detail/CVE-2022-0481)
- [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-0890](https://nvd.nist.gov/vuln/detail/CVE-2022-0890)
- [CVE-2022-1071](https://nvd.nist.gov/vuln/detail/CVE-2022-1071)
- [CVE-2022-1106](https://nvd.nist.gov/vuln/detail/CVE-2022-1106)
- [CVE-2022-1201](https://nvd.nist.gov/vuln/detail/CVE-2022-1201)
- [CVE-2022-1427](https://nvd.nist.gov/vuln/detail/CVE-2022-1427)
## Unaffected CVEs
Following CVEs do not cause problems in this release. They are fixed in the later release.
- [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-0717](https://nvd.nist.gov/vuln/detail/CVE-2022-0817)
- [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)
+3 -3
View File
@@ -57,7 +57,7 @@ MRB_BEGIN_DECL
/*
* Patch level string. (optional)
*/
#define MRUBY_PATCHLEVEL_STR "RC2"
#define MRUBY_PATCHLEVEL_STR ""
#ifndef MRUBY_PATCHLEVEL_STR
# if MRUBY_PATCHLEVEL < 0
@@ -85,12 +85,12 @@ MRB_BEGIN_DECL
/*
* Release month.
*/
#define MRUBY_RELEASE_MONTH 3
#define MRUBY_RELEASE_MONTH 5
/*
* Release day.
*/
#define MRUBY_RELEASE_DAY 31
#define MRUBY_RELEASE_DAY 12
/*
* Release date as a string.
+13 -12
View File
@@ -1603,7 +1603,7 @@ gen_hash(codegen_scope *s, node *tree, int val, int limit)
while (tree) {
if (nint(tree->car->car->car) == NODE_KW_REST_ARGS) {
if (len > 0) {
if (val && len > 0) {
pop_n(len*2);
if (!update) {
genop_2(s, OP_HASH, cursp(), len);
@@ -1615,7 +1615,7 @@ gen_hash(codegen_scope *s, node *tree, int val, int limit)
push();
}
codegen(s, tree->car->cdr, val);
if (len > 0 || update) {
if (val && (len > 0 || update)) {
pop(); pop();
genop_1(s, OP_HASHCAT, cursp());
push();
@@ -1644,14 +1644,13 @@ gen_hash(codegen_scope *s, node *tree, int val, int limit)
}
}
if (update) {
if (len > 0) {
if (val && len > 0) {
pop_n(len*2+1);
genop_2(s, OP_HASHADD, cursp(), len);
push();
}
return -1; /* variable length */
}
if (update) return -1;
return len;
}
@@ -2861,19 +2860,20 @@ codegen(codegen_scope *s, node *tree, int val)
if (tree->cdr->cdr) {
codegen(s, tree->cdr->cdr, VAL);
}
else if (!s2) {/* super at top-level */
push(); /* no need to push block */
}
else if (s2) gen_blkmove(s, s2->ainfo, lv);
else {
gen_blkmove(s, s2->ainfo, lv);
genop_1(s, OP_LOADNIL, cursp());
push();
}
st++;
}
else {
if (!s2) push();
else gen_blkmove(s, s2->ainfo, lv);
st++;
if (s2) gen_blkmove(s, s2->ainfo, lv);
else {
genop_1(s, OP_LOADNIL, cursp());
push();
}
}
st++;
pop_n(st+1);
genop_2(s, OP_SUPER, cursp(), n);
if (val) push();
@@ -3125,6 +3125,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen_error(s, "no anonymous block argument");
}
gen_move(s, cursp(), idx, val);
if (val) push();
}
else {
codegen(s, tree, val);
+13 -6
View File
@@ -208,15 +208,22 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
if (!c->ci->proc) {
mrb_raise(mrb, E_FIBER_ERROR, "double resume (current)");
}
mrb_stack_extend(mrb, len+2); /* for receiver and (optional) block */
b = c->stbase+1;
e = b + len;
while (b<e) {
*b++ = *a++;
}
if (vmexec) {
c->ci--; /* pop dummy callinfo */
}
if (len >= 15) {
mrb_stack_extend(mrb, 3); /* for receiver, args and (optional) block */
c->stbase[1] = mrb_ary_new_from_values(mrb, len, a);
len = 15;
}
else {
mrb_stack_extend(mrb, len+2); /* for receiver and (optional) block */
b = c->stbase+1;
e = b + len;
while (b<e) {
*b++ = *a++;
}
}
c->cibase->n = len;
value = c->stbase[0] = MRB_PROC_ENV(c->cibase->proc)->stack[0];
}
+2
View File
@@ -357,6 +357,7 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o)
{
struct RClass *sc, *c;
mrb_assert(o->c);
if (o->c->tt == MRB_TT_SCLASS) return;
sc = MRB_OBJ_ALLOC(mrb, MRB_TT_SCLASS, mrb->class_class);
sc->flags |= MRB_FL_CLASS_IS_INHERITED;
@@ -1682,6 +1683,7 @@ mrb_singleton_class_ptr(mrb_state *mrb, mrb_value v)
break;
}
obj = mrb_basic_ptr(v);
if (obj->c == NULL) return NULL;
prepare_singleton_class(mrb, obj);
return obj->c;
}
+62 -29
View File
@@ -59,7 +59,7 @@ str_to_double(mrb_state *mrb, const char *p)
#endif
static mrb_bool
read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags, mrb_irep **irepp)
read_irep_record_1(mrb_state *mrb, const uint8_t *bin, const uint8_t *end, size_t *len, uint8_t flags, mrb_irep **irepp)
{
int i;
const uint8_t *src = bin;
@@ -102,6 +102,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
if (SIZE_ERROR_MUL(irep->ilen, sizeof(mrb_code))) {
return FALSE;
}
if (src + data_len > end) return FALSE;
if ((flags & FLAG_SRC_MALLOC) == 0) {
irep->iseq = (mrb_code*)src;
irep->flags |= MRB_ISEQ_NO_FREE;
@@ -117,6 +118,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
/* POOL BLOCK */
plen = bin_to_uint16(src); /* number of pool */
src += sizeof(uint16_t);
if (src > end) return FALSE;
if (plen > 0) {
if (SIZE_ERROR_MUL(plen, sizeof(mrb_value))) {
return FALSE;
@@ -130,6 +132,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
switch (tt) { /* pool data */
case IREP_TT_INT32:
{
if (src + sizeof(uint32_t) > end) return FALSE;
mrb_int v = (int32_t)bin_to_uint32(src);
src += sizeof(uint32_t);
#ifdef MRB_64BIT
@@ -144,6 +147,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
case IREP_TT_INT64:
#ifdef MRB_INT64
{
if (src + sizeof(uint32_t)*2 > end) return FALSE;
uint64_t i64 = bin_to_uint32(src);
src += sizeof(uint32_t);
i64 <<= 32;
@@ -160,6 +164,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
case IREP_TT_BIGINT:
pool_data_len = bin_to_uint8(src); /* pool data length */
src += sizeof(uint8_t);
if (src + pool_data_len > end) return FALSE;
{
char *p;
pool[i].tt = IREP_TT_BIGINT;
@@ -172,6 +177,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
case IREP_TT_FLOAT:
#ifndef MRB_NO_FLOAT
if (src + sizeof(double) > end) return FALSE;
pool[i].tt = tt;
pool[i].u.f = str_to_double(mrb, (const char*)src);
src += sizeof(double);
@@ -183,6 +189,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
case IREP_TT_STR:
pool_data_len = bin_to_uint16(src); /* pool data length */
src += sizeof(uint16_t);
if (src + pool_data_len > end) return FALSE;
if (st) {
pool[i].tt = (pool_data_len<<2) | IREP_TT_SSTR;
pool[i].u.str = (const char*)src;
@@ -208,6 +215,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
/* SYMS BLOCK */
irep->slen = bin_to_uint16(src); /* syms length */
src += sizeof(uint16_t);
if (src > end) return FALSE;
if (irep->slen > 0) {
if (SIZE_ERROR_MUL(irep->slen, sizeof(mrb_sym))) {
return FALSE;
@@ -223,6 +231,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
continue;
}
if (src + snl > end) return FALSE;
if (flags & FLAG_SRC_MALLOC) {
syms[i] = mrb_intern(mrb, (char *)src, snl);
}
@@ -242,10 +251,10 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
}
static mrb_bool
read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags, mrb_irep **irepp)
read_irep_record(mrb_state *mrb, const uint8_t *bin, const uint8_t *end, size_t *len, uint8_t flags, mrb_irep **irepp)
{
int ai = mrb_gc_arena_save(mrb);
mrb_bool readsuccess = read_irep_record_1(mrb, bin, len, flags, irepp);
mrb_bool readsuccess = read_irep_record_1(mrb, bin, end, len, flags, irepp);
mrb_irep **reps;
int i;
@@ -261,7 +270,7 @@ read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags,
for (i=0; i<(*irepp)->rlen; i++) {
size_t rlen;
readsuccess = read_irep_record(mrb, bin, &rlen, flags, &reps[i]);
readsuccess = read_irep_record(mrb, bin, end, &rlen, flags, &reps[i]);
mrb_gc_arena_restore(mrb, ai);
if (!readsuccess) {
return FALSE;
@@ -274,10 +283,9 @@ read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags,
}
static mrb_irep*
read_section_irep(mrb_state *mrb, const uint8_t *bin, uint8_t flags, struct RProc **proc)
read_section_irep(mrb_state *mrb, const uint8_t *bin, size_t size, uint8_t flags, struct RProc **proc)
{
size_t len;
if (size < sizeof(struct rite_section_irep_header)) return NULL;
/*
* This proc object keeps all the data in progress to avoid memory leaks
* if something goes wrong while reading irep.
@@ -285,8 +293,9 @@ read_section_irep(mrb_state *mrb, const uint8_t *bin, uint8_t flags, struct RPro
*proc = mrb_proc_new(mrb, NULL);
mrb_irep **irepp = (mrb_irep**)&(*proc)->body.irep;
size_t len;
bin += sizeof(struct rite_section_irep_header);
if (read_irep_record(mrb, bin, &len, flags, irepp)) {
if (read_irep_record(mrb, bin, bin+size, &len, flags, irepp)) {
return *irepp;
}
else {
@@ -295,7 +304,7 @@ read_section_irep(mrb_state *mrb, const uint8_t *bin, uint8_t flags, struct RPro
}
static int
read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *record_len, const mrb_sym *filenames, size_t filenames_len)
read_debug_record(mrb_state *mrb, const uint8_t *start, const uint8_t *end, mrb_irep* irep, size_t *record_len, const mrb_sym *filenames, size_t filenames_len)
{
const uint8_t *bin = start;
ptrdiff_t diff;
@@ -313,13 +322,15 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *
bin += sizeof(uint32_t);
debug->flen = bin_to_uint16(bin);
debug->files = (mrb_irep_debug_info_file**)mrb_calloc(mrb, irep->debug_info->flen, sizeof(mrb_irep_debug_info*));
bin += sizeof(uint16_t);
if (bin > end) return MRB_DUMP_GENERAL_FAILURE;
debug->files = (mrb_irep_debug_info_file**)mrb_calloc(mrb, irep->debug_info->flen, sizeof(mrb_irep_debug_info*));
for (f_idx = 0; f_idx < debug->flen; ++f_idx) {
mrb_irep_debug_info_file *file;
uint16_t filename_idx;
if (bin > end) return MRB_DUMP_GENERAL_FAILURE;
file = (mrb_irep_debug_info_file *)mrb_calloc(mrb, 1, sizeof(*file));
debug->files[f_idx] = file;
@@ -338,9 +349,10 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *
bin += sizeof(uint8_t);
switch (file->line_type) {
case mrb_debug_line_ary: {
uint32_t l;
size_t l = sizeof(uint16_t) * (size_t)file->line_entry_count;
file->lines.ary = (uint16_t *)mrb_malloc(mrb, sizeof(uint16_t) * (size_t)(file->line_entry_count));
if (bin + l > end) return MRB_DUMP_GENERAL_FAILURE;
file->lines.ary = (uint16_t *)mrb_malloc(mrb, l);
for (l = 0; l < file->line_entry_count; ++l) {
file->lines.ary[l] = bin_to_uint16(bin);
bin += sizeof(uint16_t);
@@ -348,11 +360,12 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *
} break;
case mrb_debug_line_flat_map: {
uint32_t l;
size_t c = (size_t)file->line_entry_count;
size_t n = sizeof(mrb_irep_debug_info_line);
file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_calloc(
mrb, (size_t)(file->line_entry_count), sizeof(mrb_irep_debug_info_line));
for (l = 0; l < file->line_entry_count; ++l) {
if (bin + c*n > end) return MRB_DUMP_GENERAL_FAILURE;
file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_calloc(mrb, c, n);
for (size_t l = 0; l < file->line_entry_count; ++l) {
file->lines.flat_map[l].start_pos = bin_to_uint32(bin);
bin += sizeof(uint32_t);
file->lines.flat_map[l].line = bin_to_uint16(bin);
@@ -361,7 +374,10 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *
} break;
case mrb_debug_line_packed_map: {
file->lines.packed_map = (uint8_t*)mrb_calloc(mrb, 1, (size_t)file->line_entry_count);
size_t l = (size_t)file->line_entry_count;
if (bin + l > end) return MRB_DUMP_GENERAL_FAILURE;
file->lines.packed_map = (uint8_t*)mrb_calloc(mrb, 1, l);
memcpy(file->lines.packed_map, bin, file->line_entry_count);
bin += file->line_entry_count;
} break;
@@ -381,7 +397,7 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *
size_t len;
int ret;
ret = read_debug_record(mrb, bin, (mrb_irep*)irep->reps[i], &len, filenames, filenames_len);
ret = read_debug_record(mrb, bin, end, (mrb_irep*)irep->reps[i], &len, filenames, filenames_len);
if (ret != MRB_DUMP_OK) return ret;
bin += len;
}
@@ -394,9 +410,10 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *
}
static int
read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t flags)
read_section_debug(mrb_state *mrb, const uint8_t *start, size_t size, mrb_irep *irep, uint8_t flags)
{
const uint8_t *bin;
const uint8_t *end = start + size;
ptrdiff_t diff;
struct rite_section_debug_header *header;
uint16_t i;
@@ -412,11 +429,16 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t
filenames_len = bin_to_uint16(bin);
bin += sizeof(uint16_t);
if (bin > end) return MRB_DUMP_GENERAL_FAILURE;
filenames_obj = mrb_str_new(mrb, NULL, sizeof(mrb_sym) * (size_t)filenames_len);
filenames = (mrb_sym*)RSTRING_PTR(filenames_obj);
for (i = 0; i < filenames_len; ++i) {
uint16_t f_len = bin_to_uint16(bin);
bin += sizeof(uint16_t);
if (bin + f_len > end) {
result = MRB_DUMP_GENERAL_FAILURE;
goto debug_exit;
}
if (flags & FLAG_SRC_MALLOC) {
filenames[i] = mrb_intern(mrb, (const char *)bin, (size_t)f_len);
}
@@ -426,7 +448,7 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t
bin += f_len;
}
result = read_debug_record(mrb, bin, irep, &len, filenames, filenames_len);
result = read_debug_record(mrb, bin, end, irep, &len, filenames, filenames_len);
if (result != MRB_DUMP_OK) goto debug_exit;
bin += len;
@@ -449,6 +471,7 @@ read_lv_record(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, size_t *rec
ptrdiff_t diff;
int i;
if (irep->nlocals == 0) return MRB_DUMP_GENERAL_FAILURE;
irep->lv = lv = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (irep->nlocals - 1));
for (i = 0; i + 1 < irep->nlocals; ++i) {
@@ -482,9 +505,10 @@ read_lv_record(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, size_t *rec
}
static int
read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t flags)
read_section_lv(mrb_state *mrb, const uint8_t *start, size_t size, mrb_irep *irep, uint8_t flags)
{
const uint8_t *bin;
const uint8_t *end = start + size;
ptrdiff_t diff;
struct rite_section_lv_header const *header;
uint32_t i;
@@ -502,12 +526,13 @@ read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t fl
syms_len = bin_to_uint32(bin);
bin += sizeof(uint32_t);
if (bin > end) return MRB_DUMP_READ_FAULT;
syms_obj = mrb_str_new(mrb, NULL, sizeof(mrb_sym) * (size_t)syms_len);
syms = (mrb_sym*)RSTRING_PTR(syms_obj);
for (i = 0; i < syms_len; ++i) {
uint16_t const str_len = bin_to_uint16(bin);
bin += sizeof(uint16_t);
if (bin > end) return MRB_DUMP_READ_FAULT;
syms[i] = intern_func(mrb, (const char*)bin, str_len);
bin += str_len;
}
@@ -577,28 +602,36 @@ read_irep(mrb_state *mrb, const uint8_t *bin, size_t bufsize, uint8_t flags)
}
bin += sizeof(struct rite_binary_header);
do {
bin_size -= sizeof(struct rite_binary_header);
while (bin_size > sizeof(struct rite_section_header)) {
section_header = (const struct rite_section_header *)bin;
uint32_t section_size = bin_to_uint32(section_header->section_size);
if (bin_size < section_size) return NULL;
if (memcmp(section_header->section_ident, RITE_SECTION_IREP_IDENT, sizeof(section_header->section_ident)) == 0) {
irep = read_section_irep(mrb, bin, flags, &proc);
irep = read_section_irep(mrb, bin, bin_size, flags, &proc);
if (!irep) return NULL;
}
else if (memcmp(section_header->section_ident, RITE_SECTION_DEBUG_IDENT, sizeof(section_header->section_ident)) == 0) {
if (!irep) return NULL; /* corrupted data */
result = read_section_debug(mrb, bin, irep, flags);
result = read_section_debug(mrb, bin, bin_size, irep, flags);
if (result < MRB_DUMP_OK) {
return NULL;
}
}
else if (memcmp(section_header->section_ident, RITE_SECTION_LV_IDENT, sizeof(section_header->section_ident)) == 0) {
if (!irep) return NULL;
result = read_section_lv(mrb, bin, irep, flags);
result = read_section_lv(mrb, bin, bin_size, irep, flags);
if (result < MRB_DUMP_OK) {
return NULL;
}
}
bin += bin_to_uint32(section_header->section_size);
} while (memcmp(section_header->section_ident, RITE_BINARY_EOF, sizeof(section_header->section_ident)) != 0);
else if (memcmp(section_header->section_ident, RITE_BINARY_EOF, sizeof(section_header->section_ident)) != 0) {
break;
}
bin += section_size;
bin_size -= section_size;
}
return proc;
}
@@ -608,7 +641,7 @@ mrb_proc_read_irep(mrb_state *mrb, const uint8_t *bin)
{
uint8_t flags = mrb_ro_data_p((char*)bin) ? FLAG_SRC_STATIC : FLAG_SRC_MALLOC;
return read_irep(mrb, bin, (size_t)-1, flags);
return read_irep(mrb, bin, (size_t)UINT32_MAX, flags);
}
DEFINE_READ_IREP_FUNC(
+19 -13
View File
@@ -689,9 +689,11 @@ mrb_f_send(mrb_state *mrb, mrb_value self)
regs = mrb->c->ci->stack+1;
if (n == 0) {
argnum_error:
mrb_argnum_error(mrb, 0, 1, -1);
}
else if (n == 15) {
if (RARRAY_LEN(regs[0]) == 0) goto argnum_error;
name = mrb_obj_to_sym(mrb, RARRAY_PTR(regs[0])[0]);
}
else {
@@ -1359,14 +1361,16 @@ RETRY_TRY_BLOCK:
regs[a] = mrb_ary_entry(va, mrb_integer(vb));
break;
case MRB_TT_HASH:
regs[a] = mrb_hash_get(mrb, va, vb);
va = mrb_hash_get(mrb, va, vb);
regs[a] = va;
break;
case MRB_TT_STRING:
switch (mrb_type(vb)) {
case MRB_TT_INTEGER:
case MRB_TT_STRING:
case MRB_TT_RANGE:
regs[a] = mrb_str_aref(mrb, va, vb, mrb_undef_value());
va = mrb_str_aref(mrb, va, vb, mrb_undef_value());
regs[a] = va;
break;
default:
goto getidx_fallback;
@@ -1388,7 +1392,8 @@ RETRY_TRY_BLOCK:
}
CASE(OP_GETCONST, BB) {
regs[a] = mrb_vm_const_get(mrb, syms[b]);
mrb_value v = mrb_vm_const_get(mrb, syms[b]);
regs[a] = v;
NEXT;
}
@@ -1398,7 +1403,8 @@ RETRY_TRY_BLOCK:
}
CASE(OP_GETMCNST, BB) {
regs[a] = mrb_const_get(mrb, regs[a], syms[b]);
mrb_value v = mrb_const_get(mrb, regs[a], syms[b]);
regs[a] = v;
NEXT;
}
@@ -1747,12 +1753,9 @@ RETRY_TRY_BLOCK:
mrb_exc_set(mrb, exc);
goto L_RAISE;
}
if (target_class->flags & MRB_FL_CLASS_IS_PREPENDED) {
if ((target_class->flags & MRB_FL_CLASS_IS_PREPENDED) || target_class->tt == MRB_TT_MODULE) {
target_class = mrb_vm_ci_target_class(ci);
}
else if (target_class->tt == MRB_TT_MODULE) {
target_class = mrb_vm_ci_target_class(ci);
if (target_class->tt != MRB_TT_ICLASS) {
if (!target_class || target_class->tt != MRB_TT_ICLASS) {
goto super_typeerror;
}
}
@@ -2025,14 +2028,15 @@ RETRY_TRY_BLOCK:
CASE(OP_KARG, BB) {
mrb_value k = mrb_symbol_value(syms[b]);
mrb_int kidx = mrb_ci_kidx(mrb->c->ci);
mrb_value kdict;
mrb_value kdict, v;
if (kidx < 0 || !mrb_hash_p(kdict=regs[kidx]) || !mrb_hash_key_p(mrb, kdict, k)) {
mrb_value str = mrb_format(mrb, "missing keyword: %v", k);
mrb_exc_set(mrb, mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str));
goto L_RAISE;
}
regs[a] = mrb_hash_get(mrb, kdict, k);
v = mrb_hash_get(mrb, kdict, k);
regs[a] = v;
mrb_hash_delete_key(mrb, kdict, k);
NEXT;
}
@@ -2824,13 +2828,15 @@ RETRY_TRY_BLOCK:
}
CASE(OP_RANGE_INC, B) {
regs[a] = mrb_range_new(mrb, regs[a], regs[a+1], FALSE);
mrb_value v = mrb_range_new(mrb, regs[a], regs[a+1], FALSE);
regs[a] = v;
mrb_gc_arena_restore(mrb, ai);
NEXT;
}
CASE(OP_RANGE_EXC, B) {
regs[a] = mrb_range_new(mrb, regs[a], regs[a+1], TRUE);
mrb_value v = mrb_range_new(mrb, regs[a], regs[a+1], TRUE);
regs[a] = v;
mrb_gc_arena_restore(mrb, ai);
NEXT;
}