From efe4f30b3982e8ff85a9142933955d6fa0bdebc7 Mon Sep 17 00:00:00 2001 From: ksss Date: Wed, 12 Oct 2016 22:05:14 +0900 Subject: Module#define_method supports proc argument --- test/t/module.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'test') diff --git a/test/t/module.rb b/test/t/module.rb index 4bde20fbe..6b0632414 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -494,6 +494,18 @@ end # Not ISO specified +assert('Module#define_method') do + c = Class.new { + define_method(:m1) { :ok } + define_method(:m2, Proc.new { :ok }) + } + assert_equal c.new.m1, :ok + assert_equal c.new.m2, :ok + assert_raise(TypeError) do + Class.new { define_method(:n1, nil) } + end +end + # @!group prepend assert('Module#prepend') do module M0 -- cgit v1.2.3 From 617050450e66bf0689c621bf72abb6a162309ea6 Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Thu, 10 Nov 2016 13:17:59 +0100 Subject: test/assert.rb should not use puts --- test/assert.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/assert.rb b/test/assert.rb index e8368c64c..f565652b1 100644 --- a/test/assert.rb +++ b/test/assert.rb @@ -213,7 +213,7 @@ def report() t_print("\n") $asserts.each do |msg| - puts msg + t_print "#{msg}\n" end $total_test = $ok_test+$ko_test+$kill_test -- cgit v1.2.3 From 1f554ff8540d61e30d0e649bf80c0ecd27b40ad6 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 16 Nov 2016 02:10:44 +0900 Subject: Fixed rindex calling into mrb_equal bug Fixed by Alex Snaps and reported by Mathieu Leduc-Hamel, both from shopify.com. Thank you! --- src/array.c | 5 ++++- test/t/array.rb | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/src/array.c b/src/array.c index e8882b7a3..5a319d809 100644 --- a/src/array.c +++ b/src/array.c @@ -868,13 +868,16 @@ static mrb_value mrb_ary_rindex_m(mrb_state *mrb, mrb_value self) { mrb_value obj; - mrb_int i; + mrb_int i, len; mrb_get_args(mrb, "o", &obj); for (i = RARRAY_LEN(self) - 1; i >= 0; i--) { if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) { return mrb_fixnum_value(i); } + if (i > (len = RARRAY_LEN(self))) { + i = len; + } } return mrb_nil_value(); } diff --git a/test/t/array.rb b/test/t/array.rb index 538ea0c3f..d887c117b 100644 --- a/test/t/array.rb +++ b/test/t/array.rb @@ -347,3 +347,15 @@ assert("Array (Longish inline array)") do ary.each {|p| h[p.class] += 1} assert_equal({Array=>200}, h) end + +assert("Array#rindex") do + class Sneaky + def ==(*) + $a.clear + $a.replace([1]) + false + end + end + $a = [2, 3, 4, 5, 6, 7, 8, 9, 10, Sneaky.new] + assert_equal 0, $a.rindex(1) +end -- cgit v1.2.3 From 176d93d72a9322f7f8e41aea0b06a857b7ba23aa Mon Sep 17 00:00:00 2001 From: ksss Date: Thu, 17 Nov 2016 14:57:30 +0900 Subject: Ranges should not rewrite --- src/range.c | 3 +++ test/t/range.rb | 2 ++ 2 files changed, 5 insertions(+) (limited to 'test') diff --git a/src/range.c b/src/range.c index 079a1035e..41b41237c 100644 --- a/src/range.c +++ b/src/range.c @@ -129,6 +129,9 @@ mrb_range_initialize(mrb_state *mrb, mrb_value range) exclusive = FALSE; } /* Ranges are immutable, so that they should be initialized only once. */ + if (mrb_range_ptr(range)->edges) { + mrb_name_error(mrb, mrb_intern_lit(mrb, "initialize"), "`initialize' called twice"); + } range_init(mrb, range, beg, end, exclusive); return range; } diff --git a/test/t/range.rb b/test/t/range.rb index 278b26902..c542c8f06 100644 --- a/test/t/range.rb +++ b/test/t/range.rb @@ -57,6 +57,8 @@ assert('Range#initialize', '15.2.14.4.9') do assert_true a.exclude_end? assert_equal (1..10), b assert_false b.exclude_end? + + assert_raise(NameError) { (0..1).send(:initialize, 1, 3) } end assert('Range#last', '15.2.14.4.10') do -- cgit v1.2.3 From 57900d809f7dac7f450eadd475ad225a6cca39cb Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 17 Nov 2016 18:02:10 +0900 Subject: String#include? does not take integers --- src/string.c | 18 ++++-------------- test/t/string.rb | 2 -- 2 files changed, 4 insertions(+), 16 deletions(-) (limited to 'test') diff --git a/src/string.c b/src/string.c index 8c46da2bf..f8ab9478f 100644 --- a/src/string.c +++ b/src/string.c @@ -1530,22 +1530,12 @@ mrb_str_hash_m(mrb_state *mrb, mrb_value self) static mrb_value mrb_str_include(mrb_state *mrb, mrb_value self) { - mrb_int i; mrb_value str2; - mrb_bool include_p; - - mrb_get_args(mrb, "o", &str2); - if (mrb_fixnum_p(str2)) { - include_p = (memchr(RSTRING_PTR(self), mrb_fixnum(str2), RSTRING_LEN(self)) != NULL); - } - else { - str2 = mrb_str_to_str(mrb, str2); - i = str_index(mrb, self, str2, 0); - - include_p = (i != -1); - } - return mrb_bool_value(include_p); + mrb_get_args(mrb, "S", &str2); + if (str_index(mrb, self, str2, 0) < 0) + return mrb_bool_value(FALSE); + return mrb_bool_value(TRUE); } /* 15.2.10.5.22 */ diff --git a/test/t/string.rb b/test/t/string.rb index fbaada451..e67389b5c 100644 --- a/test/t/string.rb +++ b/test/t/string.rb @@ -381,8 +381,6 @@ assert('String#hash', '15.2.10.5.20') do end assert('String#include?', '15.2.10.5.21') do - assert_true 'abc'.include?(97) - assert_false 'abc'.include?(100) assert_true 'abc'.include?('a') assert_false 'abc'.include?('d') end -- cgit v1.2.3 From 4ef591c89705a9ec10aaf8f323d8f73304c0097a Mon Sep 17 00:00:00 2001 From: ksss Date: Fri, 18 Nov 2016 10:01:03 +0900 Subject: Fix condition of Range#include? --- src/range.c | 2 +- test/t/range.rb | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/src/range.c b/src/range.c index 079a1035e..7b304011a 100644 --- a/src/range.c +++ b/src/range.c @@ -229,7 +229,7 @@ mrb_range_include(mrb_state *mrb, mrb_value range) end = r->edges->end; include_p = r_le(mrb, beg, val) && /* beg <= val */ ((r->excl && r_gt(mrb, end, val)) || /* end > val */ - (r_ge(mrb, end, val))); /* end >= val */ + (!r->excl && r_ge(mrb, end, val))); /* end >= val */ return mrb_bool_value(include_p); } diff --git a/test/t/range.rb b/test/t/range.rb index 278b26902..2ff89de4c 100644 --- a/test/t/range.rb +++ b/test/t/range.rb @@ -43,10 +43,11 @@ assert('Range#first', '15.2.14.4.7') do end assert('Range#include?', '15.2.14.4.8') do - a = (1..10) + assert_true (1..10).include?(10) + assert_false (1..10).include?(11) - assert_true a.include?(5) - assert_false a.include?(20) + assert_true (1...10).include?(9) + assert_false (1...10).include?(10) end assert('Range#initialize', '15.2.14.4.9') do -- cgit v1.2.3 From aaa86a1fd537172ddecdd432d2f44967cd5cdaca Mon Sep 17 00:00:00 2001 From: Yutaka HARA Date: Tue, 22 Nov 2016 16:25:18 +0900 Subject: Fix typo in test --- test/t/literals.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/t/literals.rb b/test/t/literals.rb index 5bf6d6e06..51a37c32d 100644 --- a/test/t/literals.rb +++ b/test/t/literals.rb @@ -26,7 +26,7 @@ assert('Literals Numerical', '8.7.6.2') do assert_equal 10000000, 10_000_000 assert_equal 10, 1_0 # integer with exponent - assert_equal 10.0, 1e1, + assert_equal 10.0, 1e1 assert_equal(0.1, 1e-1) assert_equal 10.0, 1e+1 # float with exponent -- cgit v1.2.3 From fb7776586e4230cdc00077dca6bc6399bc8783f2 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 22 Nov 2016 17:59:25 +0900 Subject: hash value may be overflown from Integer mruby special. --- test/t/array.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/t/array.rb b/test/t/array.rb index d887c117b..3c5211591 100644 --- a/test/t/array.rb +++ b/test/t/array.rb @@ -318,7 +318,8 @@ end assert('Array#hash', '15.2.12.5.35') do a = [ 1, 2, 3 ] - assert_true(a.hash.is_a? Integer) + #assert_true(a.hash.is_a? Integer) + assert_true(a.hash.is_a? Integral) # mruby special assert_equal([1,2].hash, [1,2].hash) end -- cgit v1.2.3 From a8b8abbd826b60b6313baef5635acd41e6d8f716 Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Thu, 24 Nov 2016 12:48:41 +0100 Subject: Fixed float tolerance in tests when MRB_USE_FLOAT is set --- mrbgems/mruby-test/driver.c | 6 ++++++ test/assert.rb | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/mrbgems/mruby-test/driver.c b/mrbgems/mruby-test/driver.c index 7cc5211f0..14e93ff33 100644 --- a/mrbgems/mruby-test/driver.c +++ b/mrbgems/mruby-test/driver.c @@ -94,6 +94,12 @@ mrb_init_test_driver(mrb_state *mrb, mrb_bool verbose) mrb_define_const(mrb, mrbtest, "FIXNUM_MIN", mrb_fixnum_value(MRB_INT_MIN)); mrb_define_const(mrb, mrbtest, "FIXNUM_BIT", mrb_fixnum_value(MRB_INT_BIT)); +#ifdef MRB_USE_FLOAT + mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-6)); +#else + mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-12)); +#endif + if (verbose) { mrb_gv_set(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose"), mrb_true_value()); } diff --git a/test/assert.rb b/test/assert.rb index f565652b1..5617e1e38 100644 --- a/test/assert.rb +++ b/test/assert.rb @@ -232,7 +232,7 @@ end ## # Performs fuzzy check for equality on methods returning floats def check_float(a, b) - tolerance = 1e-12 + tolerance = Mrbtest::FLOAT_TOLERANCE a = a.to_f b = b.to_f if a.finite? and b.finite? -- cgit v1.2.3 From 73bb30c2f4dba7c8da091ec5c5308d6dacf5f52f Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 21 Nov 2016 16:31:47 -0500 Subject: Copy over INSTANCE_TT when duping class --- src/kernel.c | 1 + test/t/kernel.rb | 8 ++++++++ 2 files changed, 9 insertions(+) (limited to 'test') diff --git a/src/kernel.c b/src/kernel.c index 74254e636..c63e05596 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -285,6 +285,7 @@ copy_class(mrb_state *mrb, mrb_value dst, mrb_value src) } dc->mt = kh_copy(mt, mrb, sc->mt); dc->super = sc->super; + MRB_SET_INSTANCE_TT(dc, MRB_INSTANCE_TT(sc)); } static void diff --git a/test/t/kernel.rb b/test/t/kernel.rb index 927166283..d240e59dc 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -221,6 +221,14 @@ assert('Kernel#dup', '15.3.1.3.9') do assert_false c.respond_to?(:test) end +assert('Kernel#dup class') do + assert_nothing_raised do + Array.dup.new(200) + Range.dup.new(2, 3) + String.dup.new("a"*50) + end +end + # Kernel#eval is provided by mruby-eval mrbgem '15.3.1.3.12' assert('Kernel#extend', '15.3.1.3.13') do -- cgit v1.2.3 From 73e4f069becaf69707b990d658b34155f8973508 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Fri, 18 Nov 2016 16:17:40 -0500 Subject: Fix nested empty heredoc causing segfault As reported by https://hackerone.com/jpenalbae --- mrbgems/mruby-compiler/core/codegen.c | 6 +++++- mrbgems/mruby-compiler/core/parse.y | 2 +- test/t/codegen.rb | 10 ++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 test/t/codegen.rb (limited to 'test') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 0c84dd558..13091a6f5 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2285,7 +2285,11 @@ codegen(codegen_scope *s, node *tree, int val) if (val) { node *n = tree; - if (!n) break; + if (!n) { + genop(s, MKOP_A(OP_LOADNIL, cursp())); + push(); + break; + } codegen(s, n->car, VAL); n = n->cdr; while (n) { diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 0ff7d819c..c44669f45 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -6541,7 +6541,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset) case NODE_HEREDOC: printf("NODE_HEREDOC (<<%s):\n", ((parser_heredoc_info*)tree)->term); - mrb_parser_dump(mrb, ((parser_heredoc_info*)tree)->doc, offset+1); + dump_recur(mrb, ((parser_heredoc_info*)tree)->doc, offset+1); break; default: diff --git a/test/t/codegen.rb b/test/t/codegen.rb new file mode 100644 index 000000000..2f44ca247 --- /dev/null +++ b/test/t/codegen.rb @@ -0,0 +1,10 @@ +## +# Codegen tests + +assert('nested empty heredoc') do + _, a = nil, < Date: Thu, 17 Nov 2016 11:12:35 -0500 Subject: Fix segfault on method call with exactly 127 arguments Reported by https://hackerone.com/dkasak --- mrbgems/mruby-compiler/core/codegen.c | 8 +++++--- test/t/codegen.rb | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 test/t/codegen.rb (limited to 'test') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 0c84dd558..a36984dea 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -772,6 +772,8 @@ attrsym(codegen_scope *s, mrb_sym a) return mrb_intern(s->mrb, name2, len+1); } +#define CALL_MAXARGS 127 + static int gen_values(codegen_scope *s, node *t, int val) { @@ -780,7 +782,9 @@ gen_values(codegen_scope *s, node *t, int val) while (t) { is_splat = (intptr_t)t->car->car == NODE_SPLAT; /* splat mode */ - if (n >= 127 || is_splat) { + if ( + n >= CALL_MAXARGS - 1 /* need to subtract one because vm.c expects an array if n == CALL_MAXARGS */ + || is_splat) { if (val) { if (is_splat && n == 0 && (intptr_t)t->car->cdr->car == NODE_ARRAY) { codegen(s, t->car->cdr, VAL); @@ -831,8 +835,6 @@ gen_values(codegen_scope *s, node *t, int val) return n; } -#define CALL_MAXARGS 127 - static void gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) { diff --git a/test/t/codegen.rb b/test/t/codegen.rb new file mode 100644 index 000000000..0690cef06 --- /dev/null +++ b/test/t/codegen.rb @@ -0,0 +1,17 @@ +## +# Codegen tests + +assert('method call with exactly 127 arguments') do + def args_to_ary(*args) + args + end + + assert_equal [0]*127, args_to_ary( + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ) +end -- cgit v1.2.3 From 22f550405449faf5bb424f04a52835376add2ae2 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 14 Nov 2016 17:57:43 -0500 Subject: Fix segfault on remove_method with invalid argument Reported by https://hackerone.com/jpenalbae --- src/class.c | 2 +- test/t/class.rb | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/src/class.c b/src/class.c index d02253c57..d120f1fec 100644 --- a/src/class.c +++ b/src/class.c @@ -2068,7 +2068,7 @@ mrb_mod_remove_method(mrb_state *mrb, mrb_value mod) mrb_get_args(mrb, "*", &argv, &argc); while (argc--) { - remove_method(mrb, mod, mrb_symbol(*argv)); + remove_method(mrb, mod, to_sym(mrb, *argv)); argv++; } return mod; diff --git a/test/t/class.rb b/test/t/class.rb index 7bcaaf90d..597999d3e 100644 --- a/test/t/class.rb +++ b/test/t/class.rb @@ -401,3 +401,12 @@ assert('class with non-class/module outer raises TypeError') do assert_raise(TypeError) { class 0::C1; end } assert_raise(TypeError) { class []::C2; end } end + +assert("remove_method doesn't segfault if the passed in argument isn't a symbol") do + klass = Class.new + assert_raise(TypeError) { klass.remove_method nil } + assert_raise(TypeError) { klass.remove_method 123 } + assert_raise(TypeError) { klass.remove_method 1.23 } + assert_raise(NameError) { klass.remove_method "hello" } + assert_raise(TypeError) { klass.remove_method Class.new } +end -- cgit v1.2.3 From 12539825773ddb13fac38091d13341b816ac23fa Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 14 Nov 2016 15:07:07 -0500 Subject: Fix codegen issue causing misaligned register Reported by https://hackerone.com/haquaman --- mrbgems/mruby-compiler/core/codegen.c | 2 ++ test/t/codegen.rb | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 test/t/codegen.rb (limited to 'test') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 0c84dd558..75adbefdd 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2024,6 +2024,7 @@ codegen(codegen_scope *s, node *tree, int val) } genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc)); } + if (val) push(); break; case NODE_RETRY: @@ -2058,6 +2059,7 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc)); } } + if (val) push(); } break; diff --git a/test/t/codegen.rb b/test/t/codegen.rb new file mode 100644 index 000000000..89ad94bae --- /dev/null +++ b/test/t/codegen.rb @@ -0,0 +1,20 @@ +## +# Codegen tests + +assert('codegen absorbs arguments to redo and retry if they are the argument of a call') do + assert_nothing_raised do + a=*"1", case nil + when 1 + redo | + 1 + end + end + + assert_nothing_raised do + a=*"1", case nil + when 1 + retry | + 1 + end + end +end -- cgit v1.2.3 From 71641bbf732ab8cbadf8a07e20b2a939b0e3b82b Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 14 Nov 2016 17:28:18 -0500 Subject: Fix segfault caused by empty condition in ternary Reported by https://hackerone.com/jpenalbae --- mrbgems/mruby-compiler/core/codegen.c | 4 ++++ test/t/codegen.rb | 6 ++++++ 2 files changed, 10 insertions(+) create mode 100644 test/t/codegen.rb (limited to 'test') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 0c84dd558..71b1dcc6f 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1362,6 +1362,10 @@ codegen(codegen_scope *s, node *tree, int val) int pos1, pos2; node *e = tree->cdr->cdr->car; + if (!tree->car) { + codegen(s, e, val); + return; + } switch ((intptr_t)tree->car->car) { case NODE_TRUE: case NODE_INT: diff --git a/test/t/codegen.rb b/test/t/codegen.rb new file mode 100644 index 000000000..99d6dbe66 --- /dev/null +++ b/test/t/codegen.rb @@ -0,0 +1,6 @@ +## +# Codegen tests + +assert('empty condition in ternary expression parses correctly') do + assert_equal () ? 1 : 2, 2 +end -- cgit v1.2.3 From 1ec5994377b45b0299a9c4e6e7ab275792d81bc9 Mon Sep 17 00:00:00 2001 From: Francois Chagnon Date: Mon, 14 Nov 2016 16:49:45 -0500 Subject: Fix calling .arity on Proc with undefined `initialize` Reported by @bouk --- mrbgems/mruby-proc-ext/src/proc.c | 3 +++ mrbgems/mruby-proc-ext/test/proc.rb | 11 +++++++++++ src/proc.c | 15 ++++++++------- test/t/proc.rb | 11 +++++++++++ 4 files changed, 33 insertions(+), 7 deletions(-) (limited to 'test') diff --git a/mrbgems/mruby-proc-ext/src/proc.c b/mrbgems/mruby-proc-ext/src/proc.c index c8c8f1aa1..34f6230dc 100644 --- a/mrbgems/mruby-proc-ext/src/proc.c +++ b/mrbgems/mruby-proc-ext/src/proc.c @@ -114,6 +114,9 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self) // TODO cfunc aspec is not implemented yet return mrb_ary_new(mrb); } + if (!irep) { + return mrb_ary_new(mrb); + } if (!irep->lv) { return mrb_ary_new(mrb); } diff --git a/mrbgems/mruby-proc-ext/test/proc.rb b/mrbgems/mruby-proc-ext/test/proc.rb index 75e11dd93..7a078aabf 100644 --- a/mrbgems/mruby-proc-ext/test/proc.rb +++ b/mrbgems/mruby-proc-ext/test/proc.rb @@ -58,6 +58,17 @@ assert('Proc#parameters') do assert_equal([[:req, :a], [:req, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:req, :f], [:req, :g], [:block, :h]], lambda {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters) end +assert('Proc#parameters with uninitialized Proc') do + begin + Proc.alias_method(:original_initialize, :initialize) + Proc.remove_method(:initialize) + assert_equal [], Proc.new{|a, b, c| 1}.parameters + ensure + Proc.alias_method(:initialize, :original_initialize) + Proc.remove_method(:original_initialize) + end +end + assert('Proc#to_proc') do proc = Proc.new {} assert_equal proc, proc.to_proc diff --git a/src/proc.c b/src/proc.c index 1620bddf8..4f770932b 100644 --- a/src/proc.c +++ b/src/proc.c @@ -188,18 +188,13 @@ mrb_proc_call_cfunc(mrb_state *mrb, struct RProc *p, mrb_value self) return (p->body.func)(mrb, self); } -mrb_code* -mrb_proc_iseq(mrb_state *mrb, struct RProc *p) -{ - return p->body.irep->iseq; -} - /* 15.2.17.4.2 */ static mrb_value mrb_proc_arity(mrb_state *mrb, mrb_value self) { struct RProc *p = mrb_proc_ptr(self); - mrb_code *iseq = mrb_proc_iseq(mrb, p); + struct mrb_irep *irep; + mrb_code *iseq; mrb_aspec aspec; int ma, op, ra, pa, arity; @@ -208,6 +203,12 @@ mrb_proc_arity(mrb_state *mrb, mrb_value self) return mrb_fixnum_value(-1); } + irep = p->body.irep; + if (!irep) { + return mrb_fixnum_value(0); + } + + iseq = irep->iseq; /* arity is depend on OP_ENTER */ if (GET_OPCODE(*iseq) != OP_ENTER) { return mrb_fixnum_value(0); diff --git a/test/t/proc.rb b/test/t/proc.rb index 888b7d56a..bc9821f7c 100644 --- a/test/t/proc.rb +++ b/test/t/proc.rb @@ -46,6 +46,17 @@ assert('Proc#arity', '15.2.17.4.2') do assert_equal(-1, g) end +assert('Proc#arity with unitialized Proc') do + begin + Proc.alias_method(:original_initialize, :initialize) + Proc.remove_method(:initialize) + assert_equal 0, Proc.new{|a, b, c| 1}.arity + ensure + Proc.alias_method(:initialize, :original_initialize) + Proc.remove_method(:original_initialize) + end +end + assert('Proc#call', '15.2.17.4.3') do a = 0 b = Proc.new { a += 1 } -- cgit v1.2.3 From 76a1bdfa29469576112a41b78a132b785616a3f9 Mon Sep 17 00:00:00 2001 From: Clayton Smith Date: Wed, 16 Nov 2016 10:10:14 -0500 Subject: Get String length after args in String#chomp! Fixes RCE issue Reported by @bouk --- src/string.c | 4 +++- test/t/string.rb | 14 +++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/src/string.c b/src/string.c index 5e490bf03..f47294291 100644 --- a/src/string.c +++ b/src/string.c @@ -1235,11 +1235,13 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str) char *p, *pp; mrb_int rslen; mrb_int len; + mrb_int argc; struct RString *s = mrb_str_ptr(str); mrb_str_modify(mrb, s); + argc = mrb_get_args(mrb, "|S", &rs); len = RSTR_LEN(s); - if (mrb_get_args(mrb, "|S", &rs) == 0) { + if (argc == 0) { if (len == 0) return mrb_nil_value(); smart_chomp: if (RSTR_PTR(s)[len-1] == '\n') { diff --git a/test/t/string.rb b/test/t/string.rb index e67389b5c..80fcbe6fa 100644 --- a/test/t/string.rb +++ b/test/t/string.rb @@ -251,6 +251,19 @@ assert('String#chomp!', '15.2.10.5.10') do assert_equal 'abc', e end +assert('String#chomp! uses the correct length') do + class A + def to_str + $s.replace("AA") + "A" + end + end + + $s = "AAA" + $s.chomp!(A.new) + assert_equal $s, "A" +end + assert('String#chop', '15.2.10.5.11') do a = ''.chop b = 'abc'.chop @@ -683,4 +696,3 @@ assert('String#freeze') do assert_raise(RuntimeError) { str.upcase! } end - -- cgit v1.2.3 From 964427f82c5a8556daf4448b47cc65fb6d2a94b8 Mon Sep 17 00:00:00 2001 From: Francis Bogsanyi Date: Thu, 17 Nov 2016 12:59:27 -0500 Subject: Fix unsafe peephole optimization Reported by https://hackerone.com/dkasak --- mrbgems/mruby-compiler/core/codegen.c | 6 ++++-- test/t/codegen.rb | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 test/t/codegen.rb (limited to 'test') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 0c84dd558..39d62348a 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1798,8 +1798,10 @@ codegen(codegen_scope *s, node *tree, int val) int pos; pop(); - if (val && vsp >= 0) { - genop(s, MKOP_AB(OP_MOVE, vsp, cursp())); + if (val) { + if (vsp >= 0) { + genop(s, MKOP_AB(OP_MOVE, vsp, cursp())); + } pos = genop(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0)); } else { diff --git a/test/t/codegen.rb b/test/t/codegen.rb new file mode 100644 index 000000000..f910d37fb --- /dev/null +++ b/test/t/codegen.rb @@ -0,0 +1,11 @@ +## +# Codegen tests + +assert('peephole optimization does not eliminate move whose result is reused') do + assert_raise LocalJumpError do + def method + yield + end + method(&a &&= 0) + end +end -- cgit v1.2.3 From a384bcce350acf5e8be5d45f0258e6ef5bdeb033 Mon Sep 17 00:00:00 2001 From: Francois Chagnon Date: Thu, 17 Nov 2016 14:52:52 -0500 Subject: Fix instances where return value of mrb_method_search_vm is unchecked Reported by @charliesome --- src/vm.c | 47 +++++++++++++++++++++++++++++++++++++---------- test/t/nomethoderror.rb | 31 +++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 10 deletions(-) (limited to 'test') diff --git a/src/vm.c b/src/vm.c index a7418e6e7..fed622b85 100644 --- a/src/vm.c +++ b/src/vm.c @@ -54,6 +54,10 @@ The value below allows about 60000 recursive calls in the simplest case. */ #define ARENA_RESTORE(mrb,ai) (mrb)->gc.arena_idx = (ai) +#define CALL_MAXARGS 127 + +void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args); + static inline void stack_clear(mrb_value *from, size_t count) { @@ -362,9 +366,13 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc c = mrb_class(mrb, self); p = mrb_method_search_vm(mrb, &c, mid); if (!p) { + mrb_sym missing = mrb_intern_lit(mrb, "method_missing"); + p = mrb_method_search_vm(mrb, &c, missing); + if (!p) { + mrb_value args = mrb_ary_new_from_values(mrb, argc, argv); + mrb_method_missing(mrb, mid, self, args); + } undef = mid; - mid = mrb_intern_lit(mrb, "method_missing"); - p = mrb_method_search_vm(mrb, &c, mid); n++; argc++; } ci = cipush(mrb); @@ -749,10 +757,6 @@ argnum_error(mrb_state *mrb, mrb_int num) #endif -#define CALL_MAXARGS 127 - -void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args); - MRB_API mrb_value mrb_vm_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep) { @@ -1290,8 +1294,20 @@ RETRY_TRY_BLOCK: c = mrb->c->ci->target_class->super; m = mrb_method_search_vm(mrb, &c, mid); if (!m) { - mid = mrb_intern_lit(mrb, "method_missing"); - m = mrb_method_search_vm(mrb, &c, mid); + mrb_sym missing = mrb_intern_lit(mrb, "method_missing"); + m = mrb_method_search_vm(mrb, &c, missing); + if (!m) { + mrb_value args; + + if (n == CALL_MAXARGS) { + args = regs[a+1]; + } + else { + args = mrb_ary_new_from_values(mrb, n, regs+a+1); + } + mrb_method_missing(mrb, mid, recv, args); + } + mid = missing; if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid)); } @@ -1681,9 +1697,20 @@ RETRY_TRY_BLOCK: m = mrb_method_search_vm(mrb, &c, mid); if (!m) { mrb_value sym = mrb_symbol_value(mid); + mrb_sym missing = mrb_intern_lit(mrb, "method_missing"); + m = mrb_method_search_vm(mrb, &c, missing); + if (!m) { + mrb_value args; - mid = mrb_intern_lit(mrb, "method_missing"); - m = mrb_method_search_vm(mrb, &c, mid); + if (n == CALL_MAXARGS) { + args = regs[a+1]; + } + else { + args = mrb_ary_new_from_values(mrb, n, regs+a+1); + } + mrb_method_missing(mrb, mid, recv, args); + } + mid = missing; if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], sym); } diff --git a/test/t/nomethoderror.rb b/test/t/nomethoderror.rb index 5fed79689..ce3514782 100644 --- a/test/t/nomethoderror.rb +++ b/test/t/nomethoderror.rb @@ -20,3 +20,34 @@ assert('NoMethodError#args', '15.2.32.2.1') do end end end + +assert('Can still raise when BasicObject#method_missing is removed') do + assert_raise(TypeError) do + begin + BasicObject.alias_method(:old_method_missing, :method_missing) + BasicObject.remove_method(:method_missing) + 1.__send__(:foo) + ensure + BasicObject.alias_method(:method_missing, :old_method_missing) + BasicObject.remove_method(:old_method_missing) + end + end +end + +assert('Can still call super when BasicObject#method_missing is removed') do + assert_raise(TypeError) do + class A + def foo + super + end + end + begin + BasicObject.alias_method(:old_method_missing, :method_missing) + BasicObject.remove_method(:method_missing) + A.new.foo + ensure + BasicObject.alias_method(:method_missing, :old_method_missing) + BasicObject.remove_method(:old_method_missing) + end + end +end -- cgit v1.2.3 From 3f83ec64a82410cdc16863f8242eaea30dec026f Mon Sep 17 00:00:00 2001 From: Yutaka HARA Date: Thu, 1 Dec 2016 14:55:26 +0900 Subject: Add test for recently fixed bugs --- test/t/array.rb | 13 +++++++++++++ test/t/class.rb | 12 ++++++++++++ test/t/hash.rb | 7 +++++++ test/t/syntax.rb | 20 ++++++++++++++++++++ 4 files changed, 52 insertions(+) (limited to 'test') 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/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 -- cgit v1.2.3 From bd9bc7786fb72ecbae1542e6ab01d7c4cee9e636 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 1 Dec 2016 14:28:28 +0900 Subject: Fix assertion argument orders --- test/t/unicode.rb | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'test') diff --git a/test/t/unicode.rb b/test/t/unicode.rb index 7edd65ef2..b8c54ca66 100644 --- a/test/t/unicode.rb +++ b/test/t/unicode.rb @@ -2,34 +2,34 @@ 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 -- cgit v1.2.3 From 0f08914ac0d433545a4224ee1c3f8d3eb8d51e68 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 1 Dec 2016 14:37:59 +0900 Subject: Support multiple elements \u syntax --- mrbgems/mruby-compiler/core/parse.y | 14 ++++++++++++++ test/t/unicode.rb | 4 ++++ 2 files changed, 18 insertions(+) (limited to 'test') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 65b89bed3..f0c45b85b 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3995,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/test/t/unicode.rb b/test/t/unicode.rb index b8c54ca66..8622ae08a 100644 --- a/test/t/unicode.rb +++ b/test/t/unicode.rb @@ -33,3 +33,7 @@ assert('braced \u notation test') do 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 -- cgit v1.2.3 From 9c61e1cd87aca3646fe39a6d53223efdcb11e250 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 28 Nov 2016 15:04:27 -0500 Subject: Use mrb_ptr instead of mrb_cptr in Kernel#to_s This is to avoid segfault when WORD_BOXING is enabled Reported by https://hackerone.com/brakhane --- src/object.c | 2 +- test/t/kernel.rb | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/src/object.c b/src/object.c index f76ee68a2..eb2c23e63 100644 --- a/src/object.c +++ b/src/object.c @@ -444,7 +444,7 @@ mrb_any_to_s(mrb_state *mrb, mrb_value obj) mrb_str_cat_lit(mrb, str, "#<"); mrb_str_cat_cstr(mrb, str, cname); mrb_str_cat_lit(mrb, str, ":"); - mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_cptr(obj))); + mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_ptr(obj))); mrb_str_cat_lit(mrb, str, ">"); return str; diff --git a/test/t/kernel.rb b/test/t/kernel.rb index d240e59dc..e59bd6a10 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -520,6 +520,21 @@ assert('Kernel#to_s', '15.3.1.3.46') do assert_equal to_s.class, String end +assert('Kernel#to_s on primitives') do + begin + Fixnum.alias_method :to_s_, :to_s + Fixnum.remove_method :to_s + + assert_nothing_raised do + # segfaults if mrb_cptr is used + 1.to_s + end + ensure + Fixnum.alias_method :to_s, :to_s_ + Fixnum.remove_method :to_s_ + end +end + assert('Kernel.local_variables', '15.3.1.2.7') do a, b = 0, 1 a += b -- cgit v1.2.3 From fe362c1f2649c9c502d9a5998ef8c4c94893f3ea Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Thu, 24 Nov 2016 13:31:47 -0500 Subject: Fix segfault when using result of rest assignment Reported by https://hackerone.com/haquaman --- mrbgems/mruby-compiler/core/codegen.c | 4 +++- test/t/codegen.rb | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 553baa116..2c75c8aed 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1061,7 +1061,9 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) n++; } } - push(); + if (!val) { + push(); + } } } diff --git a/test/t/codegen.rb b/test/t/codegen.rb index 1ac689a82..bb0f5c306 100644 --- a/test/t/codegen.rb +++ b/test/t/codegen.rb @@ -54,3 +54,12 @@ A B assert_equal "\n", a end + +assert('splat in case splat') do + a = *case + when 0 + * = 1 + end + + assert_equal [1], a +end -- cgit v1.2.3 From 1ff4b3f800d369510658b7926a1d6dc9327d0422 Mon Sep 17 00:00:00 2001 From: Clayton Smith Date: Thu, 24 Nov 2016 15:51:25 -0500 Subject: Fix segfault in mrb_proc_copy. --- src/proc.c | 2 +- test/t/proc.rb | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'test') 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/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 -- cgit v1.2.3 From 144006a20e7d97733d682ff1502f24b032b3db59 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 3 Dec 2016 18:23:04 +0900 Subject: update NoMethodError tests; ref #3291 --- test/t/nomethoderror.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/t/nomethoderror.rb b/test/t/nomethoderror.rb index ce3514782..1c09bc20e 100644 --- a/test/t/nomethoderror.rb +++ b/test/t/nomethoderror.rb @@ -22,7 +22,7 @@ assert('NoMethodError#args', '15.2.32.2.1') do end assert('Can still raise when BasicObject#method_missing is removed') do - assert_raise(TypeError) do + assert_raise(NoMethodError) do begin BasicObject.alias_method(:old_method_missing, :method_missing) BasicObject.remove_method(:method_missing) @@ -35,7 +35,7 @@ assert('Can still raise when BasicObject#method_missing is removed') do end assert('Can still call super when BasicObject#method_missing is removed') do - assert_raise(TypeError) do + assert_raise(NoMethodError) do class A def foo super -- cgit v1.2.3 From 338e0ff52d645556e644ac08b3efc6ea31868c59 Mon Sep 17 00:00:00 2001 From: Shugo Maeda Date: Wed, 7 Dec 2016 22:39:20 +0900 Subject: Copy default_proc by Hash#dup. --- src/hash.c | 14 +++++++++++++- test/t/hash.rb | 4 ++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/src/hash.c b/src/hash.c index 4df2babbe..93fe656e0 100644 --- a/src/hash.c +++ b/src/hash.c @@ -225,6 +225,7 @@ mrb_hash_dup(mrb_state *mrb, mrb_value hash) struct RHash* ret; khash_t(ht) *h, *ret_h; khiter_t k, ret_k; + mrb_value ifnone, vret; h = RHASH_TBL(hash); ret = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class); @@ -243,7 +244,18 @@ mrb_hash_dup(mrb_state *mrb, mrb_value hash) } } - return mrb_obj_value(ret); + if (MRB_RHASH_DEFAULT_P(hash)) { + ret->flags |= MRB_HASH_DEFAULT; + } + if (MRB_RHASH_PROCDEFAULT_P(hash)) { + ret->flags |= MRB_HASH_PROC_DEFAULT; + } + vret = mrb_obj_value(ret); + ifnone = RHASH_IFNONE(hash); + if (!mrb_nil_p(ifnone)) { + mrb_iv_set(mrb, vret, mrb_intern_lit(mrb, "ifnone"), ifnone); + } + return vret; } MRB_API mrb_value diff --git a/test/t/hash.rb b/test/t/hash.rb index b455812cf..f076db8e5 100644 --- a/test/t/hash.rb +++ b/test/t/hash.rb @@ -44,6 +44,10 @@ assert('Hash#dup') do b = a.dup a['a'] = 2 assert_equal({'a' => 1}, b) + + c = Hash.new { |h, k| h[k] = k.upcase } + d = c.dup + assert_equal("FOO", d["foo"]) end assert('Hash#default', '15.2.13.4.5') do -- cgit v1.2.3 From d56a19cbf526190de036130fe3a5bf14a0705ee2 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Fri, 2 Dec 2016 09:48:28 -0500 Subject: Don't generate code for NODE_NEGATE if the result isn't used Reported by https://hackerone.com/haquaman --- mrbgems/mruby-compiler/core/codegen.c | 4 ++++ test/t/codegen.rb | 10 ++++++++++ 2 files changed, 14 insertions(+) (limited to 'test') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index b2cd12225..891c4f62b 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2223,6 +2223,10 @@ codegen(codegen_scope *s, node *tree, int val) { nt = (intptr_t)tree->car; tree = tree->cdr; + if (!val) { + codegen(s, tree, NOVAL); + break; + } switch (nt) { case NODE_FLOAT: { diff --git a/test/t/codegen.rb b/test/t/codegen.rb index bb0f5c306..bd360dbcb 100644 --- a/test/t/codegen.rb +++ b/test/t/codegen.rb @@ -63,3 +63,13 @@ assert('splat in case splat') do assert_equal [1], a end + +assert('negate literal register alignment') do + a = *case + when 0 + -0.0 + 2 + end + + assert_equal [2], a +end -- cgit v1.2.3 From c8da3c4df4f8cb6f6d00c70e75606c59f9888509 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Wed, 7 Dec 2016 11:22:30 -0500 Subject: Fix segfault when undef is called with exactly 127 arguments The issue is that when there are more than 126 arguments an array needs to be created to pass the arguments on with. Reported by https://hackerone.com/revskills --- mrbgems/mruby-compiler/core/codegen.c | 22 ++++++++++++++++++++-- test/t/codegen.rb | 10 ++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index b2cd12225..3cfd99d41 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2560,13 +2560,31 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_A(OP_TCLASS, cursp())); push(); while (t) { - int symbol = new_msym(s, sym(t->car)); + int symbol; + if (num >= CALL_MAXARGS - 1) { + pop_n(num); + genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), num)); + while (t) { + symbol = new_msym(s, sym(t->car)); + push(); + genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol)); + pop(); + genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1)); + t = t->cdr; + } + num = CALL_MAXARGS; + break; + } + symbol = new_msym(s, sym(t->car)); genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol)); push(); t = t->cdr; num++; } - pop_n(num + 1); + pop(); + if (num < CALL_MAXARGS) { + pop_n(num); + } genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num)); if (val) { push(); diff --git a/test/t/codegen.rb b/test/t/codegen.rb index bb0f5c306..3058a7fbc 100644 --- a/test/t/codegen.rb +++ b/test/t/codegen.rb @@ -63,3 +63,13 @@ assert('splat in case splat') do assert_equal [1], a end + +assert('undef with 127 or more arguments') do + assert_raise NameError do + undef + a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, + a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, + a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, + a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a + end +end -- cgit v1.2.3 From 1264219832aeff2630f47d4abb9bee6d013c3e75 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Tue, 15 Nov 2016 11:13:38 -0500 Subject: Fix segfault in gen_values with NOVAL and more than 127 args --- mrbgems/mruby-compiler/core/codegen.c | 2 -- test/t/codegen.rb | 8 ++++++++ 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 3cfd99d41..99ab4dd97 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -818,8 +818,6 @@ gen_values(codegen_scope *s, node *t, int val) } } else { - codegen(s, t->car->cdr, NOVAL); - t = t->cdr; while (t) { codegen(s, t->car, NOVAL); t = t->cdr; diff --git a/test/t/codegen.rb b/test/t/codegen.rb index 3058a7fbc..528f58d9e 100644 --- a/test/t/codegen.rb +++ b/test/t/codegen.rb @@ -73,3 +73,11 @@ assert('undef with 127 or more arguments') do a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a end end + +assert('next in normal loop with 127 arguments') do + assert_raise NameError do + while true + next A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A + end + end +end -- cgit v1.2.3 From 10bb7ad693e7c7443de924a39c1fedb4461108ba Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Sun, 11 Dec 2016 01:45:38 +0900 Subject: Implement Object#freeze --- include/mruby/class.h | 1 + include/mruby/object.h | 4 ++++ include/mruby/string.h | 5 ----- src/array.c | 4 ++++ src/hash.c | 7 +++++-- src/kernel.c | 10 ++++++++++ src/string.c | 15 ++------------- test/t/array.rb | 7 +++++++ test/t/hash.rb | 7 +++++++ test/t/kernel.rb | 5 +++++ 10 files changed, 45 insertions(+), 20 deletions(-) (limited to 'test') diff --git a/include/mruby/class.h b/include/mruby/class.h index 246e82e59..ce953af3b 100644 --- a/include/mruby/class.h +++ b/include/mruby/class.h @@ -52,6 +52,7 @@ mrb_class(mrb_state *mrb, mrb_value v) } // TODO: figure out where to put user flags +#define MRB_FLAG_IS_FROZEN (1 << 18) #define MRB_FLAG_IS_PREPENDED (1 << 19) #define MRB_FLAG_IS_ORIGIN (1 << 20) #define MRB_CLASS_ORIGIN(c) do {\ diff --git a/include/mruby/object.h b/include/mruby/object.h index 9fbfe34f3..da44027e1 100644 --- a/include/mruby/object.h +++ b/include/mruby/object.h @@ -22,6 +22,10 @@ struct RBasic { }; #define mrb_basic_ptr(v) ((struct RBasic*)(mrb_ptr(v))) +#define RBASIC_FROZEN_P(o) ((o)->flags & MRB_FLAG_IS_FROZEN) +#define RBASIC_SET_FROZEN_FLAG(o) ((o)->flags |= MRB_FLAG_IS_FROZEN) +#define RBASIC_UNSET_FROZEN_FLAG(o) ((o)->flags &= ~MRB_FLAG_IS_FROZEN) + struct RObject { MRB_OBJECT_HEADER; struct iv_tbl *iv; diff --git a/include/mruby/string.h b/include/mruby/string.h index b30c1ed98..9ccf8f187 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -62,10 +62,6 @@ struct RString { #define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE) #define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE) -#define RSTR_FROZEN_P(s) ((s)->flags & MRB_STR_FROZEN) -#define RSTR_SET_FROZEN_FLAG(s) ((s)->flags |= MRB_STR_FROZEN) -#define RSTR_UNSET_FROZEN_FLAG(s) ((s)->flags &= ~MRB_STR_FROZEN) - /* * Returns a pointer from a Ruby string */ @@ -80,7 +76,6 @@ MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*); #define MRB_STR_SHARED 1 #define MRB_STR_NOFREE 2 -#define MRB_STR_FROZEN 4 #define MRB_STR_NO_UTF 8 #define MRB_STR_EMBED 16 #define MRB_STR_EMBED_LEN_MASK 0x3e0 diff --git a/src/array.c b/src/array.c index f6599bd5b..c6bac7b47 100644 --- a/src/array.c +++ b/src/array.c @@ -108,6 +108,10 @@ ary_fill_with_nil(mrb_value *ptr, mrb_int size) static void ary_modify(mrb_state *mrb, struct RArray *a) { + if (RBASIC_FROZEN_P(a)) { + mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen array"); + } + if (ARY_SHARED_P(a)) { mrb_shared_array *shared = a->aux.shared; diff --git a/src/hash.c b/src/hash.c index 93fe656e0..d0e865b5c 100644 --- a/src/hash.c +++ b/src/hash.c @@ -98,9 +98,9 @@ static void mrb_hash_modify(mrb_state *mrb, mrb_value hash); static inline mrb_value mrb_hash_ht_key(mrb_state *mrb, mrb_value key) { - if (mrb_string_p(key) && !RSTR_FROZEN_P(mrb_str_ptr(key))) { + if (mrb_string_p(key) && !RBASIC_FROZEN_P(mrb_str_ptr(key))) { key = mrb_str_dup(mrb, key); - RSTR_SET_FROZEN_FLAG(mrb_str_ptr(key)); + RBASIC_SET_FROZEN_FLAG(mrb_str_ptr(key)); } return key; } @@ -278,6 +278,9 @@ mrb_hash_tbl(mrb_state *mrb, mrb_value hash) static void mrb_hash_modify(mrb_state *mrb, mrb_value hash) { + if (RBASIC_FROZEN_P(mrb_hash_ptr(hash))) { + mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen hash"); + } mrb_hash_tbl(mrb, hash); } diff --git a/src/kernel.c b/src/kernel.c index c63e05596..78e57a17a 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -450,6 +450,15 @@ mrb_obj_extend_m(mrb_state *mrb, mrb_value self) return mrb_obj_extend(mrb, argc, argv, self); } +static mrb_value +mrb_obj_freeze(mrb_state *mrb, mrb_value self) +{ + struct RBasic *b = mrb_basic_ptr(self); + + RBASIC_SET_FROZEN_FLAG(b); + return self; +} + /* 15.3.1.3.15 */ /* * call-seq: @@ -1124,6 +1133,7 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "eql?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.10 */ mrb_define_method(mrb, krn, "equal?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.11 */ mrb_define_method(mrb, krn, "extend", mrb_obj_extend_m, MRB_ARGS_ANY()); /* 15.3.1.3.13 */ + mrb_define_method(mrb, krn, "freeze", mrb_obj_freeze, MRB_ARGS_NONE()); mrb_define_method(mrb, krn, "global_variables", mrb_f_global_variables, MRB_ARGS_NONE()); /* 15.3.1.3.14 */ mrb_define_method(mrb, krn, "hash", mrb_obj_hash, MRB_ARGS_NONE()); /* 15.3.1.3.15 */ mrb_define_method(mrb, krn, "initialize_copy", mrb_obj_init_copy, MRB_ARGS_REQ(1)); /* 15.3.1.3.16 */ diff --git a/src/string.c b/src/string.c index a4f8085ec..7234ecf2b 100644 --- a/src/string.c +++ b/src/string.c @@ -501,7 +501,7 @@ str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset) static void check_frozen(mrb_state *mrb, struct RString *s) { - if (RSTR_FROZEN_P(s)) { + if (RBASIC_FROZEN_P(s)) { mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen string"); } } @@ -700,15 +700,6 @@ mrb_str_modify(mrb_state *mrb, struct RString *s) } } -static mrb_value -mrb_str_freeze(mrb_state *mrb, mrb_value str) -{ - struct RString *s = mrb_str_ptr(str); - - RSTR_SET_FROZEN_FLAG(s); - return str; -} - MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len) { @@ -2217,7 +2208,7 @@ mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr) char *p = RSTR_PTR(ps); if (!p || p[len] != '\0') { - if (RSTR_FROZEN_P(ps)) { + if (RBASIC_FROZEN_P(ps)) { *ptr = str = mrb_str_dup(mrb, str); ps = mrb_str_ptr(str); } @@ -2746,8 +2737,6 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.43 */ mrb_define_method(mrb, s, "inspect", mrb_str_inspect, MRB_ARGS_NONE()); /* 15.2.10.5.46(x) */ mrb_define_method(mrb, s, "bytes", mrb_str_bytes, MRB_ARGS_NONE()); - - mrb_define_method(mrb, s, "freeze", mrb_str_freeze, MRB_ARGS_NONE()); } /* diff --git a/test/t/array.rb b/test/t/array.rb index 9cc2f64ad..cf7ed4704 100644 --- a/test/t/array.rb +++ b/test/t/array.rb @@ -373,3 +373,10 @@ assert("Array#rindex") do $a = [2, 3, 4, 5, 6, 7, 8, 9, 10, Sneaky.new] assert_equal 0, $a.rindex(1) end + +assert('Array#freeze') do + a = [].freeze + assert_raise(RuntimeError) do + a[0] = 1 + end +end diff --git a/test/t/hash.rb b/test/t/hash.rb index f076db8e5..c63b8c009 100644 --- a/test/t/hash.rb +++ b/test/t/hash.rb @@ -366,3 +366,10 @@ assert('Hash#rehash') do h.rehash assert_equal("b", h[[:b]]) end + +assert('Hash#freeze') do + h = {}.freeze + assert_raise(RuntimeError) do + h[:a] = 'b' + end +end diff --git a/test/t/kernel.rb b/test/t/kernel.rb index e59bd6a10..42abed9df 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -257,6 +257,11 @@ assert('Kernel#extend works on toplevel', '15.3.1.3.13') do assert_true respond_to?(:test_method) end +assert('Kernel#freeze') do + obj = Object.new + assert_equal obj, obj.freeze +end + assert('Kernel#global_variables', '15.3.1.3.14') do assert_equal Array, global_variables.class end -- cgit v1.2.3 From 868d2e528fce86f380a2d099877f6cb8ffd1ff69 Mon Sep 17 00:00:00 2001 From: Clayton Smith Date: Thu, 15 Dec 2016 09:36:22 -0500 Subject: Fix crash when exponent is -2147483648 --- src/string.c | 9 ++++++++- test/t/string.rb | 4 ++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/src/string.c b/src/string.c index 0049fdd5b..ce27cdaa1 100644 --- a/src/string.c +++ b/src/string.c @@ -2868,7 +2868,11 @@ mrb_float_read(const char *string, char **endPtr) mantSize -= 1; /* One of the digits was the point. */ } if (mantSize > 18) { - fracExp = decPt - 18; + if (decPt - 18 > 29999) { + fracExp = 29999; + } else { + fracExp = decPt - 18; + } mantSize = 18; } else { fracExp = decPt - mantSize; @@ -2922,6 +2926,9 @@ mrb_float_read(const char *string, char **endPtr) } while (isdigit(*p)) { exp = exp * 10 + (*p - '0'); + if (exp > 19999) { + exp = 19999; + } p += 1; } } diff --git a/test/t/string.rb b/test/t/string.rb index 80fcbe6fa..20dc49d92 100644 --- a/test/t/string.rb +++ b/test/t/string.rb @@ -596,10 +596,14 @@ assert('String#to_f', '15.2.10.5.38') do a = ''.to_f b = '123456789'.to_f c = '12345.6789'.to_f + d = '1e-2147483648'.to_f + e = '1e2147483648'.to_f assert_float(0.0, a) assert_float(123456789.0, b) assert_float(12345.6789, c) + assert_float(0, d) + assert_float(Float::INFINITY, e) end assert('String#to_i', '15.2.10.5.39') do -- cgit v1.2.3 From 3cba13c249457cfb318c9d7d4456d99003442139 Mon Sep 17 00:00:00 2001 From: ksss Date: Wed, 21 Dec 2016 15:17:05 +0900 Subject: Proc shouldn't have `initialize` method Fix #3356 --- mrbgems/mruby-proc-ext/test/proc.rb | 11 ----------- src/proc.c | 12 ++++++------ test/t/proc.rb | 27 --------------------------- 3 files changed, 6 insertions(+), 44 deletions(-) (limited to 'test') diff --git a/mrbgems/mruby-proc-ext/test/proc.rb b/mrbgems/mruby-proc-ext/test/proc.rb index 7a078aabf..75e11dd93 100644 --- a/mrbgems/mruby-proc-ext/test/proc.rb +++ b/mrbgems/mruby-proc-ext/test/proc.rb @@ -58,17 +58,6 @@ assert('Proc#parameters') do assert_equal([[:req, :a], [:req, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:req, :f], [:req, :g], [:block, :h]], lambda {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters) end -assert('Proc#parameters with uninitialized Proc') do - begin - Proc.alias_method(:original_initialize, :initialize) - Proc.remove_method(:initialize) - assert_equal [], Proc.new{|a, b, c| 1}.parameters - ensure - Proc.alias_method(:initialize, :original_initialize) - Proc.remove_method(:original_initialize) - end -end - assert('Proc#to_proc') do proc = Proc.new {} assert_equal proc, proc.to_proc diff --git a/src/proc.c b/src/proc.c index 470547094..0fb38359f 100644 --- a/src/proc.c +++ b/src/proc.c @@ -148,19 +148,19 @@ mrb_proc_copy(struct RProc *a, struct RProc *b) } static mrb_value -mrb_proc_initialize(mrb_state *mrb, mrb_value self) +mrb_proc_s_new(mrb_state *mrb, mrb_value proc_class) { mrb_value blk; + struct RProc *p; mrb_get_args(mrb, "&", &blk); if (mrb_nil_p(blk)) { /* Calling Proc.new without a block is not implemented yet */ mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block"); } - else { - mrb_proc_copy(mrb_proc_ptr(self), mrb_proc_ptr(blk)); - } - return self; + p = (struct RProc *)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb_class_ptr(proc_class)); + mrb_proc_copy(p, mrb_proc_ptr(blk)); + return mrb_obj_value(p); } static mrb_value @@ -268,7 +268,7 @@ mrb_init_proc(mrb_state *mrb) call_irep->iseq = call_iseq; call_irep->ilen = 1; - mrb_define_method(mrb, mrb->proc_class, "initialize", mrb_proc_initialize, MRB_ARGS_NONE()); + mrb_define_class_method(mrb, mrb->proc_class, "new", mrb_proc_s_new, MRB_ARGS_ANY()); mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1)); mrb_define_method(mrb, mrb->proc_class, "arity", mrb_proc_arity, MRB_ARGS_NONE()); diff --git a/test/t/proc.rb b/test/t/proc.rb index 29530e8dd..888b7d56a 100644 --- a/test/t/proc.rb +++ b/test/t/proc.rb @@ -46,17 +46,6 @@ assert('Proc#arity', '15.2.17.4.2') do assert_equal(-1, g) end -assert('Proc#arity with unitialized Proc') do - begin - Proc.alias_method(:original_initialize, :initialize) - Proc.remove_method(:initialize) - assert_equal 0, Proc.new{|a, b, c| 1}.arity - ensure - Proc.alias_method(:initialize, :original_initialize) - Proc.remove_method(:original_initialize) - end -end - assert('Proc#call', '15.2.17.4.3') do a = 0 b = Proc.new { a += 1 } @@ -163,19 +152,3 @@ 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 -- cgit v1.2.3 From a68b568911f5dbf762d26ba21e4171bc7a2473e5 Mon Sep 17 00:00:00 2001 From: ksss Date: Wed, 21 Dec 2016 18:31:44 +0900 Subject: Should call initialize method if defined --- src/proc.c | 5 ++++- test/t/proc.rb | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/src/proc.c b/src/proc.c index 0fb38359f..a75774667 100644 --- a/src/proc.c +++ b/src/proc.c @@ -151,6 +151,7 @@ static mrb_value mrb_proc_s_new(mrb_state *mrb, mrb_value proc_class) { mrb_value blk; + mrb_value proc; struct RProc *p; mrb_get_args(mrb, "&", &blk); @@ -160,7 +161,9 @@ mrb_proc_s_new(mrb_state *mrb, mrb_value proc_class) } p = (struct RProc *)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb_class_ptr(proc_class)); mrb_proc_copy(p, mrb_proc_ptr(blk)); - return mrb_obj_value(p); + proc = mrb_obj_value(p); + mrb_funcall_with_block(mrb, proc, mrb_intern_lit(mrb, "initialize"), 0, NULL, blk); + return proc; } static mrb_value diff --git a/test/t/proc.rb b/test/t/proc.rb index 888b7d56a..ef4566e66 100644 --- a/test/t/proc.rb +++ b/test/t/proc.rb @@ -136,6 +136,18 @@ assert('Proc#return_does_not_break_self') do assert_equal c, c.block.call end +assert('call Proc#initialize if defined') do + a = [] + c = Class.new(Proc) do + define_method(:initialize) do + a << :ok + end + end + + assert_kind_of c, c.new{} + assert_equal [:ok], a +end + assert('&obj call to_proc if defined') do pr = Proc.new{} def mock(&b) -- cgit v1.2.3 From 5c1c002ac2983fef8ef3254e2d2f3e016918c3cd Mon Sep 17 00:00:00 2001 From: ksss Date: Sat, 24 Dec 2016 22:54:52 +0900 Subject: Fix segv when primitive value Fix #3352 --- src/kernel.c | 18 ++++++++++++++++-- test/t/kernel.rb | 3 ++- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/src/kernel.c b/src/kernel.c index a5166deb2..5e44d73b4 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -453,9 +453,23 @@ mrb_obj_extend_m(mrb_state *mrb, mrb_value self) static mrb_value mrb_obj_freeze(mrb_state *mrb, mrb_value self) { - struct RBasic *b = mrb_basic_ptr(self); + struct RBasic *b; + + switch (mrb_type(self)) { + case MRB_TT_FALSE: + case MRB_TT_TRUE: + case MRB_TT_FIXNUM: + case MRB_TT_SYMBOL: + case MRB_TT_FLOAT: + return self; + default: + break; + } - MRB_SET_FROZEN_FLAG(b); + b = mrb_basic_ptr(self); + if (!MRB_FROZEN_P(b)) { + MRB_SET_FROZEN_FLAG(b); + } return self; } diff --git a/test/t/kernel.rb b/test/t/kernel.rb index 42abed9df..ca4b73907 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -260,6 +260,8 @@ end assert('Kernel#freeze') do obj = Object.new assert_equal obj, obj.freeze + assert_equal 0, 0.freeze + assert_equal :a, :a.freeze end assert('Kernel#global_variables', '15.3.1.3.14') do @@ -620,4 +622,3 @@ assert('stack extend') do assert_equal 6, recurse(0, 5) end - -- cgit v1.2.3 From f085baae06c967e829d463a8156fa9c3be4e0330 Mon Sep 17 00:00:00 2001 From: Ryo Okubo Date: Sat, 7 Jan 2017 17:57:14 +0900 Subject: Pass when assert returns a false value --- test/assert.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/assert.rb b/test/assert.rb index 5617e1e38..7efc24e19 100644 --- a/test/assert.rb +++ b/test/assert.rb @@ -44,7 +44,8 @@ def assert(str = 'Assertion failed', iso = '') begin $mrbtest_assert = [] $mrbtest_assert_idx = 0 - if(!yield || $mrbtest_assert.size > 0) + yield + if($mrbtest_assert.size > 0) $asserts.push(assertion_string('Fail: ', str, iso, nil)) $ko_test += 1 t_print('F') -- cgit v1.2.3 From 6be5160eb634e7b045cba83a38675cf14fa16593 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Tue, 6 Dec 2016 14:25:56 -0500 Subject: Fix 36fc1f14 not checking in the right location --- src/error.c | 5 +++-- test/t/nomethoderror.rb | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/src/error.c b/src/error.c index fda2cd15c..d7facd0b9 100644 --- a/src/error.c +++ b/src/error.c @@ -280,8 +280,6 @@ mrb_exc_set(mrb_state *mrb, mrb_value exc) mrb->exc = 0; } else { - if (!mrb_obj_is_kind_of(mrb, exc, mrb->eException_class)) - mrb_raise(mrb, E_TYPE_ERROR, "exception object expected"); mrb->exc = mrb_obj_ptr(exc); } } @@ -289,6 +287,9 @@ mrb_exc_set(mrb_state *mrb, mrb_value exc) MRB_API mrb_noreturn void mrb_exc_raise(mrb_state *mrb, mrb_value exc) { + if (!mrb_obj_is_kind_of(mrb, exc, mrb->eException_class)) { + mrb_raise(mrb, E_TYPE_ERROR, "exception object expected"); + } mrb_exc_set(mrb, exc); if (!mrb->gc.out_of_memory) { exc_debug_info(mrb, mrb->exc); diff --git a/test/t/nomethoderror.rb b/test/t/nomethoderror.rb index 1c09bc20e..41a3ba14f 100644 --- a/test/t/nomethoderror.rb +++ b/test/t/nomethoderror.rb @@ -51,3 +51,21 @@ assert('Can still call super when BasicObject#method_missing is removed') do end end end + +assert("NoMethodError#new does not return an exception") do + begin + class << NoMethodError + def new(*) + nil + end + end + + assert_raise(TypeError) do + Object.q + end + ensure + class << NoMethodError + remove_method :new + end + end +end -- cgit v1.2.3 From bd72dba8c05056693e42c74b35d90691221f0d0d Mon Sep 17 00:00:00 2001 From: ksss Date: Mon, 6 Feb 2017 11:04:42 +0900 Subject: Kernel#local_variables: Make result array unique --- src/kernel.c | 11 ++++++----- test/t/kernel.rb | 7 +++---- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'test') diff --git a/src/kernel.c b/src/kernel.c index 5ca1736c3..8b00d701b 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -1106,8 +1107,8 @@ mrb_obj_ceqq(mrb_state *mrb, mrb_value self) static mrb_value mrb_local_variables(mrb_state *mrb, mrb_value self) { - mrb_value ret; struct RProc *proc; + mrb_value vars; struct mrb_irep *irep; size_t i; @@ -1121,10 +1122,10 @@ mrb_local_variables(mrb_state *mrb, mrb_value self) if (!irep->lv) { return mrb_ary_new(mrb); } - ret = mrb_ary_new_capa(mrb, irep->nlocals - 1); + vars = mrb_hash_new(mrb); for (i = 0; i + 1 < irep->nlocals; ++i) { if (irep->lv[i].name) { - mrb_ary_push(mrb, ret, mrb_symbol_value(irep->lv[i].name)); + mrb_hash_set(mrb, vars, mrb_symbol_value(irep->lv[i].name), mrb_true_value()); } } if (proc->env) { @@ -1137,7 +1138,7 @@ mrb_local_variables(mrb_state *mrb, mrb_value self) if (irep->lv) { for (i = 0; i + 1 < irep->nlocals; ++i) { if (irep->lv[i].name) { - mrb_ary_push(mrb, ret, mrb_symbol_value(irep->lv[i].name)); + mrb_hash_set(mrb, vars, mrb_symbol_value(irep->lv[i].name), mrb_true_value()); } } } @@ -1146,7 +1147,7 @@ mrb_local_variables(mrb_state *mrb, mrb_value self) } } - return ret; + return mrb_hash_keys(mrb, vars); } void diff --git a/test/t/kernel.rb b/test/t/kernel.rb index ca4b73907..aff2dd461 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -549,11 +549,10 @@ assert('Kernel.local_variables', '15.3.1.2.7') do vars = Kernel.local_variables.sort assert_equal [:a, :b, :vars], vars - Proc.new { + assert_equal [:a, :b, :c, :vars], Proc.new { |a, b| c = 2 - vars = Kernel.local_variables.sort - assert_equal [:a, :b, :c, :vars], vars - }.call + Kernel.local_variables.sort + }.call(-1, -2) end assert('Kernel#!=') do -- cgit v1.2.3 From 3f9450e7b07bea475dc0ceccda55c216a4a8a2c2 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 12:56:27 +0900 Subject: Move BasicObject#method_missing to Kernel#method_missing; ref #3417 More compatibility to CRuby. Updated tests that assume old mruby behavior. --- src/class.c | 72 ------------------------------------------------- src/kernel.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ test/t/nomethoderror.rb | 20 +++++++------- 3 files changed, 82 insertions(+), 82 deletions(-) (limited to 'test') diff --git a/src/class.c b/src/class.c index 84cc08a10..0b7521e61 100644 --- a/src/class.c +++ b/src/class.c @@ -1486,77 +1486,6 @@ mrb_bob_not(mrb_state *mrb, mrb_value cv) return mrb_bool_value(!mrb_test(cv)); } -void -mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args) -{ - mrb_sym inspect; - mrb_value repr; - - inspect = mrb_intern_lit(mrb, "inspect"); - if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) { - /* method missing in inspect; avoid recursion */ - repr = mrb_any_to_s(mrb, self); - } - else if (mrb_respond_to(mrb, self, inspect) && mrb->c->ci - mrb->c->cibase < 64) { - repr = mrb_funcall_argv(mrb, self, inspect, 0, 0); - if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) { - repr = mrb_any_to_s(mrb, self); - } - } - else { - repr = mrb_any_to_s(mrb, self); - } - - mrb_no_method_error(mrb, name, args, "undefined method '%S' for %S", - mrb_sym2str(mrb, name), repr); -} - -/* 15.3.1.3.30 */ -/* - * call-seq: - * obj.method_missing(symbol [, *args] ) -> result - * - * Invoked by Ruby when obj is sent a message it cannot handle. - * symbol is the symbol for the method called, and args - * are any arguments that were passed to it. By default, the interpreter - * raises an error when this method is called. However, it is possible - * to override the method to provide more dynamic behavior. - * If it is decided that a particular method should not be handled, then - * super should be called, so that ancestors can pick up the - * missing method. - * The example below creates - * a class Roman, which responds to methods with names - * consisting of roman numerals, returning the corresponding integer - * values. - * - * class Roman - * def romanToInt(str) - * # ... - * end - * def method_missing(methId) - * str = methId.id2name - * romanToInt(str) - * end - * end - * - * r = Roman.new - * r.iv #=> 4 - * r.xxiii #=> 23 - * r.mm #=> 2000 - */ -static mrb_value -mrb_bob_missing(mrb_state *mrb, mrb_value mod) -{ - mrb_sym name; - mrb_value *a; - mrb_int alen; - - mrb_get_args(mrb, "n*", &name, &a, &alen); - mrb_method_missing(mrb, name, mod, mrb_ary_new_from_values(mrb, alen, a)); - /* not reached */ - return mrb_nil_value(); -} - MRB_API mrb_bool mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid) { @@ -2306,7 +2235,6 @@ mrb_init_class(mrb_state *mrb) MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS); mrb_define_method(mrb, bob, "initialize", mrb_bob_init, MRB_ARGS_NONE()); mrb_define_method(mrb, bob, "!", mrb_bob_not, MRB_ARGS_NONE()); - mrb_define_method(mrb, bob, "method_missing", mrb_bob_missing, MRB_ARGS_ANY()); /* 15.3.1.3.30 */ mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, MRB_ARGS_OPT(1)); mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, MRB_ARGS_NONE()); /* 15.2.3.3.4 */ diff --git a/src/kernel.c b/src/kernel.c index 02bb3c99b..fd00d0484 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -963,6 +963,77 @@ mrb_obj_remove_instance_variable(mrb_state *mrb, mrb_value self) return val; } +void +mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args) +{ + mrb_sym inspect; + mrb_value repr; + + inspect = mrb_intern_lit(mrb, "inspect"); + if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) { + /* method missing in inspect; avoid recursion */ + repr = mrb_any_to_s(mrb, self); + } + else if (mrb_respond_to(mrb, self, inspect) && mrb->c->ci - mrb->c->cibase < 64) { + repr = mrb_funcall_argv(mrb, self, inspect, 0, 0); + if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) { + repr = mrb_any_to_s(mrb, self); + } + } + else { + repr = mrb_any_to_s(mrb, self); + } + + mrb_no_method_error(mrb, name, args, "undefined method '%S' for %S", + mrb_sym2str(mrb, name), repr); +} + +/* 15.3.1.3.30 */ +/* + * call-seq: + * obj.method_missing(symbol [, *args] ) -> result + * + * Invoked by Ruby when obj is sent a message it cannot handle. + * symbol is the symbol for the method called, and args + * are any arguments that were passed to it. By default, the interpreter + * raises an error when this method is called. However, it is possible + * to override the method to provide more dynamic behavior. + * If it is decided that a particular method should not be handled, then + * super should be called, so that ancestors can pick up the + * missing method. + * The example below creates + * a class Roman, which responds to methods with names + * consisting of roman numerals, returning the corresponding integer + * values. + * + * class Roman + * def romanToInt(str) + * # ... + * end + * def method_missing(methId) + * str = methId.id2name + * romanToInt(str) + * end + * end + * + * r = Roman.new + * r.iv #=> 4 + * r.xxiii #=> 23 + * r.mm #=> 2000 + */ +static mrb_value +mrb_obj_missing(mrb_state *mrb, mrb_value mod) +{ + mrb_sym name; + mrb_value *a; + mrb_int alen; + + mrb_get_args(mrb, "n*", &name, &a, &alen); + mrb_method_missing(mrb, name, mod, mrb_ary_new_from_values(mrb, alen, a)); + /* not reached */ + return mrb_nil_value(); +} + static inline mrb_bool basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub) { @@ -1199,6 +1270,7 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.25 */ mrb_define_method(mrb, krn, "kind_of?", mrb_obj_is_kind_of_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.26 */ mrb_define_method(mrb, krn, "local_variables", mrb_local_variables, MRB_ARGS_NONE()); /* 15.3.1.3.28 */ + mrb_define_method(mrb, krn, "method_missing", mrb_obj_missing, MRB_ARGS_ANY()); /* 15.3.1.3.30 */ mrb_define_method(mrb, krn, "methods", mrb_obj_methods_m, MRB_ARGS_OPT(1)); /* 15.3.1.3.31 */ mrb_define_method(mrb, krn, "nil?", mrb_false, MRB_ARGS_NONE()); /* 15.3.1.3.32 */ mrb_define_method(mrb, krn, "object_id", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.33 */ diff --git a/test/t/nomethoderror.rb b/test/t/nomethoderror.rb index 41a3ba14f..35cbdaee9 100644 --- a/test/t/nomethoderror.rb +++ b/test/t/nomethoderror.rb @@ -21,20 +21,20 @@ assert('NoMethodError#args', '15.2.32.2.1') do end end -assert('Can still raise when BasicObject#method_missing is removed') do +assert('Can still raise when Kernel#method_missing is removed') do assert_raise(NoMethodError) do begin - BasicObject.alias_method(:old_method_missing, :method_missing) - BasicObject.remove_method(:method_missing) + Kernel.alias_method(:old_method_missing, :method_missing) + Kernel.remove_method(:method_missing) 1.__send__(:foo) ensure - BasicObject.alias_method(:method_missing, :old_method_missing) - BasicObject.remove_method(:old_method_missing) + Kernel.alias_method(:method_missing, :old_method_missing) + Kernel.remove_method(:old_method_missing) end end end -assert('Can still call super when BasicObject#method_missing is removed') do +assert('Can still call super when Kernel#method_missing is removed') do assert_raise(NoMethodError) do class A def foo @@ -42,12 +42,12 @@ assert('Can still call super when BasicObject#method_missing is removed') do end end begin - BasicObject.alias_method(:old_method_missing, :method_missing) - BasicObject.remove_method(:method_missing) + Kernel.alias_method(:old_method_missing, :method_missing) + Kernel.remove_method(:method_missing) A.new.foo ensure - BasicObject.alias_method(:method_missing, :old_method_missing) - BasicObject.remove_method(:old_method_missing) + Kernel.alias_method(:method_missing, :old_method_missing) + Kernel.remove_method(:old_method_missing) end end end -- cgit v1.2.3