summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mrbgems/mruby-compiler/core/parse.y102
-rw-r--r--src/array.c15
-rw-r--r--src/proc.c2
-rw-r--r--test/t/array.rb13
-rw-r--r--test/t/class.rb12
-rw-r--r--test/t/hash.rb7
-rw-r--r--test/t/proc.rb16
-rw-r--r--test/t/syntax.rb20
-rw-r--r--test/t/unicode.rb32
9 files changed, 157 insertions, 62 deletions
diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y
index ef522d239..bf893fb37 100644
--- a/mrbgems/mruby-compiler/core/parse.y
+++ b/mrbgems/mruby-compiler/core/parse.y
@@ -3752,6 +3752,44 @@ scan_hex(const int *start, int len, int *retlen)
return retval;
}
+static int32_t
+read_escape_unicode(parser_state *p, int limit)
+{
+ int32_t c;
+ int buf[9];
+ int i;
+
+ /* Look for opening brace */
+ i = 0;
+ buf[0] = nextc(p);
+ if (buf[0] < 0) goto eof;
+ if (ISXDIGIT(buf[0])) {
+ /* \uxxxx form */
+ for (i=1; i<limit; i++) {
+ buf[i] = nextc(p);
+ if (buf[i] < 0) goto eof;
+ if (!ISXDIGIT(buf[i])) {
+ pushback(p, buf[i]);
+ break;
+ }
+ }
+ }
+ else {
+ pushback(p, buf[0]);
+ }
+ c = scan_hex(buf, i, &i);
+ if (i == 0) {
+ eof:
+ yyerror(p, "Invalid escape character syntax");
+ return -1;
+ }
+ if (c < 0 || c > 0x10FFFF || (c & 0xFFFFF800) == 0xD800) {
+ yyerror(p, "Invalid Unicode code point");
+ return -1;
+ }
+ return c;
+}
+
/* Return negative to indicate Unicode code point */
static int32_t
read_escape(parser_state *p)
@@ -3824,53 +3862,17 @@ read_escape(parser_state *p)
return c;
case 'u': /* Unicode */
- {
- int buf[9];
- int i;
-
- /* Look for opening brace */
- i = 0;
- buf[0] = nextc(p);
- if (buf[0] < 0) goto eof;
- if (buf[0] == '{') {
+ if (peek(p, '{')) {
/* \u{xxxxxxxx} form */
- for (i=0; i<9; i++) {
- buf[i] = nextc(p);
- if (buf[i] < 0) goto eof;
- if (buf[i] == '}') {
- break;
- }
- else if (!ISXDIGIT(buf[i])) {
- yyerror(p, "Invalid escape character syntax");
- pushback(p, buf[i]);
- return 0;
- }
- }
- }
- else if (ISXDIGIT(buf[0])) {
- /* \uxxxx form */
- for (i=1; i<4; i++) {
- buf[i] = nextc(p);
- if (buf[i] < 0) goto eof;
- if (!ISXDIGIT(buf[i])) {
- pushback(p, buf[i]);
- break;
- }
- }
+ nextc(p);
+ c = read_escape_unicode(p, 8);
+ if (c < 0) return 0;
+ if (nextc(p) != '}') goto eof;
}
else {
- pushback(p, buf[0]);
- }
- c = scan_hex(buf, i, &i);
- if (i == 0) {
- yyerror(p, "Invalid escape character syntax");
- return 0;
+ c = read_escape_unicode(p, 4);
+ if (c < 0) return 0;
}
- if (c < 0 || c > 0x10FFFF || (c & 0xFFFFF800) == 0xD800) {
- yyerror(p, "Invalid Unicode code point");
- return 0;
- }
- }
return -c;
case 'b':/* backspace */
@@ -3993,6 +3995,20 @@ parse_string(parser_state *p)
tokadd(p, '\\');
tokadd(p, c);
}
+ else if (c == 'u' && peek(p, '{')) {
+ /* \u{xxxx xxxx xxxx} form */
+ nextc(p);
+ while (1) {
+ do c = nextc(p); while (ISSPACE(c));
+ if (c == '}') break;
+ pushback(p, c);
+ c = read_escape_unicode(p, 8);
+ if (c < 0) break;
+ tokadd(p, -c);
+ }
+ if (hinf)
+ hinf->line_head = FALSE;
+ }
else {
pushback(p, c);
tokadd(p, read_escape(p));
diff --git a/src/array.c b/src/array.c
index 8902f2dda..f6599bd5b 100644
--- a/src/array.c
+++ b/src/array.c
@@ -173,11 +173,13 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, mrb_int len)
capa = ARY_DEFAULT_LEN;
}
while (capa < len) {
- capa *= 2;
+ if (capa <= ARY_MAX_SIZE / 2) {
+ capa *= 2;
+ } else {
+ capa = ARY_MAX_SIZE;
+ }
}
- if (capa > ARY_MAX_SIZE) capa = ARY_MAX_SIZE; /* len <= capa <= ARY_MAX_SIZE */
-
if (capa > a->aux.capa) {
mrb_value *expanded_ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa);
@@ -244,10 +246,12 @@ mrb_ary_s_create(mrb_state *mrb, mrb_value self)
static void
ary_concat(mrb_state *mrb, struct RArray *a, struct RArray *a2)
{
+ mrb_int len;
+
if (a2->len > ARY_MAX_SIZE - a->len) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
}
- mrb_int len = a->len + a2->len;
+ len = a->len + a2->len;
ary_modify(mrb, a);
if (a->aux.capa < len) {
@@ -501,6 +505,9 @@ mrb_ary_unshift_m(mrb_state *mrb, mrb_value self)
mrb_int len;
mrb_get_args(mrb, "*", &vals, &len);
+ if (len > ARY_MAX_SIZE - a->len) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
+ }
if (ARY_SHARED_P(a)
&& a->aux.shared->refcnt == 1 /* shared only referenced from this array */
&& a->ptr - a->aux.shared->ptr >= len) /* there's room for unshifted item */ {
diff --git a/src/proc.c b/src/proc.c
index 4f770932b..470547094 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -140,7 +140,7 @@ mrb_proc_copy(struct RProc *a, struct RProc *b)
{
a->flags = b->flags;
a->body = b->body;
- if (!MRB_PROC_CFUNC_P(a)) {
+ if (!MRB_PROC_CFUNC_P(a) && a->body.irep) {
a->body.irep->refcnt++;
}
a->target_class = b->target_class;
diff --git a/test/t/array.rb b/test/t/array.rb
index 3c5211591..9cc2f64ad 100644
--- a/test/t/array.rb
+++ b/test/t/array.rb
@@ -82,6 +82,14 @@ assert('Array#[]=', '15.2.12.5.5') do
a = [1,2,3,4,5]
a[2...4] = 6
assert_equal([1,2,6,5], a)
+
+ # passing self (#3274)
+ a = [1,2,3]
+ a[1,0] = a
+ assert_equal([1,1,2,3,2,3], a)
+ a = [1,2,3]
+ a[-1,0] = a
+ assert_equal([1,2,1,2,3,3], a)
end
assert('Array#clear', '15.2.12.5.6') do
@@ -98,6 +106,11 @@ end
assert('Array#concat', '15.2.12.5.8') do
assert_equal([1,2,3,4], [1, 2].concat([3, 4]))
+
+ # passing self (#3302)
+ a = [1,2,3]
+ a.concat(a)
+ assert_equal([1,2,3,1,2,3], a)
end
assert('Array#delete_at', '15.2.12.5.9') do
diff --git a/test/t/class.rb b/test/t/class.rb
index 597999d3e..605b7ec40 100644
--- a/test/t/class.rb
+++ b/test/t/class.rb
@@ -397,6 +397,18 @@ assert('class variable in module and class << self style class method') do
assert_equal("value", ClassVariableInModuleTest.class_variable)
end
+assert('overriding class variable with a module (#3235)') do
+ module ModuleWithCVar
+ @@class_variable = 1
+ end
+ class CVarOverrideTest
+ @@class_variable = 2
+ include ModuleWithCVar
+
+ assert_equal(1, @@class_variable)
+ end
+end
+
assert('class with non-class/module outer raises TypeError') do
assert_raise(TypeError) { class 0::C1; end }
assert_raise(TypeError) { class []::C2; end }
diff --git a/test/t/hash.rb b/test/t/hash.rb
index c8d7a70ef..b455812cf 100644
--- a/test/t/hash.rb
+++ b/test/t/hash.rb
@@ -16,6 +16,13 @@ assert('Hash#[]', '15.2.13.4.2') do
a = { 'abc' => 'abc' }
assert_equal 'abc', a['abc']
+
+ # Hash#[] should call #default (#3272)
+ hash = {}
+ def hash.default(k); self[k] = 1; end
+ hash[:foo] += 1
+
+ assert_equal 2, hash[:foo]
end
assert('Hash#[]=', '15.2.13.4.3') do
diff --git a/test/t/proc.rb b/test/t/proc.rb
index bc9821f7c..29530e8dd 100644
--- a/test/t/proc.rb
+++ b/test/t/proc.rb
@@ -163,3 +163,19 @@ assert('&obj call to_proc if defined') do
assert_raise(TypeError){ mock(&(Object.new)) }
end
+
+assert('initialize_copy works when initialize is removed') do
+ begin
+ Proc.alias_method(:old_initialize, :initialize)
+ Proc.remove_method(:initialize)
+
+ a = Proc.new {}
+ b = Proc.new {}
+ assert_nothing_raised do
+ a.initialize_copy(b)
+ end
+ ensure
+ Proc.alias_method(:initialize, :old_initialize)
+ Proc.remove_method(:old_initialize)
+ end
+end
diff --git a/test/t/syntax.rb b/test/t/syntax.rb
index 3bc68484b..461f5430b 100644
--- a/test/t/syntax.rb
+++ b/test/t/syntax.rb
@@ -47,6 +47,19 @@ assert('yield', '11.3.5') do
end
end
+assert('redo in a for loop (#3275)') do
+ sum = 0
+ for i in 1..10
+ sum += i
+ i -= 1
+ if i > 0
+ redo
+ end
+ end
+
+ assert_equal 220, sum
+end
+
assert('Abbreviated variable assignment', '11.4.2.3.2') do
a ||= 1
b &&= 1
@@ -255,6 +268,13 @@ assert('multiple assignment (nosplat array rhs)') do
assert_equal 2, g
end
+assert('multiple assignment (empty array rhs #3236, #3239)') do
+ a,b,*c = []; assert_equal [nil, nil, []], [a, b, c]
+ a,b,*c = [1]; assert_equal [1, nil, []], [a, b, c]
+ a,b,*c = [nil]; assert_equal [nil,nil, []], [a, b, c]
+ a,b,*c = [[]]; assert_equal [[], nil, []], [a, b, c]
+end
+
assert('Return values of case statements') do
a = [] << case 1
when 3 then 2
diff --git a/test/t/unicode.rb b/test/t/unicode.rb
index 7edd65ef2..8622ae08a 100644
--- a/test/t/unicode.rb
+++ b/test/t/unicode.rb
@@ -2,34 +2,38 @@
assert('bare \u notation test') do
# Mininum and maximum one byte characters
- assert_equal("\u0000", "\x00")
- assert_equal("\u007F", "\x7F")
+ assert_equal("\x00", "\u0000")
+ assert_equal("\x7F", "\u007F")
# Mininum and maximum two byte characters
- assert_equal("\u0080", "\xC2\x80")
- assert_equal("\u07FF", "\xDF\xBF")
+ assert_equal("\xC2\x80", "\u0080")
+ assert_equal("\xDF\xBF", "\u07FF")
# Mininum and maximum three byte characters
- assert_equal("\u0800", "\xE0\xA0\x80")
- assert_equal("\uFFFF", "\xEF\xBF\xBF")
+ assert_equal("\xE0\xA0\x80", "\u0800")
+ assert_equal("\xEF\xBF\xBF", "\uFFFF")
# Four byte characters require the \U notation
end
assert('braced \u notation test') do
# Mininum and maximum one byte characters
- assert_equal("\u{0000}", "\x00")
- assert_equal("\u{007F}", "\x7F")
+ assert_equal("\x00", "\u{0000}")
+ assert_equal("\x7F", "\u{007F}")
# Mininum and maximum two byte characters
- assert_equal("\u{0080}", "\xC2\x80")
- assert_equal("\u{07FF}", "\xDF\xBF")
+ assert_equal("\xC2\x80", "\u{0080}")
+ assert_equal("\xDF\xBF", "\u{07FF}")
# Mininum and maximum three byte characters
- assert_equal("\u{0800}", "\xE0\xA0\x80")
- assert_equal("\u{FFFF}", "\xEF\xBF\xBF")
+ assert_equal("\xE0\xA0\x80", "\u{0800}")
+ assert_equal("\xEF\xBF\xBF", "\u{FFFF}")
# Mininum and maximum four byte characters
- assert_equal("\u{10000}", "\xF0\x90\x80\x80")
- assert_equal("\u{10FFFF}", "\xF4\x8F\xBF\xBF")
+ assert_equal("\xF0\x90\x80\x80", "\u{10000}")
+ assert_equal("\xF4\x8F\xBF\xBF", "\u{10FFFF}")
+end
+
+assert('braced multiple \u notation test') do
+ assert_equal("ABC", "\u{41 42 43}")
end