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 --- src/class.c | 14 +++++++++++++- test/t/module.rb | 12 ++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/class.c b/src/class.c index 47a6c846b..00fc9c12e 100644 --- a/src/class.c +++ b/src/class.c @@ -1773,9 +1773,21 @@ mod_define_method(mrb_state *mrb, mrb_value self) struct RClass *c = mrb_class_ptr(self); struct RProc *p; mrb_sym mid; + mrb_value proc = mrb_undef_value(); mrb_value blk; - mrb_get_args(mrb, "n&", &mid, &blk); + mrb_get_args(mrb, "n|o&", &mid, &proc, &blk); + switch (mrb_type(proc)) { + case MRB_TT_PROC: + blk = proc; + break; + case MRB_TT_UNDEF: + /* ignored */ + break; + default: + mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected Proc)", mrb_obj_value(mrb_obj_class(mrb, proc))); + break; + } if (mrb_nil_p(blk)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); } 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(-) 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 e3c8092ccdd3a9991ccd31634e28e9a5a0e29d91 Mon Sep 17 00:00:00 2001 From: Felix Jones Date: Thu, 10 Nov 2016 19:51:56 +0000 Subject: Renamed class_under_defined to class_defined_under --- include/mruby.h | 8 ++++---- src/class.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/mruby.h b/include/mruby.h index 886b15e50..1b227d41a 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -578,10 +578,10 @@ MRB_API struct RClass * mrb_class_get(mrb_state *mrb, const char *name); * example_outer = mrb_define_module(mrb, "ExampleOuter"); * * example_inner = mrb_define_class_under(mrb, example_outer, "ExampleInner", mrb->object_class); - * cd = mrb_class_under_defined(mrb, example_outer, "ExampleInner"); + * cd = mrb_class_defined_under(mrb, example_outer, "ExampleInner"); * - * // If mrb_class_under_defined returns 1 then puts "True" - * // If mrb_class_under_defined returns 0 then puts "False" + * // If mrb_class_defined_under returns 1 then puts "True" + * // If mrb_class_defined_under returns 0 then puts "False" * if (cd == 1){ * puts("True"); * } @@ -595,7 +595,7 @@ MRB_API struct RClass * mrb_class_get(mrb_state *mrb, const char *name); * @param [const char *] name A string representing the name of the inner class. * @return [mrb_bool] A boolean value. */ -MRB_API mrb_bool mrb_class_under_defined(mrb_state *mrb, struct RClass *outer, const char *name); +MRB_API mrb_bool mrb_class_defined_under(mrb_state *mrb, struct RClass *outer, const char *name); /** * Gets a child class. diff --git a/src/class.c b/src/class.c index ed2e5d5ba..b81859ab8 100644 --- a/src/class.c +++ b/src/class.c @@ -272,7 +272,7 @@ mrb_class_defined(mrb_state *mrb, const char *name) } MRB_API mrb_bool -mrb_class_under_defined(mrb_state *mrb, struct RClass *outer, const char *name) +mrb_class_defined_under(mrb_state *mrb, struct RClass *outer, const char *name) { mrb_value sym = mrb_check_intern_cstr(mrb, name); if (mrb_nil_p(sym)) { -- cgit v1.2.3 From 126d55480d9668a6a313a8e8c428cccfb88d459e Mon Sep 17 00:00:00 2001 From: ksss Date: Fri, 11 Nov 2016 15:49:17 +0900 Subject: Reimplement Enumerable#cycle Fix pattern of infinite loop And support all specs in https://github.com/ruby/spec/blob/27960d06e0ce92c37f074450f0eab4b0519b118c/core/enumerable/cycle_spec.rb without Enumerable#size --- mrbgems/mruby-enum-ext/mrblib/enum.rb | 49 +++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb index a5f661ce6..6724dff37 100644 --- a/mrbgems/mruby-enum-ext/mrblib/enum.rb +++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb @@ -573,35 +573,38 @@ module Enumerable # a.cycle(2) { |x| puts x } # print, a, b, c, a, b, c. # - def cycle(n=nil, &block) - return to_enum(:cycle, n) if !block && n.nil? + def cycle(nv = nil, &block) + return to_enum(:cycle, nv) unless block - ary = [] - if n.nil? - self.each do|*val| - ary.push val - block.call(*val) + n = nil + + if nv.nil? + n = -1 + else + unless nv.respond_to?(:to_int) + raise TypeError, "no implicit conversion of #{nv.class} into Integer" end - loop do - ary.each do|e| - block.call(*e) - end + n = nv.to_int + unless n.kind_of?(Integer) + raise TypeError, "no implicit conversion of #{nv.class} into Integer" end - else - raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) + return nil if n <= 0 + end - n = n.to_int - self.each do|*val| - ary.push val - end - count = 0 - while count < n - ary.each do|e| - block.call(*e) - end - count += 1 + ary = [] + each do |*i| + ary.push(i) + yield(*i) + end + return nil if ary.empty? + + while n < 0 || 0 < (n -= 1) + ary.each do |i| + yield(*i) end end + + nil end ## -- cgit v1.2.3 From 7685783af4872b99265e2ea9c41ac00baf191c30 Mon Sep 17 00:00:00 2001 From: ksss Date: Fri, 11 Nov 2016 15:54:42 +0900 Subject: Add regression test for Enumerable#cycle --- mrbgems/mruby-enum-ext/test/enum.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mrbgems/mruby-enum-ext/test/enum.rb b/mrbgems/mruby-enum-ext/test/enum.rb index 08b553fe5..076562f45 100644 --- a/mrbgems/mruby-enum-ext/test/enum.rb +++ b/mrbgems/mruby-enum-ext/test/enum.rb @@ -128,6 +128,13 @@ assert("Enumerable#cycle") do ["a", "b", "c"].cycle(2) { |v| a << v } assert_equal ["a", "b", "c", "a", "b", "c"], a assert_raise(TypeError) { ["a", "b", "c"].cycle("a") { |v| a << v } } + + empty = Class.new do + include Enumerable + def each + end + end + assert_nil empty.new.cycle { break :nope } end assert("Enumerable#find_index") do -- cgit v1.2.3 From 45aadd7e604c886ba7b96c69fa797a8e2937c711 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 11 Nov 2016 22:49:23 +0900 Subject: HEREDOC could fail with NUL terminated lines; fix#3244 --- mrbgems/mruby-compiler/core/parse.y | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 426c262fb..76fb398e2 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3907,6 +3907,8 @@ parse_string(parser_state *p) int end = (intptr_t)p->lex_strterm->cdr->cdr->cdr; parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL; + if (beg == 0) beg = -3; /* should never happen */ + if (end == 0) end = -3; newtok(p); while ((c = nextc(p)) != end || nest_level != 0) { if (hinf && (c == '\n' || c < 0)) { -- cgit v1.2.3 From 185dad3a6eaf24e106c515bb580807e2b41e1f66 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 11 Nov 2016 22:50:41 +0900 Subject: node_dump() to print NODE_HEREDOC terminator --- mrbgems/mruby-compiler/core/parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 76fb398e2..b23016bd3 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -6506,7 +6506,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset) break; case NODE_HEREDOC: - printf("NODE_HEREDOC:\n"); + printf("NODE_HEREDOC (<<%s):\n", ((parser_heredoc_info*)tree)->term); mrb_parser_dump(mrb, ((parser_heredoc_info*)tree)->doc, offset+1); break; -- cgit v1.2.3 From 752ca514f6e3d9435a8af345fa2481e733a5ddca Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 11 Nov 2016 22:51:48 +0900 Subject: do not dump_node if parser failed --- mrbgems/mruby-compiler/core/parse.y | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index b23016bd3..90b8812b9 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -5479,7 +5479,10 @@ mrb_parser_parse(parser_state *p, mrbc_context *c) p->lex_strterm = NULL; parser_init_cxt(p, c); - yyparse(p); + if (yyparse(p) != 0 || p->nerr > 0) { + p->tree = 0; + return; + } if (!p->tree) { p->tree = new_nil(p); } -- cgit v1.2.3 From 88604e39ac9c25ffdad2e3f03be26516fe866038 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 12 Nov 2016 05:23:05 +0900 Subject: Hash#[] to call Hash#default --- src/hash.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/hash.c b/src/hash.c index 2ad6a9642..015b2d614 100644 --- a/src/hash.c +++ b/src/hash.c @@ -173,10 +173,8 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) /* not found */ if (MRB_RHASH_DEFAULT_P(hash)) { - if (MRB_RHASH_PROCDEFAULT_P(hash)) { - return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key); - } - return RHASH_IFNONE(hash); + /* xxx mrb_funcall_tailcall(mrb, hash, "default", 1, key); */ + return mrb_funcall(mrb, hash, "default", 1, key); } return mrb_nil_value(); } @@ -385,13 +383,16 @@ mrb_hash_default(mrb_state *mrb, mrb_value hash) mrb_bool given; mrb_get_args(mrb, "|o?", &key, &given); - if (MRB_RHASH_PROCDEFAULT_P(hash)) { - if (!given) return mrb_nil_value(); - return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key); - } - else { - return RHASH_IFNONE(hash); + if (MRB_RHASH_DEFAULT_P(hash)) { + if (MRB_RHASH_PROCDEFAULT_P(hash)) { + if (!given) return mrb_nil_value(); + return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key); + } + else { + return RHASH_IFNONE(hash); + } } + return mrb_nil_value(); } /* 15.2.13.4.6 */ -- cgit v1.2.3 From 451985d44be9078660bcb43e4c7d91b3398230a4 Mon Sep 17 00:00:00 2001 From: take_cheeze Date: Sun, 13 Jul 2014 20:46:50 +0900 Subject: Implement Module#name. Solves #2132. --- mrbgems/default.gembox | 3 +++ mrbgems/mruby-module-ext/mrbgem.rake | 5 +++++ mrbgems/mruby-module-ext/src/module.c | 23 +++++++++++++++++++++++ mrbgems/mruby-module-ext/test/module.rb | 10 ++++++++++ 4 files changed, 41 insertions(+) create mode 100644 mrbgems/mruby-module-ext/mrbgem.rake create mode 100644 mrbgems/mruby-module-ext/src/module.c create mode 100644 mrbgems/mruby-module-ext/test/module.rb diff --git a/mrbgems/default.gembox b/mrbgems/default.gembox index 0960ba979..9abbd8512 100644 --- a/mrbgems/default.gembox +++ b/mrbgems/default.gembox @@ -71,6 +71,9 @@ MRuby::GemBox.new do |conf| # Use Kernel module extension conf.gem :core => "mruby-kernel-ext" + # Use extensional Module class + conf.gem :core => "mruby-module-ext" + # Use mruby-compiler to build other mrbgems conf.gem :core => "mruby-compiler" end diff --git a/mrbgems/mruby-module-ext/mrbgem.rake b/mrbgems/mruby-module-ext/mrbgem.rake new file mode 100644 index 000000000..d1f3952ba --- /dev/null +++ b/mrbgems/mruby-module-ext/mrbgem.rake @@ -0,0 +1,5 @@ +MRuby::Gem::Specification.new('mruby-module-ext') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + spec.summary = 'extensional Module class' +end diff --git a/mrbgems/mruby-module-ext/src/module.c b/mrbgems/mruby-module-ext/src/module.c new file mode 100644 index 000000000..74bece800 --- /dev/null +++ b/mrbgems/mruby-module-ext/src/module.c @@ -0,0 +1,23 @@ +#include "mruby.h" +#include "mruby/class.h" +#include "mruby/string.h" + +static mrb_value +mrb_mod_name(mrb_state *mrb, mrb_value self) +{ + mrb_value name = mrb_class_path(mrb, mrb_class_ptr(self)); + return mrb_nil_p(name)? name : mrb_str_dup(mrb, name); +} + +void +mrb_mruby_module_ext_gem_init(mrb_state *mrb) +{ + struct RClass *mod = mrb->module_class; + + mrb_define_method(mrb, mod, "name", mrb_mod_name, MRB_ARGS_NONE()); +} + +void +mrb_mruby_module_ext_gem_final(mrb_state *mrb) +{ +} diff --git a/mrbgems/mruby-module-ext/test/module.rb b/mrbgems/mruby-module-ext/test/module.rb new file mode 100644 index 000000000..f721ad0c6 --- /dev/null +++ b/mrbgems/mruby-module-ext/test/module.rb @@ -0,0 +1,10 @@ +assert 'Module#name' do + module A + class B + end + end + + assert_nil A::B.singleton_class.name + assert_equal 'Fixnum', Fixnum.name + assert_equal 'A::B', A::B.name +end -- cgit v1.2.3 From 01dddaf38525b631c61886758628afe8f04b6356 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 13 Nov 2016 16:11:24 +0900 Subject: rename mruby-module-ext to mruby-class-ext; ref #2470 --- mrbgems/default.gembox | 4 ++-- mrbgems/mruby-class-ext/mrbgem.rake | 5 +++++ mrbgems/mruby-class-ext/src/class.c | 23 +++++++++++++++++++++++ mrbgems/mruby-class-ext/test/module.rb | 10 ++++++++++ mrbgems/mruby-module-ext/mrbgem.rake | 5 ----- mrbgems/mruby-module-ext/src/module.c | 23 ----------------------- mrbgems/mruby-module-ext/test/module.rb | 10 ---------- 7 files changed, 40 insertions(+), 40 deletions(-) create mode 100644 mrbgems/mruby-class-ext/mrbgem.rake create mode 100644 mrbgems/mruby-class-ext/src/class.c create mode 100644 mrbgems/mruby-class-ext/test/module.rb delete mode 100644 mrbgems/mruby-module-ext/mrbgem.rake delete mode 100644 mrbgems/mruby-module-ext/src/module.c delete mode 100644 mrbgems/mruby-module-ext/test/module.rb diff --git a/mrbgems/default.gembox b/mrbgems/default.gembox index 9abbd8512..dab7230aa 100644 --- a/mrbgems/default.gembox +++ b/mrbgems/default.gembox @@ -71,8 +71,8 @@ MRuby::GemBox.new do |conf| # Use Kernel module extension conf.gem :core => "mruby-kernel-ext" - # Use extensional Module class - conf.gem :core => "mruby-module-ext" + # Use class/module extension + conf.gem :core => "mruby-class-ext" # Use mruby-compiler to build other mrbgems conf.gem :core => "mruby-compiler" diff --git a/mrbgems/mruby-class-ext/mrbgem.rake b/mrbgems/mruby-class-ext/mrbgem.rake new file mode 100644 index 000000000..a384b1eef --- /dev/null +++ b/mrbgems/mruby-class-ext/mrbgem.rake @@ -0,0 +1,5 @@ +MRuby::Gem::Specification.new('mruby-class-ext') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + spec.summary = 'class/module extension' +end diff --git a/mrbgems/mruby-class-ext/src/class.c b/mrbgems/mruby-class-ext/src/class.c new file mode 100644 index 000000000..8ca7d66c2 --- /dev/null +++ b/mrbgems/mruby-class-ext/src/class.c @@ -0,0 +1,23 @@ +#include "mruby.h" +#include "mruby/class.h" +#include "mruby/string.h" + +static mrb_value +mrb_mod_name(mrb_state *mrb, mrb_value self) +{ + mrb_value name = mrb_class_path(mrb, mrb_class_ptr(self)); + return mrb_nil_p(name)? name : mrb_str_dup(mrb, name); +} + +void +mrb_mruby_class_ext_gem_init(mrb_state *mrb) +{ + struct RClass *mod = mrb->module_class; + + mrb_define_method(mrb, mod, "name", mrb_mod_name, MRB_ARGS_NONE()); +} + +void +mrb_mruby_class_ext_gem_final(mrb_state *mrb) +{ +} diff --git a/mrbgems/mruby-class-ext/test/module.rb b/mrbgems/mruby-class-ext/test/module.rb new file mode 100644 index 000000000..f721ad0c6 --- /dev/null +++ b/mrbgems/mruby-class-ext/test/module.rb @@ -0,0 +1,10 @@ +assert 'Module#name' do + module A + class B + end + end + + assert_nil A::B.singleton_class.name + assert_equal 'Fixnum', Fixnum.name + assert_equal 'A::B', A::B.name +end diff --git a/mrbgems/mruby-module-ext/mrbgem.rake b/mrbgems/mruby-module-ext/mrbgem.rake deleted file mode 100644 index d1f3952ba..000000000 --- a/mrbgems/mruby-module-ext/mrbgem.rake +++ /dev/null @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-module-ext') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'extensional Module class' -end diff --git a/mrbgems/mruby-module-ext/src/module.c b/mrbgems/mruby-module-ext/src/module.c deleted file mode 100644 index 74bece800..000000000 --- a/mrbgems/mruby-module-ext/src/module.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "mruby.h" -#include "mruby/class.h" -#include "mruby/string.h" - -static mrb_value -mrb_mod_name(mrb_state *mrb, mrb_value self) -{ - mrb_value name = mrb_class_path(mrb, mrb_class_ptr(self)); - return mrb_nil_p(name)? name : mrb_str_dup(mrb, name); -} - -void -mrb_mruby_module_ext_gem_init(mrb_state *mrb) -{ - struct RClass *mod = mrb->module_class; - - mrb_define_method(mrb, mod, "name", mrb_mod_name, MRB_ARGS_NONE()); -} - -void -mrb_mruby_module_ext_gem_final(mrb_state *mrb) -{ -} diff --git a/mrbgems/mruby-module-ext/test/module.rb b/mrbgems/mruby-module-ext/test/module.rb deleted file mode 100644 index f721ad0c6..000000000 --- a/mrbgems/mruby-module-ext/test/module.rb +++ /dev/null @@ -1,10 +0,0 @@ -assert 'Module#name' do - module A - class B - end - end - - assert_nil A::B.singleton_class.name - assert_equal 'Fixnum', Fixnum.name - assert_equal 'A::B', A::B.name -end -- cgit v1.2.3 From 1422e5763005e50ce5f7874910e1a130a12091c9 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 13 Nov 2016 16:12:13 +0900 Subject: move mrb_str_dup() to mrb_class_path; ref #2470 Class#to_s used to return same string repeatedly, that mean you can modify "class name" by modifying the return value from Class#to_s. --- src/class.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class.c b/src/class.c index 7097a593a..d044cb68a 100644 --- a/src/class.c +++ b/src/class.c @@ -1539,7 +1539,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) } mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path); } - return path; + return mrb_str_dup(mrb, path); } MRB_API struct RClass * -- cgit v1.2.3 From 4f6cce059b317f7e6c1da801fe0edd487985df6e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 15 Nov 2016 04:15:24 +0900 Subject: class/module statement should re-open; fix #3225 --- src/class.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/class.c b/src/class.c index d044cb68a..e5d60a693 100644 --- a/src/class.c +++ b/src/class.c @@ -174,6 +174,14 @@ MRB_API struct RClass* mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id) { check_if_class_or_module(mrb, outer); + if (mrb_const_defined_at(mrb, outer, id)) { + mrb_value old = mrb_const_get(mrb, outer, id); + + if (mrb_type(old) != MRB_TT_MODULE) { + mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a module", mrb_inspect(mrb, old)); + } + return mrb_class_ptr(old); + } return define_module(mrb, id, mrb_class_ptr(outer)); } @@ -255,6 +263,21 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id s = 0; } check_if_class_or_module(mrb, outer); + if (mrb_const_defined_at(mrb, outer, id)) { + mrb_value old = mrb_const_get(mrb, outer, id); + + if (mrb_type(old) != MRB_TT_CLASS) { + mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class", mrb_inspect(mrb, old)); + } + c = mrb_class_ptr(old); + if (s) { + /* check super class */ + if (mrb_class_real(c->super) != s) { + mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %S", old); + } + } + return c; + } c = define_class(mrb, id, s, mrb_class_ptr(outer)); mrb_class_inherited(mrb, mrb_class_real(c->super), c); -- cgit v1.2.3 From 739dad6e87e91c74cda794ae3f33cd94a7c33eb1 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 16 Nov 2016 01:29:04 +0900 Subject: Fixed a memory problem in Array#to_h Reported from Alex Snaps via Mathieu Leduc-Hamel, both from shopify.com. Thank you! --- include/mruby/array.h | 9 +++++++++ mrbgems/mruby-array-ext/src/array.c | 2 +- mrbgems/mruby-array-ext/test/array.rb | 11 +++++++++++ src/array.c | 9 --------- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/include/mruby/array.h b/include/mruby/array.h index bd78db066..8f9d5d502 100644 --- a/include/mruby/array.h +++ b/include/mruby/array.h @@ -134,6 +134,15 @@ mrb_ary_len(mrb_state *mrb, mrb_value ary) return RARRAY_LEN(ary); } +static inline mrb_value +ary_elt(mrb_value ary, mrb_int offset) +{ + if (offset < 0 || RARRAY_LEN(ary) <= offset) { + return mrb_nil_value(); + } + return RARRAY_PTR(ary)[offset]; +} + MRB_END_DECL #endif /* MRUBY_ARRAY_H */ diff --git a/mrbgems/mruby-array-ext/src/array.c b/mrbgems/mruby-array-ext/src/array.c index d5c96e2cc..af947303b 100644 --- a/mrbgems/mruby-array-ext/src/array.c +++ b/mrbgems/mruby-array-ext/src/array.c @@ -131,7 +131,7 @@ mrb_ary_to_h(mrb_state *mrb, mrb_value ary) if (mrb_nil_p(v)) { mrb_raisef(mrb, E_TYPE_ERROR, "wrong element type %S at %S (expected array)", - mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, RARRAY_PTR(ary)[i])), + mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, ary_elt(ary, i))), mrb_fixnum_value(i) ); } diff --git a/mrbgems/mruby-array-ext/test/array.rb b/mrbgems/mruby-array-ext/test/array.rb index ec1528fc3..09ec8d9e7 100644 --- a/mrbgems/mruby-array-ext/test/array.rb +++ b/mrbgems/mruby-array-ext/test/array.rb @@ -301,6 +301,17 @@ assert('Array#to_h') do assert_raise(ArgumentError) { [[1]].to_h } end +assert('Array#to_h (Modified)') do + class A + def to_ary + $a.clear + nil + end + end + $a = [A.new] + assert_raise(TypeError) { $a.to_h } +end + assert("Array#index (block)") do assert_nil (1..10).to_a.index { |i| i % 5 == 0 and i % 7 == 0 } assert_equal 34, (1..100).to_a.index { |i| i % 5 == 0 and i % 7 == 0 } diff --git a/src/array.c b/src/array.c index df953832b..e8882b7a3 100644 --- a/src/array.c +++ b/src/array.c @@ -16,15 +16,6 @@ #define ARY_C_MAX_SIZE (SIZE_MAX / sizeof(mrb_value)) #define ARY_MAX_SIZE ((ARY_C_MAX_SIZE < (size_t)MRB_INT_MAX) ? (mrb_int)ARY_C_MAX_SIZE : MRB_INT_MAX-1) -static inline mrb_value -ary_elt(mrb_value ary, mrb_int offset) -{ - if (offset < 0 || RARRAY_LEN(ary) <= offset) { - return mrb_nil_value(); - } - return RARRAY_PTR(ary)[offset]; -} - static struct RArray* ary_new_capa(mrb_state *mrb, mrb_int capa) { -- cgit v1.2.3 From 92f72c749006407db4fa4a4faf123bde4a3043e4 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 16 Nov 2016 02:04:56 +0900 Subject: make String#[]= to take Ranges as position argument --- mrblib/string.rb | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/mrblib/string.rb b/mrblib/string.rb index 37441ec98..f22071b36 100644 --- a/mrblib/string.rb +++ b/mrblib/string.rb @@ -159,16 +159,27 @@ class String anum = args.size if anum == 2 pos, value = args - if pos.kind_of? String + case pos + when String posnum = self.index(pos) if posnum b = self[0, posnum.to_i] a = self[(posnum + pos.length)..-1] self.replace([b, value, a].join('')) - return value else raise IndexError, "string not matched" end + when Range + head = pos.begin + tail = pos.end + tail += self.length if tail < 0 + if pos.exclude_end? + tail -= 1 + end + if tail < 0 || tail > self.length + raise IndexError, "index #{args[0]} out of string" + end + return self[head, tail-head]=value else pos += self.length if pos < 0 if pos < 0 || pos > self.length @@ -177,8 +188,8 @@ class String b = self[0, pos.to_i] a = self[pos + 1..-1] self.replace([b, value, a].join('')) - return value end + return value elsif anum == 3 pos, len, value = args pos += self.length if pos < 0 -- cgit v1.2.3 From 242b21947102d98aba2fa3db2725b129ca547f20 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 16 Nov 2016 02:05:19 +0900 Subject: Fixed memory disclosure in String#lines Reported from from Alex Snaps via Mathieu Leduc-Hamel, both from shopify.com. Thank you! --- mrbgems/mruby-string-ext/src/string.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index 2a52d53b3..122ee5454 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -307,8 +307,9 @@ mrb_str_lines(mrb_state *mrb, mrb_value self) int ai; mrb_int len; mrb_value arg; - char *p = RSTRING_PTR(self), *t; - char *e = p + RSTRING_LEN(self); + char *b = RSTRING_PTR(self); + char *p = b, *t; + char *e = b + RSTRING_LEN(self); mrb_get_args(mrb, "&", &blk); @@ -322,6 +323,12 @@ mrb_str_lines(mrb_state *mrb, mrb_value self) len = (mrb_int) (p - t); arg = mrb_str_new(mrb, t, len); mrb_yield_argv(mrb, blk, 1, &arg); + if (b != RSTRING_PTR(self)) { + ptrdiff_t diff = p - b; + b = RSTRING_PTR(self); + p = b + diff; + } + e = b + RSTRING_LEN(self); } return self; } -- 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(-) 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 1685eff2a5e672173d67916a1c96648df92b7271 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 16 Nov 2016 10:16:14 +0900 Subject: Fixed off-by-one error in String#[]= with Ranges --- mrblib/string.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/mrblib/string.rb b/mrblib/string.rb index f22071b36..aa2ca9973 100644 --- a/mrblib/string.rb +++ b/mrblib/string.rb @@ -173,11 +173,8 @@ class String head = pos.begin tail = pos.end tail += self.length if tail < 0 - if pos.exclude_end? - tail -= 1 - end - if tail < 0 || tail > self.length - raise IndexError, "index #{args[0]} out of string" + unless pos.exclude_end? + tail += 1 end return self[head, tail-head]=value else -- cgit v1.2.3 From 8e0dc6fa8db54d43d6d0dc4b81751cc3db06ebf0 Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Wed, 16 Nov 2016 15:45:47 +0100 Subject: Correct argument specifications for few methods: - Struct#values_at - Module#define_method - String#chop - String#chop! --- mrbgems/mruby-struct/src/struct.c | 2 +- src/class.c | 2 +- src/string.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index 1a06e0c12..0ccb7f4cb 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -703,7 +703,7 @@ mrb_mruby_struct_gem_init(mrb_state* mrb) mrb_define_method(mrb, st, "to_a", mrb_struct_to_a, MRB_ARGS_NONE()); mrb_define_method(mrb, st, "values", mrb_struct_to_a, MRB_ARGS_NONE()); mrb_define_method(mrb, st, "to_h", mrb_struct_to_h, MRB_ARGS_NONE()); - mrb_define_method(mrb, st, "values_at", mrb_struct_values_at, MRB_ARGS_NONE()); + mrb_define_method(mrb, st, "values_at", mrb_struct_values_at, MRB_ARGS_ANY()); } void diff --git a/src/class.c b/src/class.c index e5d60a693..4fc81689b 100644 --- a/src/class.c +++ b/src/class.c @@ -2287,7 +2287,7 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, mod, "constants", mrb_mod_constants, MRB_ARGS_OPT(1)); /* 15.2.2.4.24 */ mrb_define_method(mrb, mod, "remove_const", mrb_mod_remove_const, MRB_ARGS_REQ(1)); /* 15.2.2.4.40 */ mrb_define_method(mrb, mod, "const_missing", mrb_mod_const_missing, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, mod, "define_method", mod_define_method, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, mod, "define_method", mod_define_method, MRB_ARGS_ARG(1,1)); mrb_define_method(mrb, mod, "class_variables", mrb_mod_class_variables, MRB_ARGS_NONE()); /* 15.2.2.4.19 */ mrb_define_method(mrb, mod, "===", mrb_mod_eqq, MRB_ARGS_REQ(1)); mrb_define_class_method(mrb, mod, "constants", mrb_mod_s_constants, MRB_ARGS_ANY()); /* 15.2.2.3.1 */ diff --git a/src/string.c b/src/string.c index 15fcc502a..8c46da2bf 100644 --- a/src/string.c +++ b/src/string.c @@ -2723,8 +2723,8 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "capitalize!", mrb_str_capitalize_bang, MRB_ARGS_NONE()); /* 15.2.10.5.8 */ mrb_define_method(mrb, s, "chomp", mrb_str_chomp, MRB_ARGS_ANY()); /* 15.2.10.5.9 */ mrb_define_method(mrb, s, "chomp!", mrb_str_chomp_bang, MRB_ARGS_ANY()); /* 15.2.10.5.10 */ - mrb_define_method(mrb, s, "chop", mrb_str_chop, MRB_ARGS_REQ(1)); /* 15.2.10.5.11 */ - mrb_define_method(mrb, s, "chop!", mrb_str_chop_bang, MRB_ARGS_REQ(1)); /* 15.2.10.5.12 */ + mrb_define_method(mrb, s, "chop", mrb_str_chop, MRB_ARGS_NONE()); /* 15.2.10.5.11 */ + mrb_define_method(mrb, s, "chop!", mrb_str_chop_bang, MRB_ARGS_NONE()); /* 15.2.10.5.12 */ mrb_define_method(mrb, s, "downcase", mrb_str_downcase, MRB_ARGS_NONE()); /* 15.2.10.5.13 */ mrb_define_method(mrb, s, "downcase!", mrb_str_downcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.14 */ mrb_define_method(mrb, s, "empty?", mrb_str_empty_p, MRB_ARGS_NONE()); /* 15.2.10.5.16 */ -- cgit v1.2.3 From 1ba61f055c51c7fe3aa71e308820a3fe63cb55d0 Mon Sep 17 00:00:00 2001 From: Hiro Asari Date: Wed, 16 Nov 2016 19:41:40 -0500 Subject: Remove webhook notification for Travis CI As travis-rubies now uses 3 Mac jobs to create archives for various OS releases. This is a bit wasteful if multiple builds pass in a short period. Instead, Travis CI is now running a nightly build of mruby-head (around 22:30 UTC). This will happen regardless of the state of the master branch. --- .travis.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 50feac2e0..8d201515c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,11 +16,3 @@ addons: env: MRUBY_CONFIG=travis_config.rb script: "./minirake all test" - -notifications: - # Update mruby-head installed on Travis CI so other projects can test against it. - webhooks: - urls: - - "https://rubies.travis-ci.org/rebuild/mruby-head" - on_success: always - on_failure: never -- 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(+) 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 4cca8bac6bbdab02eba11e6527f793f2e9a5e75d Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Wed, 16 Nov 2016 17:43:55 +0100 Subject: inline structures data type for mruby (MRB_TT_INLINE) (fix #3237) Inline structures have no instance variables, no finalizer, and offer as much space as possible in RBASIC object. This means 24 bytes on 64-bit platforms and 12 bytes on 32-bit platforms. mruby-inline-struct gem is only provided for testing. --- include/mruby/inline.h | 47 +++++++++ include/mruby/value.h | 3 +- mrbgems/default.gembox | 3 + mrbgems/mruby-inline-struct/mrbgem.rake | 5 + mrbgems/mruby-inline-struct/test/inline.c | 83 ++++++++++++++++ mrbgems/mruby-inline-struct/test/inline.rb | 151 +++++++++++++++++++++++++++++ src/class.c | 20 ++++ src/etc.c | 1 + src/kernel.c | 4 + src/object.c | 4 +- 10 files changed, 318 insertions(+), 3 deletions(-) create mode 100644 include/mruby/inline.h create mode 100644 mrbgems/mruby-inline-struct/mrbgem.rake create mode 100644 mrbgems/mruby-inline-struct/test/inline.c create mode 100644 mrbgems/mruby-inline-struct/test/inline.rb diff --git a/include/mruby/inline.h b/include/mruby/inline.h new file mode 100644 index 000000000..e773aa118 --- /dev/null +++ b/include/mruby/inline.h @@ -0,0 +1,47 @@ +/* +** mruby/inline.h - Inline structures +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRUBY_INLINE_H +#define MRUBY_INLINE_H + +#include "common.h" +#include + +/** + * Inline structures that fit in RVALUE + * + * They cannot have finalizer, and cannot have instance variables. + */ +MRB_BEGIN_DECL + +#define INLINE_DATA_SIZE (sizeof(void*) * 3) + +struct RInline { + MRB_OBJECT_HEADER; + char inline_data[INLINE_DATA_SIZE]; +}; + +#define RINLINE(obj) ((struct RInline*)(mrb_ptr(obj))) +#define INLINE_PTR(obj) (RINLINE(obj)->inline_data) + +MRB_INLINE mrb_int mrb_inline_size() +{ + return INLINE_DATA_SIZE; +} + +MRB_INLINE void* mrb_inline_ptr(mrb_value object) +{ + return INLINE_PTR(object); +} + +MRB_INLINE void mrb_inline_copy(mrb_value dest, mrb_value src) +{ + memcpy(INLINE_PTR(dest), INLINE_PTR(src), INLINE_DATA_SIZE); +} + +MRB_END_DECL + +#endif /* MRUBY_INLINE_H */ diff --git a/include/mruby/value.h b/include/mruby/value.h index 4330b9441..eb3f931e1 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -116,7 +116,8 @@ enum mrb_vtype { MRB_TT_ENV, /* 20 */ MRB_TT_DATA, /* 21 */ MRB_TT_FIBER, /* 22 */ - MRB_TT_MAXDEFINE /* 23 */ + MRB_TT_INLINE, /* 23 */ + MRB_TT_MAXDEFINE /* 24 */ }; #include diff --git a/mrbgems/default.gembox b/mrbgems/default.gembox index dab7230aa..e3bd114f3 100644 --- a/mrbgems/default.gembox +++ b/mrbgems/default.gembox @@ -74,6 +74,9 @@ MRuby::GemBox.new do |conf| # Use class/module extension conf.gem :core => "mruby-class-ext" + # Use inline struct + conf.gem :core => "mruby-inline-struct" + # Use mruby-compiler to build other mrbgems conf.gem :core => "mruby-compiler" end diff --git a/mrbgems/mruby-inline-struct/mrbgem.rake b/mrbgems/mruby-inline-struct/mrbgem.rake new file mode 100644 index 000000000..91ad9f44b --- /dev/null +++ b/mrbgems/mruby-inline-struct/mrbgem.rake @@ -0,0 +1,5 @@ +MRuby::Gem::Specification.new('mruby-inline-struct') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + spec.summary = 'inline structure' +end diff --git a/mrbgems/mruby-inline-struct/test/inline.c b/mrbgems/mruby-inline-struct/test/inline.c new file mode 100644 index 000000000..903c08aca --- /dev/null +++ b/mrbgems/mruby-inline-struct/test/inline.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include + +static mrb_value +inline_test_initialize(mrb_state *mrb, mrb_value self) +{ + char *string = mrb_inline_ptr(self); + mrb_int size = mrb_inline_size(); + mrb_value object; + mrb_get_args(mrb, "o", &object); + + if (mrb_float_p(object)) + { + snprintf(string, size, "float(%.3f)", mrb_float(object)); + } + else if (mrb_fixnum_p(object)) + { + snprintf(string, size, "fixnum(%d)", mrb_fixnum(object)); + } + else if (mrb_string_p(object)) + { + snprintf(string, size, "string(%s)", mrb_string_value_cstr(mrb, &object)); + } + + string[size - 1] = 0; // force NULL at the end + return self; +} + +static mrb_value +inline_test_to_s(mrb_state *mrb, mrb_value self) +{ + return mrb_str_new_cstr(mrb, mrb_inline_ptr(self)); +} + +static mrb_value +inline_test_length(mrb_state *mrb, mrb_value self) +{ + return mrb_fixnum_value(mrb_inline_size()); +} + +static mrb_value +inline_test_test_receive(mrb_state *mrb, mrb_value self) +{ + mrb_value object; + mrb_get_args(mrb, "o", &object); + if (mrb_obj_class(mrb, object) != mrb_class_get(mrb, "InlineStructTest")) + { + mrb_raisef(mrb, E_TYPE_ERROR, "Expected InlineStructTest"); + } + return mrb_bool_value(((char*)mrb_inline_ptr(object))[0] == 's'); +} + +static mrb_value +inline_test_test_receive_direct(mrb_state *mrb, mrb_value self) +{ + char *ptr; + mrb_get_args(mrb, "I", &ptr); + return mrb_bool_value(ptr[0] == 's'); +} + +static mrb_value +inline_test_mutate(mrb_state *mrb, mrb_value self) +{ + char *ptr = mrb_inline_ptr(self); + memcpy(ptr, "mutate", 6); + return mrb_nil_value(); +} + +void mrb_mruby_inline_struct_gem_test(mrb_state *mrb) +{ + struct RClass *cls; + + cls = mrb_define_class(mrb, "InlineStructTest", mrb->object_class); + MRB_SET_INSTANCE_TT(cls, MRB_TT_INLINE); + mrb_define_method(mrb, cls, "initialize", inline_test_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, cls, "to_s", inline_test_to_s, MRB_ARGS_NONE()); + mrb_define_method(mrb, cls, "mutate", inline_test_mutate, MRB_ARGS_NONE()); + mrb_define_class_method(mrb, cls, "length", inline_test_length, MRB_ARGS_NONE()); + mrb_define_class_method(mrb, cls, "test_receive", inline_test_test_receive, MRB_ARGS_REQ(1)); + mrb_define_class_method(mrb, cls, "test_receive_direct", inline_test_test_receive_direct, MRB_ARGS_REQ(1)); +} diff --git a/mrbgems/mruby-inline-struct/test/inline.rb b/mrbgems/mruby-inline-struct/test/inline.rb new file mode 100644 index 000000000..495859232 --- /dev/null +++ b/mrbgems/mruby-inline-struct/test/inline.rb @@ -0,0 +1,151 @@ +## +# InlineStruct Test + +class InlineStructTest + def extra_method + :ok + end + + def test_ivar_set + @var = :ivar + end + + def test_ivar_get + @vat + end +end + +assert('InlineStructTest#dup') do + obj = InlineStructTest.new(1) + assert_equal obj.to_s, 'fixnum(1)' + assert_equal obj.dup.to_s, 'fixnum(1)' +end + +assert('InlineStructTest#clone') do + obj = InlineStructTest.new(1) + assert_equal obj.to_s, 'fixnum(1)' + assert_equal obj.clone.to_s, 'fixnum(1)' +end + +assert('InlineStruct#object_id') do + obj1 = InlineStructTest.new(1) + obj2 = InlineStructTest.new(1) + assert_not_equal obj1, obj2 + assert_not_equal obj1.object_id, obj2.object_id + assert_not_equal obj1.object_id, obj1.dup.object_id + assert_not_equal obj1.object_id, obj1.clone.object_id +end + +assert('InlineStructTest#mutate (dup)') do + obj1 = InlineStructTest.new("foo") + assert_equal obj1.to_s, "string(foo)" + obj2 = obj1.dup + assert_equal obj2.to_s, "string(foo)" + obj1.mutate + assert_equal obj1.to_s, "mutate(foo)" + assert_equal obj2.to_s, "string(foo)" +end + +assert('InlineStructTest#mutate (clone)') do + obj1 = InlineStructTest.new("foo") + assert_equal obj1.to_s, "string(foo)" + obj2 = obj1.clone + assert_equal obj2.to_s, "string(foo)" + obj1.mutate + assert_equal obj1.to_s, "mutate(foo)" + assert_equal obj2.to_s, "string(foo)" +end + +assert('InlineStructTest#test_receive(string)') do + assert_equal InlineStructTest.test_receive(InlineStructTest.new('a')), true +end + +assert('InlineStructTest#test_receive(float)') do + assert_equal InlineStructTest.test_receive(InlineStructTest.new(1.25)), false +end + +assert('InlineStructTest#test_receive(invalid object)') do + assert_raise(TypeError) do + InlineStructTest.test_receive([]) + end +end + +assert('InlineStructTest#test_receive(string)') do + assert_equal InlineStructTest.test_receive_direct(InlineStructTest.new('a')), true +end + +assert('InlineStructTest#test_receive(float)') do + assert_equal InlineStructTest.test_receive_direct(InlineStructTest.new(1.25)), false +end + +assert('InlineStructTest#test_receive(invalid object)') do + assert_raise(TypeError) do + InlineStructTest.test_receive_direct([]) + end +end + +assert('InlineStructTest#extra_method') do + assert_equal InlineStructTest.new(1).extra_method, :ok +end + +assert('InlineStructTest instance variable') do + obj = InlineStructTest.new(1) + assert_raise(ArgumentError) do + obj.test_ivar_set + end + assert_equal obj.test_ivar_get, nil +end + +# 64-bit mode +if InlineStructTest.length == 24 + assert('InlineStructTest length [64 bit]') do + assert_equal InlineStructTest.length, 3 * 8 + end + + assert('InlineStructTest w/float [64 bit]') do + obj = InlineStructTest.new(1.25) + assert_equal obj.to_s, "float(1.250)" + end + + assert('InlineStructTest w/fixnum [64 bit]') do + obj = InlineStructTest.new(42) + assert_equal obj.to_s, "fixnum(42)" + end + + assert('InlineStructTest w/string [64 bit]') do + obj = InlineStructTest.new("hello") + assert_equal obj.to_s, "string(hello)" + end + + assert('InlineStructTest w/long string [64 bit]') do + obj = InlineStructTest.new("this won't fit in 3 * 8 bytes available for the structure") + assert_equal obj.to_s, "string(this won't fit i" + end +end + +# 32-bit mode +if InlineStructTest.length == 12 + assert('InlineStructTest length [32 bit]') do + assert_equal InlineStructTest.length, 3 * 4 + end + + assert('InlineStructTest w/float [32 bit]') do + obj = InlineStructTest.new(1.25) + assert_equal obj.to_s, "float(1.250" + end + + assert('InlineStructTest w/fixnum [32 bit]') do + obj = InlineStructTest.new(42) + assert_equal obj.to_s, "fixnum(42)" + end + + assert('InlineStructTest w/string [32 bit]') do + obj = InlineStructTest.new("hello") + assert_equal obj.to_s, "string(hell" + end + + assert('InlineStructTest w/long string [32 bit]') do + obj = InlineStructTest.new("this won't fit in 3 * 4 bytes available for the structure") + assert_equal obj.to_s, "string(this" + end +end diff --git a/src/class.c b/src/class.c index 4fc81689b..53354d02a 100644 --- a/src/class.c +++ b/src/class.c @@ -14,6 +14,7 @@ #include #include #include +#include KHASH_DEFINE(mt, mrb_sym, struct RProc*, TRUE, kh_int_hash_func, kh_int_hash_equal) @@ -491,6 +492,7 @@ to_sym(mrb_state *mrb, mrb_value ss) b: Boolean [mrb_bool] n: Symbol [mrb_sym] d: Data [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified + I: Inline struct [void*] &: Block [mrb_value] *: rest argument [mrb_value*,mrb_int] Receive the rest of the arguments as an array. |: optional Next argument of '|' and later are optional. @@ -702,6 +704,24 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) } } break; + case 'I': + { + void* *p; + mrb_value ss; + + p = va_arg(ap, void**); + if (i < argc) { + ss = ARGV[arg_i]; + if (mrb_type(ss) != MRB_TT_INLINE) + { + mrb_raisef(mrb, E_TYPE_ERROR, "%S is not inline struct", ss); + } + *p = mrb_inline_ptr(ss); + arg_i++; + i++; + } + } + break; case 'f': { mrb_float *p; diff --git a/src/etc.c b/src/etc.c index 183e2f070..c89549da6 100644 --- a/src/etc.c +++ b/src/etc.c @@ -139,6 +139,7 @@ mrb_obj_id(mrb_value obj) case MRB_TT_EXCEPTION: case MRB_TT_FILE: case MRB_TT_DATA: + case MRB_TT_INLINE: default: return MakeID(mrb_ptr(obj)); } diff --git a/src/kernel.c b/src/kernel.c index df237cd46..4a4b6b414 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -11,6 +11,7 @@ #include #include #include +#include typedef enum { NOEX_PUBLIC = 0x00, @@ -301,6 +302,9 @@ init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj) case MRB_TT_EXCEPTION: mrb_iv_copy(mrb, dest, obj); break; + case MRB_TT_INLINE: + mrb_inline_copy(dest, obj); + break; default: break; diff --git a/src/object.c b/src/object.c index bb1a4ebc4..af66d93d0 100644 --- a/src/object.c +++ b/src/object.c @@ -348,7 +348,7 @@ mrb_check_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const { mrb_value v; - if (mrb_type(val) == type && type != MRB_TT_DATA) return val; + if (mrb_type(val) == type && type != MRB_TT_DATA && type != MRB_TT_INLINE) return val; v = convert_type(mrb, val, tname, method, FALSE); if (mrb_nil_p(v) || mrb_type(v) != type) return mrb_nil_value(); return v; @@ -390,7 +390,7 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t) enum mrb_vtype xt; xt = mrb_type(x); - if ((xt != t) || (xt == MRB_TT_DATA)) { + if ((xt != t) || (xt == MRB_TT_DATA) || (xt == MRB_TT_INLINE)) { while (type->type < MRB_TT_MAXDEFINE) { if (type->type == t) { const char *etype; -- cgit v1.2.3 From 8438792d27bac2a236d5eef9824d36f815c0472f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 17 Nov 2016 17:12:11 +0900 Subject: renamed "inline" to "istruct" to represent inline struct; ref #3251 --- include/mruby/inline.h | 47 ------------------------------- include/mruby/istruct.h | 47 +++++++++++++++++++++++++++++++ include/mruby/value.h | 2 +- mrbgems/mruby-inline-struct/test/inline.c | 40 +++++++++++++------------- src/class.c | 6 ++-- src/etc.c | 2 +- src/kernel.c | 6 ++-- src/object.c | 4 +-- 8 files changed, 77 insertions(+), 77 deletions(-) delete mode 100644 include/mruby/inline.h create mode 100644 include/mruby/istruct.h diff --git a/include/mruby/inline.h b/include/mruby/inline.h deleted file mode 100644 index e773aa118..000000000 --- a/include/mruby/inline.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -** mruby/inline.h - Inline structures -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_INLINE_H -#define MRUBY_INLINE_H - -#include "common.h" -#include - -/** - * Inline structures that fit in RVALUE - * - * They cannot have finalizer, and cannot have instance variables. - */ -MRB_BEGIN_DECL - -#define INLINE_DATA_SIZE (sizeof(void*) * 3) - -struct RInline { - MRB_OBJECT_HEADER; - char inline_data[INLINE_DATA_SIZE]; -}; - -#define RINLINE(obj) ((struct RInline*)(mrb_ptr(obj))) -#define INLINE_PTR(obj) (RINLINE(obj)->inline_data) - -MRB_INLINE mrb_int mrb_inline_size() -{ - return INLINE_DATA_SIZE; -} - -MRB_INLINE void* mrb_inline_ptr(mrb_value object) -{ - return INLINE_PTR(object); -} - -MRB_INLINE void mrb_inline_copy(mrb_value dest, mrb_value src) -{ - memcpy(INLINE_PTR(dest), INLINE_PTR(src), INLINE_DATA_SIZE); -} - -MRB_END_DECL - -#endif /* MRUBY_INLINE_H */ diff --git a/include/mruby/istruct.h b/include/mruby/istruct.h new file mode 100644 index 000000000..293a13788 --- /dev/null +++ b/include/mruby/istruct.h @@ -0,0 +1,47 @@ +/* +** mruby/instruct.h - Inline structures +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRUBY_ISTRUCT_H +#define MRUBY_ISTRUCT_H + +#include "common.h" +#include + +/** + * Inline structures that fit in RVALUE + * + * They cannot have finalizer, and cannot have instance variables. + */ +MRB_BEGIN_DECL + +#define ISTRUCT_DATA_SIZE (sizeof(void*) * 3) + +struct RIstruct { + MRB_OBJECT_HEADER; + char inline_data[ISTRUCT_DATA_SIZE]; +}; + +#define RISTRUCT(obj) ((struct RIstruct*)(mrb_ptr(obj))) +#define ISTRUCT_PTR(obj) (RISTRUCT(obj)->inline_data) + +MRB_INLINE mrb_int mrb_istruct_size() +{ + return ISTRUCT_DATA_SIZE; +} + +MRB_INLINE void* mrb_istruct_ptr(mrb_value object) +{ + return ISTRUCT_PTR(object); +} + +MRB_INLINE void mrb_istruct_copy(mrb_value dest, mrb_value src) +{ + memcpy(ISTRUCT_PTR(dest), ISTRUCT_PTR(src), ISTRUCT_DATA_SIZE); +} + +MRB_END_DECL + +#endif /* MRUBY_ISTRUCT_H */ diff --git a/include/mruby/value.h b/include/mruby/value.h index eb3f931e1..6b29ab273 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -116,7 +116,7 @@ enum mrb_vtype { MRB_TT_ENV, /* 20 */ MRB_TT_DATA, /* 21 */ MRB_TT_FIBER, /* 22 */ - MRB_TT_INLINE, /* 23 */ + MRB_TT_ISTRUCT, /* 23 */ MRB_TT_MAXDEFINE /* 24 */ }; diff --git a/mrbgems/mruby-inline-struct/test/inline.c b/mrbgems/mruby-inline-struct/test/inline.c index 903c08aca..49ef31d00 100644 --- a/mrbgems/mruby-inline-struct/test/inline.c +++ b/mrbgems/mruby-inline-struct/test/inline.c @@ -1,13 +1,13 @@ #include #include #include -#include +#include static mrb_value -inline_test_initialize(mrb_state *mrb, mrb_value self) +istruct_test_initialize(mrb_state *mrb, mrb_value self) { - char *string = mrb_inline_ptr(self); - mrb_int size = mrb_inline_size(); + char *string = mrb_istruct_ptr(self); + mrb_int size = mrb_istruct_size(); mrb_value object; mrb_get_args(mrb, "o", &object); @@ -29,19 +29,19 @@ inline_test_initialize(mrb_state *mrb, mrb_value self) } static mrb_value -inline_test_to_s(mrb_state *mrb, mrb_value self) +istruct_test_to_s(mrb_state *mrb, mrb_value self) { - return mrb_str_new_cstr(mrb, mrb_inline_ptr(self)); + return mrb_str_new_cstr(mrb, mrb_istruct_ptr(self)); } static mrb_value -inline_test_length(mrb_state *mrb, mrb_value self) +istruct_test_length(mrb_state *mrb, mrb_value self) { - return mrb_fixnum_value(mrb_inline_size()); + return mrb_fixnum_value(mrb_istruct_size()); } static mrb_value -inline_test_test_receive(mrb_state *mrb, mrb_value self) +istruct_test_test_receive(mrb_state *mrb, mrb_value self) { mrb_value object; mrb_get_args(mrb, "o", &object); @@ -49,11 +49,11 @@ inline_test_test_receive(mrb_state *mrb, mrb_value self) { mrb_raisef(mrb, E_TYPE_ERROR, "Expected InlineStructTest"); } - return mrb_bool_value(((char*)mrb_inline_ptr(object))[0] == 's'); + return mrb_bool_value(((char*)mrb_istruct_ptr(object))[0] == 's'); } static mrb_value -inline_test_test_receive_direct(mrb_state *mrb, mrb_value self) +istruct_test_test_receive_direct(mrb_state *mrb, mrb_value self) { char *ptr; mrb_get_args(mrb, "I", &ptr); @@ -61,9 +61,9 @@ inline_test_test_receive_direct(mrb_state *mrb, mrb_value self) } static mrb_value -inline_test_mutate(mrb_state *mrb, mrb_value self) +istruct_test_mutate(mrb_state *mrb, mrb_value self) { - char *ptr = mrb_inline_ptr(self); + char *ptr = mrb_istruct_ptr(self); memcpy(ptr, "mutate", 6); return mrb_nil_value(); } @@ -73,11 +73,11 @@ void mrb_mruby_inline_struct_gem_test(mrb_state *mrb) struct RClass *cls; cls = mrb_define_class(mrb, "InlineStructTest", mrb->object_class); - MRB_SET_INSTANCE_TT(cls, MRB_TT_INLINE); - mrb_define_method(mrb, cls, "initialize", inline_test_initialize, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, cls, "to_s", inline_test_to_s, MRB_ARGS_NONE()); - mrb_define_method(mrb, cls, "mutate", inline_test_mutate, MRB_ARGS_NONE()); - mrb_define_class_method(mrb, cls, "length", inline_test_length, MRB_ARGS_NONE()); - mrb_define_class_method(mrb, cls, "test_receive", inline_test_test_receive, MRB_ARGS_REQ(1)); - mrb_define_class_method(mrb, cls, "test_receive_direct", inline_test_test_receive_direct, MRB_ARGS_REQ(1)); + MRB_SET_INSTANCE_TT(cls, MRB_TT_ISTRUCT); + mrb_define_method(mrb, cls, "initialize", istruct_test_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, cls, "to_s", istruct_test_to_s, MRB_ARGS_NONE()); + mrb_define_method(mrb, cls, "mutate", istruct_test_mutate, MRB_ARGS_NONE()); + mrb_define_class_method(mrb, cls, "length", istruct_test_length, MRB_ARGS_NONE()); + mrb_define_class_method(mrb, cls, "test_receive", istruct_test_test_receive, MRB_ARGS_REQ(1)); + mrb_define_class_method(mrb, cls, "test_receive_direct", istruct_test_test_receive_direct, MRB_ARGS_REQ(1)); } diff --git a/src/class.c b/src/class.c index 53354d02a..d02253c57 100644 --- a/src/class.c +++ b/src/class.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include KHASH_DEFINE(mt, mrb_sym, struct RProc*, TRUE, kh_int_hash_func, kh_int_hash_equal) @@ -712,11 +712,11 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) p = va_arg(ap, void**); if (i < argc) { ss = ARGV[arg_i]; - if (mrb_type(ss) != MRB_TT_INLINE) + if (mrb_type(ss) != MRB_TT_ISTRUCT) { mrb_raisef(mrb, E_TYPE_ERROR, "%S is not inline struct", ss); } - *p = mrb_inline_ptr(ss); + *p = mrb_istruct_ptr(ss); arg_i++; i++; } diff --git a/src/etc.c b/src/etc.c index c89549da6..e0810d589 100644 --- a/src/etc.c +++ b/src/etc.c @@ -139,7 +139,7 @@ mrb_obj_id(mrb_value obj) case MRB_TT_EXCEPTION: case MRB_TT_FILE: case MRB_TT_DATA: - case MRB_TT_INLINE: + case MRB_TT_ISTRUCT: default: return MakeID(mrb_ptr(obj)); } diff --git a/src/kernel.c b/src/kernel.c index 4a4b6b414..8b1ef80a0 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include typedef enum { NOEX_PUBLIC = 0x00, @@ -302,8 +302,8 @@ init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj) case MRB_TT_EXCEPTION: mrb_iv_copy(mrb, dest, obj); break; - case MRB_TT_INLINE: - mrb_inline_copy(dest, obj); + case MRB_TT_ISTRUCT: + mrb_istruct_copy(dest, obj); break; default: diff --git a/src/object.c b/src/object.c index af66d93d0..392432b0f 100644 --- a/src/object.c +++ b/src/object.c @@ -348,7 +348,7 @@ mrb_check_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const { mrb_value v; - if (mrb_type(val) == type && type != MRB_TT_DATA && type != MRB_TT_INLINE) return val; + if (mrb_type(val) == type && type != MRB_TT_DATA && type != MRB_TT_ISTRUCT) return val; v = convert_type(mrb, val, tname, method, FALSE); if (mrb_nil_p(v) || mrb_type(v) != type) return mrb_nil_value(); return v; @@ -390,7 +390,7 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t) enum mrb_vtype xt; xt = mrb_type(x); - if ((xt != t) || (xt == MRB_TT_DATA) || (xt == MRB_TT_INLINE)) { + if ((xt != t) || (xt == MRB_TT_DATA) || (xt == MRB_TT_ISTRUCT)) { while (type->type < MRB_TT_MAXDEFINE) { if (type->type == t) { const char *etype; -- cgit v1.2.3 From 2e8ed9514feb74f4137e5835e74f256d52d6f191 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 17 Nov 2016 17:12:43 +0900 Subject: Removed mruby-inline-struct gem from default.gembox; ref #3251 bundled testing gems do not need to be included in default.gembox. all gems under mrbgems are linked automatically in the test process. --- mrbgems/default.gembox | 3 --- 1 file changed, 3 deletions(-) diff --git a/mrbgems/default.gembox b/mrbgems/default.gembox index e3bd114f3..dab7230aa 100644 --- a/mrbgems/default.gembox +++ b/mrbgems/default.gembox @@ -74,9 +74,6 @@ MRuby::GemBox.new do |conf| # Use class/module extension conf.gem :core => "mruby-class-ext" - # Use inline struct - conf.gem :core => "mruby-inline-struct" - # Use mruby-compiler to build other mrbgems conf.gem :core => "mruby-compiler" end -- cgit v1.2.3 From 92be276d761ac7e2e7bd1ebe14625d9443b23eb3 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 17 Nov 2016 18:00:21 +0900 Subject: String#{strip,lstrip,rstrip} may cause OOB access --- mrbgems/mruby-string-ext/mrblib/string.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mrbgems/mruby-string-ext/mrblib/string.rb b/mrbgems/mruby-string-ext/mrblib/string.rb index c3b765a5f..e6fbe7ddc 100644 --- a/mrbgems/mruby-string-ext/mrblib/string.rb +++ b/mrbgems/mruby-string-ext/mrblib/string.rb @@ -45,7 +45,7 @@ class String def lstrip a = 0 z = self.size - 1 - a += 1 while " \f\n\r\t\v".include?(self[a]) and a <= z + a += 1 while a <= z and " \f\n\r\t\v".include?(self[a]) (z >= 0) ? self[a..z] : "" end @@ -62,7 +62,7 @@ class String def rstrip a = 0 z = self.size - 1 - z -= 1 while " \f\n\r\t\v\0".include?(self[z]) and a <= z + z -= 1 while a <= z and " \f\n\r\t\v\0".include?(self[z]) (z >= 0) ? self[a..z] : "" end @@ -78,8 +78,8 @@ class String def strip a = 0 z = self.size - 1 - a += 1 while " \f\n\r\t\v".include?(self[a]) and a <= z - z -= 1 while " \f\n\r\t\v\0".include?(self[z]) and a <= z + a += 1 while a <= z and " \f\n\r\t\v".include?(self[a]) + z -= 1 while a <= z and " \f\n\r\t\v\0".include?(self[z]) (z >= 0) ? self[a..z] : "" end -- 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(-) 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 c043dc631e9734ea8d55ee579a52a878e540f44d Mon Sep 17 00:00:00 2001 From: Herwin Weststrate Date: Thu, 17 Nov 2016 11:05:27 +0100 Subject: Typo fix: poped => popped --- include/mruby/array.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mruby/array.h b/include/mruby/array.h index 8f9d5d502..4d767eecb 100644 --- a/include/mruby/array.h +++ b/include/mruby/array.h @@ -84,8 +84,8 @@ MRB_API void mrb_ary_push(mrb_state *mrb, mrb_value array, mrb_value value); * ary.pop * * @param mrb The mruby state reference. - * @param ary The array from which the value will be poped. - * @return The poped value. + * @param ary The array from which the value will be popped. + * @return The popped value. */ MRB_API mrb_value mrb_ary_pop(mrb_state *mrb, mrb_value ary); -- cgit v1.2.3 From d20c56c7fa8084595c8cddb30fa37596f3142095 Mon Sep 17 00:00:00 2001 From: Herwin Weststrate Date: Thu, 17 Nov 2016 11:38:56 +0100 Subject: Documented most methods in mruby/array.h --- include/mruby/array.h | 123 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 118 insertions(+), 5 deletions(-) diff --git a/include/mruby/array.h b/include/mruby/array.h index 4d767eecb..e553faf92 100644 --- a/include/mruby/array.h +++ b/include/mruby/array.h @@ -54,14 +54,60 @@ MRB_API mrb_value mrb_ary_new_capa(mrb_state*, mrb_int); * Array.new * * @param mrb The mruby state reference. - * @return The initialized array + * @return The initialized array. */ MRB_API mrb_value mrb_ary_new(mrb_state *mrb); +/* + * Initializes a new array with initial values + * + * Equivalent to: + * + * Array[value1, value2, ...] + * + * @param mrb The mruby state reference. + * @param size The numer of values. + * @param vals The actual values. + * @return The initialized array. + */ MRB_API mrb_value mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals); + +/* + * Initializes a new array with two initial values + * + * Equivalent to: + * + * Array[car, cdr] + * + * @param mrb The mruby state reference. + * @param car The first value. + * @param cdr The second value. + * @return The initialized array. + */ MRB_API mrb_value mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr); -MRB_API void mrb_ary_concat(mrb_state*, mrb_value, mrb_value); -MRB_API mrb_value mrb_ary_splat(mrb_state*, mrb_value); + +/* + * Concatenate two arrays. The target array will be modified + * + * Equivalent to: + * ary.concat(other) + * + * @param mrb The mruby state reference. + * @param self The target array. + * @param other The array that will be concatenated to self. + */ +MRB_API void mrb_ary_concat(mrb_state *mrb, mrb_value self, mrb_value other); + +/* + * Create an array from the input. It tries calling to_a on the + * value. If value does not respond to that, it creates a new + * array with just this value. + * + * @param mrb The mruby state reference. + * @param value The value to change into an array. + * @return An array representation of value. + */ +MRB_API mrb_value mrb_ary_splat(mrb_state *mrb, mrb_value value); /* * Pushes value into array. @@ -117,14 +163,81 @@ MRB_API mrb_value mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n); */ MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val); -MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value a, mrb_value b); +/* + * Replace the array with another array + * + * Equivalent to: + * + * ary.replace(other) + * + * @param mrb The mruby state reference + * @param self The target array. + * @param other The array to replace it with. + */ +MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other); MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self); + +/* + * Unshift an element into an array + * + * Equivalent to: + * + * ary.unshift(item) + * + * @param mrb The mruby state reference. + * @param self The target array. + * @param item The item to unshift. + */ MRB_API mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item); MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset); + +/* + * Shifts the first element from the array. + * + * Equivalent to: + * + * ary.shift + * + * @param mrb The mruby state reference. + * @param self The array from which the value will be shifted. + * @return The shifted value. + */ MRB_API mrb_value mrb_ary_shift(mrb_state *mrb, mrb_value self); + +/* + * Removes all elements from this array + * + * Equivalent to: + * + * ary.clear + * + * @param mrb The mruby state reference. + * @param self The target array. + * @return self + */ MRB_API mrb_value mrb_ary_clear(mrb_state *mrb, mrb_value self); + +/* + * Join the array elements together in a string + * + * Equivalent to: + * + * ary.join(sep="") + * + * @param mrb The mruby state reference. + * @param ary The target array + * @param sep The separater, can be NULL + */ MRB_API mrb_value mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep); -MRB_API mrb_value mrb_ary_resize(mrb_state *mrb, mrb_value ary, mrb_int len); + +/* + * Update the capacity of the array + * + * @param mrb The mruby state reference. + * @param ary The target array. + * @param new_len The new capacity of the array + */ +MRB_API mrb_value mrb_ary_resize(mrb_state *mrb, mrb_value ary, mrb_int new_len); static inline mrb_int mrb_ary_len(mrb_state *mrb, mrb_value ary) -- cgit v1.2.3 From 18d6994f78a98c92cf4e07ad8ad75449f7a075b3 Mon Sep 17 00:00:00 2001 From: Herwin Weststrate Date: Thu, 17 Nov 2016 11:49:52 +0100 Subject: Documented most methods in mruby/hash.h --- include/mruby/hash.h | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/include/mruby/hash.h b/include/mruby/hash.h index 922353322..55ad6a921 100644 --- a/include/mruby/hash.h +++ b/include/mruby/hash.h @@ -28,40 +28,126 @@ MRB_API mrb_value mrb_hash_new_capa(mrb_state*, int); /* * Initializes a new hash. + * + * Equivalent to: + * + * Hash.new + * + * @param mrb The mruby state reference. + * @return The initialized hash. */ MRB_API mrb_value mrb_hash_new(mrb_state *mrb); /* * Sets a keys and values to hashes. + * + * Equivalent to: + * + * hash[key] = val + * + * @param mrb The mruby state reference. + * @param hash The target hash. + * @param key The key to set. + * @param val The value to set. + * @return The value. */ MRB_API void mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val); /* - * Gets a value from a key. + * Gets a value from a key. If the key is not found, the default of the + * hash is used. + * + * Equivalent to: + * + * hash[key] + * + * @param mrb The mruby state reference. + * @param hash The target hash. + * @param key The key to get. + * @return The found value. */ MRB_API mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key); +/* + * Gets a value from a key. If the key is not found, the default parameter is + * used. + * + * Equivalent to: + * + * hash.hash_key?(key) ? hash[key] : def + * + * @param mrb The mruby state reference. + * @param hash The target hash. + * @param key The key to get. + * @param def The default value. + * @return The found value. + */ MRB_API mrb_value mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def); /* * Deletes hash key and value pair. + * + * Equivalent to: + * + * hash.delete(key) + * + * @param mrb The mruby state reference. + * @param hash The target hash. + * @param key The key to delete. + * @return The deleted value. */ MRB_API mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key); /* * Gets an array of keys. + * + * Equivalent to: + * + * hash.keys + * + * @param mrb The mruby state reference. + * @param hash The target hash. + * @return An array with the keys of the hash. */ MRB_API mrb_value mrb_hash_keys(mrb_state *mrb, mrb_value hash); MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash); + +/* + * Check if the hash is empty + * + * Equivalent to: + * + * hash.empty? + * + * @param mrb The mruby state reference. + * @param self The target hash. + * @return True if the hash is empty, false otherwise. + */ MRB_API mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self); /* * Gets an array of values. + * + * Equivalent to: + * + * hash.values + * + * @param mrb The mruby state reference. + * @param hash The target hash. + * @return An array with the values of the hash. */ MRB_API mrb_value mrb_hash_values(mrb_state *mrb, mrb_value hash); /* * Clears the hash. + * + * Equivalent to: + * + * hash.clear + * + * @param mrb The mruby state reference. + * @param hash The target hash. + * @return The hash */ MRB_API mrb_value mrb_hash_clear(mrb_state *mrb, mrb_value hash); -- 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(-) 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 0ff3ae1fbaed62010c54c43235e29cdc85da2f78 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 18 Nov 2016 11:54:24 +0900 Subject: Range#include?: simplify condition; ref #3255 --- src/range.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/range.c b/src/range.c index 4efae1f93..f0a976e53 100644 --- a/src/range.c +++ b/src/range.c @@ -230,9 +230,9 @@ mrb_range_include(mrb_state *mrb, mrb_value range) beg = r->edges->beg; end = r->edges->end; - include_p = r_le(mrb, beg, val) && /* beg <= val */ - ((r->excl && r_gt(mrb, end, val)) || /* end > val */ - (!r->excl && r_ge(mrb, end, val))); /* end >= val */ + 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 */ return mrb_bool_value(include_p); } -- cgit v1.2.3 From a2fbd80a473071f76687dda5fda7dbbea7efde9f Mon Sep 17 00:00:00 2001 From: ksss Date: Sat, 19 Nov 2016 09:29:22 +0900 Subject: Fix Range#size results --- mrbgems/mruby-range-ext/src/range.c | 27 ++++++++++++++++++++------- mrbgems/mruby-range-ext/test/range.rb | 2 ++ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/mrbgems/mruby-range-ext/src/range.c b/mrbgems/mruby-range-ext/src/range.c index 4d6f1684f..87bdab228 100644 --- a/mrbgems/mruby-range-ext/src/range.c +++ b/mrbgems/mruby-range-ext/src/range.c @@ -1,6 +1,7 @@ #include #include #include +#include static mrb_bool r_le(mrb_state *mrb, mrb_value a, mrb_value b) @@ -140,9 +141,11 @@ mrb_range_size(mrb_state *mrb, mrb_value range) mrb_value beg, end; double beg_f, end_f; mrb_bool num_p = TRUE; + mrb_bool excl; beg = r->edges->beg; end = r->edges->end; + excl = r->excl; if (mrb_fixnum_p(beg)) { beg_f = (double)mrb_fixnum(beg); } @@ -162,14 +165,24 @@ mrb_range_size(mrb_state *mrb, mrb_value range) num_p = FALSE; } if (num_p) { - double f; - - if (beg_f > end_f) return mrb_fixnum_value(0); - f = end_f - beg_f; - if (!r->excl) { - return mrb_fixnum_value((mrb_int)ceil(f + 1)); + double n = end_f - beg_f; + double err = (fabs(beg_f) + fabs(end_f) + fabs(end_f-beg_f)) * DBL_EPSILON; + + if (err>0.5) err=0.5; + if (excl) { + if (n<=0) return mrb_fixnum_value(0); + if (n<1) + n = 0; + else + n = floor(n - err); + } + else { + if (n<0) return mrb_fixnum_value(0); + n = floor(n + err); } - return mrb_fixnum_value((mrb_int)ceil(f)); + if (isinf(n+1)) + return mrb_float_value(mrb, INFINITY); + return mrb_fixnum_value(n+1); } return mrb_nil_value(); } diff --git a/mrbgems/mruby-range-ext/test/range.rb b/mrbgems/mruby-range-ext/test/range.rb index 18e7dafe4..ea1e12f2e 100644 --- a/mrbgems/mruby-range-ext/test/range.rb +++ b/mrbgems/mruby-range-ext/test/range.rb @@ -25,5 +25,7 @@ assert('Range#size') do assert_equal 6, (1...6.3).size assert_equal 5, (1...6.0).size assert_equal 5, (1.1...6).size + assert_equal 15, (1.0..15.9).size + assert_equal Float::INFINITY, (0..Float::INFINITY).size assert_nil ('a'..'z').size end -- cgit v1.2.3 From 22390aa1c8e17135e1d298e5e66776c77234c0b5 Mon Sep 17 00:00:00 2001 From: ksss Date: Sat, 19 Nov 2016 23:24:20 +0900 Subject: Use mrb_float instead of double --- mrbgems/mruby-range-ext/src/range.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mrbgems/mruby-range-ext/src/range.c b/mrbgems/mruby-range-ext/src/range.c index 87bdab228..1d9312b03 100644 --- a/mrbgems/mruby-range-ext/src/range.c +++ b/mrbgems/mruby-range-ext/src/range.c @@ -139,7 +139,7 @@ mrb_range_size(mrb_state *mrb, mrb_value range) { struct RRange *r = mrb_range_ptr(range); mrb_value beg, end; - double beg_f, end_f; + mrb_float beg_f, end_f; mrb_bool num_p = TRUE; mrb_bool excl; @@ -147,7 +147,7 @@ mrb_range_size(mrb_state *mrb, mrb_value range) end = r->edges->end; excl = r->excl; if (mrb_fixnum_p(beg)) { - beg_f = (double)mrb_fixnum(beg); + beg_f = (mrb_float)mrb_fixnum(beg); } else if (mrb_float_p(beg)) { beg_f = mrb_float(beg); @@ -156,7 +156,7 @@ mrb_range_size(mrb_state *mrb, mrb_value range) num_p = FALSE; } if (mrb_fixnum_p(end)) { - end_f = (double)mrb_fixnum(end); + end_f = (mrb_float)mrb_fixnum(end); } else if (mrb_float_p(end)) { end_f = mrb_float(end); @@ -165,8 +165,8 @@ mrb_range_size(mrb_state *mrb, mrb_value range) num_p = FALSE; } if (num_p) { - double n = end_f - beg_f; - double err = (fabs(beg_f) + fabs(end_f) + fabs(end_f-beg_f)) * DBL_EPSILON; + mrb_float n = end_f - beg_f; + mrb_float err = (fabs(beg_f) + fabs(end_f) + fabs(end_f-beg_f)) * DBL_EPSILON; if (err>0.5) err=0.5; if (excl) { -- cgit v1.2.3 From 4289e0cd8126ef963a7aec459f24785de5ee422e Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Mon, 21 Nov 2016 00:37:03 +0100 Subject: Fix for sprintf test exceeding bounds with MRB_INT16 --- mrbgems/mruby-sprintf/test/sprintf.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgems/mruby-sprintf/test/sprintf.rb b/mrbgems/mruby-sprintf/test/sprintf.rb index 454c226e1..478581a49 100644 --- a/mrbgems/mruby-sprintf/test/sprintf.rb +++ b/mrbgems/mruby-sprintf/test/sprintf.rb @@ -5,5 +5,5 @@ assert('String#%') do assert_equal "one=1", "one=%d" % 1 assert_equal "1 one 1.0", "%d %s %3.1f" % [ 1, "one", 1.01 ] assert_equal "123 < 456", "%{num} < %s" % { num: 123, str: "456" } - assert_equal 16, ("%b" % (1<<15)).size + assert_equal 15, ("%b" % (1<<14)).size end -- cgit v1.2.3 From 682237be6ecabe9f35e7a7a1cb16a1eb54b69fb9 Mon Sep 17 00:00:00 2001 From: ksss Date: Mon, 21 Nov 2016 12:39:21 +0900 Subject: Reimplements Range#first Range#first shouldn't call `Range#to_a` on infinity range. --- mrbgems/mruby-range-ext/mrblib/range.rb | 31 +++++++++++++++++++++++++++++++ mrbgems/mruby-range-ext/src/range.c | 27 --------------------------- mrbgems/mruby-range-ext/test/range.rb | 1 + 3 files changed, 32 insertions(+), 27 deletions(-) create mode 100644 mrbgems/mruby-range-ext/mrblib/range.rb diff --git a/mrbgems/mruby-range-ext/mrblib/range.rb b/mrbgems/mruby-range-ext/mrblib/range.rb new file mode 100644 index 000000000..3b9c3874a --- /dev/null +++ b/mrbgems/mruby-range-ext/mrblib/range.rb @@ -0,0 +1,31 @@ +class Range + ## + # call-seq: + # rng.first -> obj + # rng.first(n) -> an_array + # + # Returns the first object in the range, or an array of the first +n+ + # elements. + # + # (10..20).first #=> 10 + # (10..20).first(3) #=> [10, 11, 12] + # + def first(*args) + return self.begin if args.empty? + + raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 1)" unless args.length == 1 + nv = args[0] + raise TypeError, "no implicit conversion from nil to integer" unless nv.nil?.! + raise TypeError, "no implicit conversion of #{nv.class} into Integer" unless nv.respond_to?(:to_int) + n = nv.to_int + raise TypeError, "no implicit conversion of #{nv.class} into Integer" unless n.kind_of?(Integer) + raise ArgumentError, "negative array size (or size too big)" unless 0 <= n + ary = [] + each do |i| + break if n <= 0 + ary.push(i) + n -= 1 + end + ary + end +end diff --git a/mrbgems/mruby-range-ext/src/range.c b/mrbgems/mruby-range-ext/src/range.c index 1d9312b03..32222a594 100644 --- a/mrbgems/mruby-range-ext/src/range.c +++ b/mrbgems/mruby-range-ext/src/range.c @@ -66,32 +66,6 @@ mrb_range_cover(mrb_state *mrb, mrb_value range) return mrb_false_value(); } -/* - * call-seq: - * rng.first -> obj - * rng.first(n) -> an_array - * - * Returns the first object in the range, or an array of the first +n+ - * elements. - * - * (10..20).first #=> 10 - * (10..20).first(3) #=> [10, 11, 12] - */ -static mrb_value -mrb_range_first(mrb_state *mrb, mrb_value range) -{ - mrb_int num; - mrb_value array; - struct RRange *r = mrb_range_ptr(range); - - if (mrb_get_args(mrb, "|i", &num) == 0) { - return r->edges->beg; - } - - array = mrb_funcall(mrb, range, "to_a", 0); - return mrb_funcall(mrb, array, "first", 1, mrb_fixnum_value(num)); -} - /* * call-seq: * rng.last -> obj @@ -193,7 +167,6 @@ mrb_mruby_range_ext_gem_init(mrb_state* mrb) struct RClass * s = mrb_class_get(mrb, "Range"); mrb_define_method(mrb, s, "cover?", mrb_range_cover, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, s, "first", mrb_range_first, MRB_ARGS_OPT(1)); mrb_define_method(mrb, s, "last", mrb_range_last, MRB_ARGS_OPT(1)); mrb_define_method(mrb, s, "size", mrb_range_size, MRB_ARGS_NONE()); } diff --git a/mrbgems/mruby-range-ext/test/range.rb b/mrbgems/mruby-range-ext/test/range.rb index ea1e12f2e..efcbdabe4 100644 --- a/mrbgems/mruby-range-ext/test/range.rb +++ b/mrbgems/mruby-range-ext/test/range.rb @@ -10,6 +10,7 @@ end assert('Range#first') do assert_equal 10, (10..20).first assert_equal [10, 11, 12], (10..20).first(3) + assert_equal [0, 1, 2], (0..Float::INFINITY).first(3) end assert('Range#last') do -- cgit v1.2.3 From d86f5d2dca3d17e1dc114085a0cd9a32d61f3014 Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Mon, 21 Nov 2016 12:35:09 +0100 Subject: mruby architecture detection --- include/mrbconf.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/include/mrbconf.h b/include/mrbconf.h index ab5dd1a03..d47f46ae4 100644 --- a/include/mrbconf.h +++ b/include/mrbconf.h @@ -7,6 +7,20 @@ #ifndef MRUBYCONF_H #define MRUBYCONF_H +/* architecture selection: */ +/* specify -DMRB_32BIT or -DMRB_64BIT to override */ +#if !defined(MRB_32BIT) && !defined(MRB_64BIT) +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) || defined(__aarch64__) +#define MRB_64BIT +#else +#define MRB_32BIT +#endif +#endif + +#if defined(MRB_32BIT) && defined(MRB_64BIT) +#error Cannot build for 32 and 64 bit architecture at the same time +#endif + /* configuration options: */ /* add -DMRB_USE_FLOAT to use float instead of double for floating point numbers */ //#define MRB_USE_FLOAT -- cgit v1.2.3 From 8cdaf1ed35e808f73fe06c84998ffa59d414f8cc Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Mon, 21 Nov 2016 12:02:52 +0100 Subject: Fixed NaN boxing for 64-bit configrations on platforms that use full 48-bit usermode pointers Definition of boxed pointer is following: `111111111111TTTT TTPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP` Previously, only the last 32-bit were set, and remaining 14 bits were zeroed when setting `ttt`. --- include/mruby/boxing_nan.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/mruby/boxing_nan.h b/include/mruby/boxing_nan.h index b71c4b746..154150ece 100644 --- a/include/mruby/boxing_nan.h +++ b/include/mruby/boxing_nan.h @@ -60,6 +60,12 @@ typedef struct mrb_value { #define mrb_fixnum(o) (o).value.i #define mrb_symbol(o) (o).value.sym +#ifdef MRB_64BIT +#define BOXNAN_SHIFT_LONG_POINTER(v) (((uintptr_t)(v)>>34)&0x3fff) +#else +#define BOXNAN_SHIFT_LONG_POINTER(v) 0 +#endif + #define BOXNAN_SET_VALUE(o, tt, attr, v) do {\ switch (tt) {\ case MRB_TT_FALSE:\ @@ -69,7 +75,7 @@ typedef struct mrb_value { case MRB_TT_SYMBOL: (o).attr = (v); break;\ default: (o).value.i = 0; (o).value.p = (void*)((uintptr_t)(o).value.p | (((uintptr_t)(v))>>2)); break;\ }\ - (o).value.ttt = (0xfff00000|(((tt)+1)<<14));\ + (o).value.ttt = (0xfff00000|(((tt)+1)<<14)|BOXNAN_SHIFT_LONG_POINTER(v));\ } while (0) #define SET_FLOAT_VALUE(mrb,r,v) do { \ -- cgit v1.2.3 From c385782cfef484ca9cb07b128d325cfb712de69c Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Mon, 21 Nov 2016 12:03:45 +0100 Subject: mrb_assert definition moved to the beggining of mruby.h So that other files can immediately use it. --- include/mruby.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/include/mruby.h b/include/mruby.h index 1b227d41a..e6eaf7f27 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -32,6 +32,21 @@ #include #include +#ifdef MRB_DEBUG +#include +#define mrb_assert(p) assert(p) +#define mrb_assert_int_fit(t1,n,t2,max) assert((n)>=0 && ((sizeof(n)<=sizeof(t2))||(n<=(t1)(max)))) +#else +#define mrb_assert(p) ((void)0) +#define mrb_assert_int_fit(t1,n,t2,max) ((void)0) +#endif + +#if __STDC_VERSION__ >= 201112L +#define mrb_static_assert(exp, str) _Static_assert(exp, str) +#else +#define mrb_static_assert(exp, str) mrb_assert(exp) +#endif + #include "mrbconf.h" #include "mruby/common.h" #include @@ -1135,21 +1150,6 @@ MRB_API void mrb_state_atexit(mrb_state *mrb, mrb_atexit_func func); MRB_API void mrb_show_version(mrb_state *mrb); MRB_API void mrb_show_copyright(mrb_state *mrb); -#ifdef MRB_DEBUG -#include -#define mrb_assert(p) assert(p) -#define mrb_assert_int_fit(t1,n,t2,max) assert((n)>=0 && ((sizeof(n)<=sizeof(t2))||(n<=(t1)(max)))) -#else -#define mrb_assert(p) ((void)0) -#define mrb_assert_int_fit(t1,n,t2,max) ((void)0) -#endif - -#if __STDC_VERSION__ >= 201112L -#define mrb_static_assert(exp, str) _Static_assert(exp, str) -#else -#define mrb_static_assert(exp, str) mrb_assert(exp) -#endif - MRB_API mrb_value mrb_format(mrb_state *mrb, const char *format, ...); MRB_END_DECL -- cgit v1.2.3 From b21b02465e6643879394b41494a3462079347a92 Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Mon, 21 Nov 2016 12:04:49 +0100 Subject: asserts checking validity of pointer and TT added for mrb_obj_value Useful for testing when using boxing on different platforms. --- include/mruby/value.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/mruby/value.h b/include/mruby/value.h index 6b29ab273..61110e3dd 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -211,6 +211,8 @@ mrb_obj_value(void *p) { mrb_value v; SET_OBJ_VALUE(v, (struct RBasic*)p); + mrb_assert(p == mrb_ptr(v)); + mrb_assert(((struct RBasic*)p)->tt == mrb_type(v)); return v; } -- 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(-) 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 a70104798ee72c08ee64d28b0d5dd6e93e7b76c6 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 22 Nov 2016 16:55:18 +0900 Subject: remove unnecessary ".!"; ref #3261 --- mrbgems/mruby-range-ext/mrblib/range.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgems/mruby-range-ext/mrblib/range.rb b/mrbgems/mruby-range-ext/mrblib/range.rb index 3b9c3874a..e5d1fb079 100644 --- a/mrbgems/mruby-range-ext/mrblib/range.rb +++ b/mrbgems/mruby-range-ext/mrblib/range.rb @@ -15,7 +15,7 @@ class Range raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 1)" unless args.length == 1 nv = args[0] - raise TypeError, "no implicit conversion from nil to integer" unless nv.nil?.! + raise TypeError, "no implicit conversion from nil to integer" if nv.nil? raise TypeError, "no implicit conversion of #{nv.class} into Integer" unless nv.respond_to?(:to_int) n = nv.to_int raise TypeError, "no implicit conversion of #{nv.class} into Integer" unless n.kind_of?(Integer) -- cgit v1.2.3 From 740bf09740388b09714b5cdf70d9eec61d6cf4bd Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 22 Nov 2016 17:36:26 +0900 Subject: add bit operators ~,&,|,^ to Float class (mruby special) --- src/numeric.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/numeric.c b/src/numeric.c index 327d54177..62ad3dde8 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -271,6 +271,77 @@ flo_eq(mrb_state *mrb, mrb_value x) } } +static int64_t +value_int64(mrb_state *mrb, mrb_value x) +{ + switch (mrb_type(x)) { + case MRB_TT_FIXNUM: + return (int64_t)mrb_fixnum(x); + break; + case MRB_TT_FLOAT: + return (int64_t)mrb_float(x); + default: + mrb_raise(mrb, E_TYPE_ERROR, "cannot convert to Integer"); + break; + } + /* not reached */ + return 0; +} + +static mrb_value +int64_value(mrb_state *mrb, int64_t v) +{ + if (MRB_INT_MIN <= v && v <= MRB_INT_MAX) { + return mrb_fixnum_value((mrb_int)v); + } + return mrb_float_value(mrb, (mrb_float)v); +} + +static mrb_value +flo_rev(mrb_state *mrb, mrb_value x) +{ + int64_t v1; + mrb_get_args(mrb, ""); + v1 = (int64_t)mrb_float(x); + return int64_value(mrb, ~v1); +} + +static mrb_value +flo_and(mrb_state *mrb, mrb_value x) +{ + mrb_value y; + int64_t v1, v2; + mrb_get_args(mrb, "o", &y); + + v1 = (int64_t)mrb_float(x); + v2 = value_int64(mrb, y); + return int64_value(mrb, v1 & v2); +} + +static mrb_value +flo_or(mrb_state *mrb, mrb_value x) +{ + mrb_value y; + int64_t v1, v2; + mrb_get_args(mrb, "o", &y); + + v1 = (int64_t)mrb_float(x); + v2 = value_int64(mrb, y); + return int64_value(mrb, v1 | v2); +} + +static mrb_value +flo_xor(mrb_state *mrb, mrb_value x) +{ + mrb_value y; + int64_t v1, v2; + mrb_get_args(mrb, "o", &y); + + v1 = (int64_t)mrb_float(x); + v2 = value_int64(mrb, y); + return int64_value(mrb, v1 ^ v2); +} + /* 15.2.8.3.18 */ /* * call-seq: @@ -1199,6 +1270,10 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, fl, "*", flo_mul, MRB_ARGS_REQ(1)); /* 15.2.9.3.3 */ mrb_define_method(mrb, fl, "%", flo_mod, MRB_ARGS_REQ(1)); /* 15.2.9.3.5 */ mrb_define_method(mrb, fl, "==", flo_eq, MRB_ARGS_REQ(1)); /* 15.2.9.3.7 */ + mrb_define_method(mrb, fl, "~", flo_rev, MRB_ARGS_NONE()); + mrb_define_method(mrb, fl, "&", flo_and, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, fl, "|", flo_or, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, fl, "^", flo_xor, MRB_ARGS_REQ(1)); mrb_define_method(mrb, fl, "ceil", flo_ceil, MRB_ARGS_NONE()); /* 15.2.9.3.8 */ mrb_define_method(mrb, fl, "finite?", flo_finite_p, MRB_ARGS_NONE()); /* 15.2.9.3.9 */ mrb_define_method(mrb, fl, "floor", flo_floor, MRB_ARGS_NONE()); /* 15.2.9.3.10 */ -- cgit v1.2.3 From 81122950317117f21b858294fa56d0d1e37436fe Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 22 Nov 2016 17:45:07 +0900 Subject: Removed fix_shift_get_width() Fixnum is usually big enough for shift width. --- src/numeric.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/numeric.c b/src/numeric.c index 62ad3dde8..7779cd652 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -921,15 +921,6 @@ rshift(mrb_int val, mrb_int width) return mrb_fixnum_value(val >> width); } -static inline void -fix_shift_get_width(mrb_state *mrb, mrb_int *width) -{ - mrb_value y; - - mrb_get_args(mrb, "o", &y); - *width = mrb_fixnum(bit_coerce(mrb, y)); -} - /* 15.2.8.3.12 */ /* * call-seq: @@ -943,8 +934,7 @@ fix_lshift(mrb_state *mrb, mrb_value x) { mrb_int width, val; - fix_shift_get_width(mrb, &width); - + mrb_get_args(mrb, "i", &width); if (width == 0) { return x; } @@ -968,8 +958,7 @@ fix_rshift(mrb_state *mrb, mrb_value x) { mrb_int width, val; - fix_shift_get_width(mrb, &width); - + mrb_get_args(mrb, "i", &width); if (width == 0) { return x; } -- cgit v1.2.3 From be73905c9c3ab8f684551506da219b170ee9c6dc Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 22 Nov 2016 17:57:16 +0900 Subject: accept floats as bit operator operands; fix #3260 --- src/numeric.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/numeric.c b/src/numeric.c index 7779cd652..9902b0b94 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -809,17 +809,13 @@ fix_rev(mrb_state *mrb, mrb_value num) return mrb_fixnum_value(~val); } -static mrb_value -bit_coerce(mrb_state *mrb, mrb_value x) -{ - while (!mrb_fixnum_p(x)) { - if (mrb_float_p(x)) { - mrb_raise(mrb, E_TYPE_ERROR, "can't convert Float into Integer"); - } - x = mrb_to_int(mrb, x); - } - return x; -} +static mrb_value flo_and(mrb_state *mrb, mrb_value x); +static mrb_value flo_or(mrb_state *mrb, mrb_value x); +static mrb_value flo_xor(mrb_state *mrb, mrb_value x); +#define bit_op(x,y,op1,op2) do {\ + if (mrb_fixnum_p(y)) return mrb_fixnum_value(mrb_fixnum(x) op2 mrb_fixnum(y));\ + return flo_ ## op1(mrb, mrb_float_value(mrb, mrb_fixnum(x)));\ +} while(0) /* 15.2.8.3.9 */ /* @@ -835,9 +831,7 @@ fix_and(mrb_state *mrb, mrb_value x) mrb_value y; mrb_get_args(mrb, "o", &y); - - y = bit_coerce(mrb, y); - return mrb_fixnum_value(mrb_fixnum(x) & mrb_fixnum(y)); + bit_op(x, y, and, &); } /* 15.2.8.3.10 */ @@ -854,9 +848,7 @@ fix_or(mrb_state *mrb, mrb_value x) mrb_value y; mrb_get_args(mrb, "o", &y); - - y = bit_coerce(mrb, y); - return mrb_fixnum_value(mrb_fixnum(x) | mrb_fixnum(y)); + bit_op(x, y, or, |); } /* 15.2.8.3.11 */ @@ -873,9 +865,7 @@ fix_xor(mrb_state *mrb, mrb_value x) mrb_value y; mrb_get_args(mrb, "o", &y); - - y = bit_coerce(mrb, y); - return mrb_fixnum_value(mrb_fixnum(x) ^ mrb_fixnum(y)); + bit_op(x, y, or, ^); } #define NUMERIC_SHIFT_WIDTH_MAX (MRB_INT_BIT-1) -- 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(-) 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 8cba708854205ab8f2b6f8aed9aff12085131f12 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 22 Nov 2016 19:11:54 +0900 Subject: int64_value(): use FIXABLE() --- src/numeric.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/numeric.c b/src/numeric.c index 9902b0b94..cdf8c8afb 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -291,7 +291,7 @@ value_int64(mrb_state *mrb, mrb_value x) static mrb_value int64_value(mrb_state *mrb, int64_t v) { - if (MRB_INT_MIN <= v && v <= MRB_INT_MAX) { + if (FIXABLE(v)) { return mrb_fixnum_value((mrb_int)v); } return mrb_float_value(mrb, (mrb_float)v); -- cgit v1.2.3 From 52b40cb4d0e78cf58592c2e38db1df65b2dd9041 Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Tue, 22 Nov 2016 13:34:40 +0100 Subject: Fixed extern "C" to use MRB_BEGIN/END_DECL in re.h --- include/mruby/re.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/include/mruby/re.h b/include/mruby/re.h index dfb3b0e2d..1d09d06c9 100644 --- a/include/mruby/re.h +++ b/include/mruby/re.h @@ -7,14 +7,10 @@ #ifndef MRUBY_RE_H #define MRUBY_RE_H -#ifdef __cplusplus -extern "C" { -#endif +MRB_BEGIN_DECL #define REGEXP_CLASS "Regexp" -#ifdef __cplusplus -} -#endif +MRB_END_DECL #endif /* RE_H */ -- cgit v1.2.3 From efebbbbf260e8ac5b8efbd0d4336a777cfeac514 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 23 Nov 2016 09:45:50 +0900 Subject: Implement Float shift methods in C --- mrblib/numeric.rb | 30 +----------------------------- src/numeric.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 29 deletions(-) diff --git a/mrblib/numeric.rb b/mrblib/numeric.rb index 6e4c5027f..17155bfd6 100644 --- a/mrblib/numeric.rb +++ b/mrblib/numeric.rb @@ -160,35 +160,7 @@ end # # ISO 15.2.9 class Float - include Integral # mruby special - since mruby integers may be upgraded to floats, # floats should be compatible to integers. - def >> other - n = self.to_i - other = other.to_i - if other < 0 - n << -other - else - other.times { n /= 2 } - if n.abs < 1 - if n >= 0 - 0 - else - -1 - end - else - n.to_i - end - end - end - def << other - n = self.to_i - other = other.to_i - if other < 0 - n >> -other - else - other.times { n *= 2 } - n - end - end + include Integral end diff --git a/src/numeric.c b/src/numeric.c index cdf8c8afb..c86373318 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -15,6 +15,7 @@ #include #ifdef MRB_USE_FLOAT +#define trunc(f) truncf(f) #define floor(f) floorf(f) #define ceil(f) ceilf(f) #define fmod(x,y) fmodf(x,y) @@ -342,6 +343,53 @@ flo_xor(mrb_state *mrb, mrb_value x) return int64_value(mrb, v1 ^ v2); } +static mrb_value +flo_shift(mrb_state *mrb, mrb_value x, mrb_int width) +{ + mrb_float val; + + if (width == 0) { + return x; + } + val = mrb_float(x); + if (width < 0) { + while (width++) { + val /= 2; + } + val = trunc(val); + if (val == 0 && mrb_float(x) < 0) { + return mrb_fixnum_value(-1); + } + } + else { + while (width--) { + val *= 2; + } + } + if (FIXABLE(val)) { + return mrb_fixnum_value(val); + } + return mrb_float_value(mrb, val); +} + +static mrb_value +flo_lshift(mrb_state *mrb, mrb_value x) +{ + mrb_int width; + + mrb_get_args(mrb, "i", &width); + return flo_shift(mrb, x, -width); +} + +static mrb_value +flo_rshift(mrb_state *mrb, mrb_value x) +{ + mrb_int width; + + mrb_get_args(mrb, "i", &width); + return flo_shift(mrb, x, width); +} + /* 15.2.8.3.18 */ /* * call-seq: @@ -1253,6 +1301,8 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, fl, "&", flo_and, MRB_ARGS_REQ(1)); mrb_define_method(mrb, fl, "|", flo_or, MRB_ARGS_REQ(1)); mrb_define_method(mrb, fl, "^", flo_xor, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, fl, ">>", flo_lshift, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, fl, "<<", flo_rshift, MRB_ARGS_REQ(1)); mrb_define_method(mrb, fl, "ceil", flo_ceil, MRB_ARGS_NONE()); /* 15.2.9.3.8 */ mrb_define_method(mrb, fl, "finite?", flo_finite_p, MRB_ARGS_NONE()); /* 15.2.9.3.9 */ mrb_define_method(mrb, fl, "floor", flo_floor, MRB_ARGS_NONE()); /* 15.2.9.3.10 */ -- cgit v1.2.3 From bfbc6b9ea48355785c236826e3a1a217b668aee2 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 23 Nov 2016 20:50:14 +0900 Subject: local_variables() should not touch unshared env --- src/kernel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/kernel.c b/src/kernel.c index 8b1ef80a0..74254e636 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -1078,7 +1078,8 @@ mrb_local_variables(mrb_state *mrb, mrb_value self) struct REnv *e = proc->env; while (e) { - if (!MRB_PROC_CFUNC_P(mrb->c->cibase[e->cioff].proc)) { + if (MRB_ENV_STACK_SHARED_P(e) && + !MRB_PROC_CFUNC_P(mrb->c->cibase[e->cioff].proc)) { irep = mrb->c->cibase[e->cioff].proc->body.irep; if (irep->lv) { for (i = 0; i + 1 < irep->nlocals; ++i) { -- cgit v1.2.3 From 669bbc70b0553b68483c8d7eff8c31a602f283e9 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 23 Nov 2016 21:08:35 +0900 Subject: codegen_scope should not keep old iseq ptr from irep --- mrbgems/mruby-compiler/core/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 9b064b867..85ca21dd4 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2713,7 +2713,7 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) p->icapa = 1024; p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa); - p->irep->iseq = p->iseq; + p->irep->iseq = NULL; p->pcapa = 32; p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa); -- cgit v1.2.3 From c7262be0aeaf55b5c92b26db82c08f2fe6b95412 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Wed, 23 Nov 2016 11:21:14 -0500 Subject: Fix segfault in Array#sample --- mrbgems/mruby-random/src/random.c | 3 ++- mrbgems/mruby-random/test/random.rb | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index 3b8d0dd2f..587e6c01a 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -266,7 +266,7 @@ mrb_ary_sample(mrb_state *mrb, mrb_value ary) mrb_int n = 0; mrb_bool given; mt_state *random = NULL; - mrb_int len = RARRAY_LEN(ary); + mrb_int len; mrb_get_args(mrb, "|i?d", &n, &given, &random, &mt_state_type); if (random == NULL) { @@ -274,6 +274,7 @@ mrb_ary_sample(mrb_state *mrb, mrb_value ary) } mrb_random_rand_seed(mrb, random); mt_rand(random); + len = RARRAY_LEN(ary); if (!given) { /* pick one element */ switch (len) { case 0: diff --git a/mrbgems/mruby-random/test/random.rb b/mrbgems/mruby-random/test/random.rb index 1653ae4a6..1c59be3a6 100644 --- a/mrbgems/mruby-random/test/random.rb +++ b/mrbgems/mruby-random/test/random.rb @@ -74,3 +74,15 @@ assert('Array#shuffle!(random)') do ary1 != [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and 10.times { |x| ary1.include? x } and ary1 == ary2 end + +assert('Array#sample checks input length after reading arguments') do + $ary = [1, 2, 3] + class ArrayChange + def to_i + $ary << 4 + 4 + end + end + + assert_equal [1, 2, 3, 4], $ary.sample(ArrayChange.new).sort +end -- cgit v1.2.3 From 9bf1c0e1dc09d9aa577554d58d91f3889a77b918 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Wed, 23 Nov 2016 15:18:52 -0500 Subject: Fix segfault when Fixnum#chr doesn't return a string --- mrbgems/mruby-sprintf/src/sprintf.c | 1 + mrbgems/mruby-sprintf/test/sprintf.rb | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index 8d14b0fc5..ccee23bd2 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -675,6 +675,7 @@ retry: else { mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid character"); } + mrb_check_type(mrb, tmp, MRB_TT_STRING); c = RSTRING_PTR(tmp); n = RSTRING_LEN(tmp); if (!(flags & FWIDTH)) { diff --git a/mrbgems/mruby-sprintf/test/sprintf.rb b/mrbgems/mruby-sprintf/test/sprintf.rb index 478581a49..ccbd95d51 100644 --- a/mrbgems/mruby-sprintf/test/sprintf.rb +++ b/mrbgems/mruby-sprintf/test/sprintf.rb @@ -7,3 +7,26 @@ assert('String#%') do assert_equal "123 < 456", "%{num} < %s" % { num: 123, str: "456" } assert_equal 15, ("%b" % (1<<14)).size end + +assert("String#% with invalid chr") do + begin + class Fixnum + alias_method :chr_, :chr if method_defined?(:chr) + + def chr + nil + end + end + + assert_raise TypeError do + "%c" % 0 + end + ensure + class Fixnum + if method_defined?(:chr_) + alias_method :chr, :chr_ + remove_method :chr_ + end + end + end +end -- cgit v1.2.3 From 1af9e363f28810e46e263cd13da918cdf779d71d Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Tue, 22 Nov 2016 13:19:05 +0100 Subject: Fixes for compiling mruby as C++ --- include/mruby.h | 16 ++++++++++++++++ include/mruby/boxing_nan.h | 2 +- mrbgems/mruby-inline-struct/test/inline.c | 6 +++--- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 2 +- mrbgems/mruby-sprintf/src/sprintf.c | 12 ++++++------ src/backtrace.c | 4 ++-- src/string.c | 2 +- 7 files changed, 30 insertions(+), 14 deletions(-) diff --git a/include/mruby.h b/include/mruby.h index e6eaf7f27..d40dce6d9 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -28,10 +28,26 @@ #ifndef MRUBY_H #define MRUBY_H +#ifdef __cplusplus +#define __STDC_LIMIT_MACROS +#define __STDC_CONSTANT_MACROS +#define __STDC_FORMAT_MACROS +#endif + #include #include #include +#ifdef __cplusplus +#ifndef SIZE_MAX +#ifdef __SIZE_MAX__ +#define SIZE_MAX __SIZE_MAX__ +#else +#define SIZE_MAX std::numeric_limits::max() +#endif +#endif +#endif + #ifdef MRB_DEBUG #include #define mrb_assert(p) assert(p) diff --git a/include/mruby/boxing_nan.h b/include/mruby/boxing_nan.h index 154150ece..052164ffc 100644 --- a/include/mruby/boxing_nan.h +++ b/include/mruby/boxing_nan.h @@ -53,7 +53,7 @@ typedef struct mrb_value { #define mrb_float_pool(mrb,f) mrb_float_value(mrb,f) #define mrb_tt(o) ((enum mrb_vtype)(((o).value.ttt & 0xfc000)>>14)-1) -#define mrb_type(o) ((uint32_t)0xfff00000 < (o).value.ttt ? mrb_tt(o) : MRB_TT_FLOAT) +#define mrb_type(o) (enum mrb_vtype)((uint32_t)0xfff00000 < (o).value.ttt ? mrb_tt(o) : MRB_TT_FLOAT) #define mrb_ptr(o) ((void*)((((uintptr_t)0x3fffffffffff)&((uintptr_t)((o).value.p)))<<2)) #define mrb_float(o) (o).f #define mrb_cptr(o) mrb_ptr(o) diff --git a/mrbgems/mruby-inline-struct/test/inline.c b/mrbgems/mruby-inline-struct/test/inline.c index 49ef31d00..772248e9b 100644 --- a/mrbgems/mruby-inline-struct/test/inline.c +++ b/mrbgems/mruby-inline-struct/test/inline.c @@ -6,7 +6,7 @@ static mrb_value istruct_test_initialize(mrb_state *mrb, mrb_value self) { - char *string = mrb_istruct_ptr(self); + char *string = (char*)mrb_istruct_ptr(self); mrb_int size = mrb_istruct_size(); mrb_value object; mrb_get_args(mrb, "o", &object); @@ -31,7 +31,7 @@ istruct_test_initialize(mrb_state *mrb, mrb_value self) static mrb_value istruct_test_to_s(mrb_state *mrb, mrb_value self) { - return mrb_str_new_cstr(mrb, mrb_istruct_ptr(self)); + return mrb_str_new_cstr(mrb, (const char*)mrb_istruct_ptr(self)); } static mrb_value @@ -63,7 +63,7 @@ istruct_test_test_receive_direct(mrb_state *mrb, mrb_value self) static mrb_value istruct_test_mutate(mrb_state *mrb, mrb_value self) { - char *ptr = mrb_istruct_ptr(self); + char *ptr = (char*)mrb_istruct_ptr(self); memcpy(ptr, "mutate", 6); return mrb_nil_value(); } diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index d5cd4f5a1..d0a8effd0 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -49,7 +49,7 @@ static mrb_value os_count_objects(mrb_state *mrb, mrb_value self) { struct os_count_struct obj_count = { 0 }; - enum mrb_vtype i; + mrb_int i; mrb_value hash; if (mrb_get_args(mrb, "|H", &hash) == 0) { diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index ccee23bd2..696d0939f 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -844,13 +844,13 @@ retry: strncpy(nbuf, RSTRING_PTR(val), sizeof(nbuf)); break; case 8: - snprintf(nbuf, sizeof(nbuf), "%"MRB_PRIo, v); + snprintf(nbuf, sizeof(nbuf), "%" MRB_PRIo, v); break; case 10: - snprintf(nbuf, sizeof(nbuf), "%"MRB_PRId, v); + snprintf(nbuf, sizeof(nbuf), "%" MRB_PRId, v); break; case 16: - snprintf(nbuf, sizeof(nbuf), "%"MRB_PRIx, v); + snprintf(nbuf, sizeof(nbuf), "%" MRB_PRIx, v); break; } s = nbuf; @@ -865,13 +865,13 @@ retry: strncpy(++s, RSTRING_PTR(val), sizeof(nbuf)-1); break; case 8: - snprintf(++s, sizeof(nbuf)-1, "%"MRB_PRIo, v); + snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRIo, v); break; case 10: - snprintf(++s, sizeof(nbuf)-1, "%"MRB_PRId, v); + snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRId, v); break; case 16: - snprintf(++s, sizeof(nbuf)-1, "%"MRB_PRIx, v); + snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRIx, v); break; } if (v < 0) { diff --git a/src/backtrace.c b/src/backtrace.c index 11082b705..285af562f 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -160,7 +160,7 @@ static void output_backtrace_i(mrb_state *mrb, struct backtrace_location_raw *loc_raw, void *data) { struct backtrace_location loc; - struct output_backtrace_args *args = data; + struct output_backtrace_args *args = (struct output_backtrace_args *)data; loc.i = loc_raw->i; loc.lineno = loc_raw->lineno; @@ -338,7 +338,7 @@ save_backtrace_i(mrb_state *mrb, else { new_n_allocated = mrb->backtrace.n_allocated * 2; } - mrb->backtrace.entries = + mrb->backtrace.entries = (mrb_backtrace_entry *) mrb_realloc(mrb, mrb->backtrace.entries, sizeof(mrb_backtrace_entry) * new_n_allocated); diff --git a/src/string.c b/src/string.c index f8ab9478f..5e490bf03 100644 --- a/src/string.c +++ b/src/string.c @@ -361,7 +361,7 @@ mrb_memsearch(const void *x0, mrb_int m, const void *y0, mrb_int n) return 0; } else if (m == 1) { - const unsigned char *ys = memchr(y, *x, n); + const unsigned char *ys = (const unsigned char *)memchr(y, *x, n); if (ys) return ys - y; -- cgit v1.2.3 From 401ad4586ffe8bc26740f49f9049132ad2c50539 Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Tue, 22 Nov 2016 13:59:11 +0100 Subject: Add constant export declaration for MRBC output compiled as C++ Otherwise, C++ compilers will skip this constant when producing object files. --- src/dump.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dump.c b/src/dump.c index ea1cd5596..45c595d3b 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1059,6 +1059,7 @@ mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, con return MRB_DUMP_WRITE_FAULT; } if (fprintf(fp, + "extern const uint8_t %s[];\n" "const uint8_t\n" "#if defined __GNUC__\n" "__attribute__((aligned(%u)))\n" @@ -1066,6 +1067,7 @@ mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, con "__declspec(align(%u))\n" "#endif\n" "%s[] = {", + initname, (uint16_t)MRB_DUMP_ALIGNMENT, (uint16_t)MRB_DUMP_ALIGNMENT, initname) < 0) { mrb_free(mrb, bin); return MRB_DUMP_WRITE_FAULT; -- cgit v1.2.3 From 00e61212600c53e9c4f1629a6e3bcb93422417c2 Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Tue, 22 Nov 2016 13:22:02 +0100 Subject: Safeguard against trying to use C++ exception handling in C code --- include/mruby/throw.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/mruby/throw.h b/include/mruby/throw.h index 5dd1d0a9f..010793027 100644 --- a/include/mruby/throw.h +++ b/include/mruby/throw.h @@ -7,6 +7,10 @@ #ifndef MRB_THROW_H #define MRB_THROW_H +#if defined(MRB_ENABLE_CXX_EXCEPTION) && !defined(__cplusplus) +#error Trying to use C++ exception handling in C code +#endif + #if defined(MRB_ENABLE_CXX_EXCEPTION) && defined(__cplusplus) #define MRB_TRY(buf) do { try { -- cgit v1.2.3 From 18757c8f7be05d9bc8d850180ada4d3fa1fc018d Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Tue, 22 Nov 2016 13:19:53 +0100 Subject: Different method of compiling C as C++ (-x c++) --- include/mruby/common.h | 5 +++++ tasks/mruby_build.rake | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/include/mruby/common.h b/include/mruby/common.h index 3745c58ea..338044c2f 100644 --- a/include/mruby/common.h +++ b/include/mruby/common.h @@ -9,8 +9,13 @@ #ifdef __cplusplus +#ifdef MRB_ENABLE_CXX_EXCEPTION +#define MRB_BEGIN_DECL +#define MRB_END_DECL +#else # define MRB_BEGIN_DECL extern "C" { # define MRB_END_DECL } +#endif #else /** Start declarations in C mode */ # define MRB_BEGIN_DECL diff --git a/tasks/mruby_build.rake b/tasks/mruby_build.rake index cff45ddf8..cde996aae 100644 --- a/tasks/mruby_build.rake +++ b/tasks/mruby_build.rake @@ -120,6 +120,7 @@ module MRuby def enable_cxx_abi return if @cxx_exception_disabled or @cxx_abi_enabled compilers.each { |c| c.defines += %w(MRB_ENABLE_CXX_EXCEPTION) } + compilers.each { |c| c.flags << '-x c++'} linker.command = cxx.command if toolchains.find { |v| v == 'gcc' } @cxx_abi_enabled = true end @@ -135,9 +136,13 @@ module MRuby #define __STDC_CONSTANT_MACROS #define __STDC_LIMIT_MACROS +#ifndef MRB_ENABLE_CXX_EXCEPTION extern "C" { +#endif #include "#{src}" +#ifndef MRB_ENABLE_CXX_EXCEPTION } +#endif #{src == "#{MRUBY_ROOT}/src/error.c"? 'mrb_int mrb_jmpbuf::jmpbuf_id = 0;' : ''} EOS -- cgit v1.2.3 From 44c3859a9725a5fb41e374ba91b52459498b8f17 Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Wed, 23 Nov 2016 11:59:26 +0100 Subject: Fix for compiling mruby as C++ on Visual Studio toolchain --- tasks/mruby_build.rake | 2 +- tasks/mruby_build_commands.rake | 1 + tasks/toolchains/gcc.rake | 2 ++ tasks/toolchains/visualcpp.rake | 2 ++ 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tasks/mruby_build.rake b/tasks/mruby_build.rake index cde996aae..bd911493d 100644 --- a/tasks/mruby_build.rake +++ b/tasks/mruby_build.rake @@ -120,7 +120,7 @@ module MRuby def enable_cxx_abi return if @cxx_exception_disabled or @cxx_abi_enabled compilers.each { |c| c.defines += %w(MRB_ENABLE_CXX_EXCEPTION) } - compilers.each { |c| c.flags << '-x c++'} + compilers.each { |c| c.flags << c.cxx_compile_flag } linker.command = cxx.command if toolchains.find { |v| v == 'gcc' } @cxx_abi_enabled = true end diff --git a/tasks/mruby_build_commands.rake b/tasks/mruby_build_commands.rake index f4805f46d..d688077ff 100644 --- a/tasks/mruby_build_commands.rake +++ b/tasks/mruby_build_commands.rake @@ -41,6 +41,7 @@ module MRuby class Command::Compiler < Command attr_accessor :flags, :include_paths, :defines, :source_exts attr_accessor :compile_options, :option_define, :option_include_path, :out_ext + attr_accessor :cxx_compile_flag def initialize(build, source_exts=[]) super(build) diff --git a/tasks/toolchains/gcc.rake b/tasks/toolchains/gcc.rake index 4897e8c52..e4680b632 100644 --- a/tasks/toolchains/gcc.rake +++ b/tasks/toolchains/gcc.rake @@ -6,6 +6,7 @@ MRuby::Toolchain.new(:gcc) do |conf, _params| cc.option_include_path = '-I%s' cc.option_define = '-D%s' cc.compile_options = '%{flags} -MMD -o %{outfile} -c %{infile}' + cc.cxx_compile_flag = '-x c++' end [conf.cxx].each do |cxx| @@ -15,6 +16,7 @@ MRuby::Toolchain.new(:gcc) do |conf, _params| cxx.option_include_path = '-I%s' cxx.option_define = '-D%s' cxx.compile_options = '%{flags} -MMD -o %{outfile} -c %{infile}' + cxx.cxx_compile_flag = '-x c++' end conf.linker do |linker| diff --git a/tasks/toolchains/visualcpp.rake b/tasks/toolchains/visualcpp.rake index 52820656b..5f5bab9c2 100644 --- a/tasks/toolchains/visualcpp.rake +++ b/tasks/toolchains/visualcpp.rake @@ -7,6 +7,7 @@ MRuby::Toolchain.new(:visualcpp) do |conf, _params| cc.option_include_path = '/I%s' cc.option_define = '/D%s' cc.compile_options = "%{flags} /Fo%{outfile} %{infile}" + cc.cxx_compile_flag = '/TP' end conf.cxx do |cxx| @@ -16,6 +17,7 @@ MRuby::Toolchain.new(:visualcpp) do |conf, _params| cxx.option_include_path = '/I%s' cxx.option_define = '/D%s' cxx.compile_options = "%{flags} /Fo%{outfile} %{infile}" + cxx.cxx_compile_flag = '/TP' end conf.linker do |linker| -- cgit v1.2.3 From c2a60eb8aff29ef73d3b4feb7818b59fb5dd95bd Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Wed, 23 Nov 2016 12:03:05 +0100 Subject: Fix for Windows-specific mruby C++ issues --- mrbgems/mruby-print/src/print.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgems/mruby-print/src/print.c b/mrbgems/mruby-print/src/print.c index da5f36789..fd8d15241 100644 --- a/mrbgems/mruby-print/src/print.c +++ b/mrbgems/mruby-print/src/print.c @@ -22,7 +22,7 @@ printstr(mrb_state *mrb, mrb_value obj) int mlen = RSTRING_LEN(obj); char* utf8 = RSTRING_PTR(obj); int wlen = MultiByteToWideChar(CP_UTF8, 0, utf8, mlen, NULL, 0); - wchar_t* utf16 = mrb_malloc(mrb, (wlen+1) * sizeof(wchar_t)); + wchar_t* utf16 = (wchar_t*)mrb_malloc(mrb, (wlen+1) * sizeof(wchar_t)); if (utf16 == NULL) return; if (MultiByteToWideChar(CP_UTF8, 0, utf8, mlen, utf16, wlen) > 0) { utf16[wlen] = 0; -- cgit v1.2.3 From d7a6070d22c21bcb1237d903209114878930de95 Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Wed, 23 Nov 2016 12:12:18 +0100 Subject: Fixed language standard mode for GCC (cannot use gnu99 with C++, c++03 used instead) --- tasks/toolchains/gcc.rake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/toolchains/gcc.rake b/tasks/toolchains/gcc.rake index e4680b632..59ae015ac 100644 --- a/tasks/toolchains/gcc.rake +++ b/tasks/toolchains/gcc.rake @@ -6,7 +6,7 @@ MRuby::Toolchain.new(:gcc) do |conf, _params| cc.option_include_path = '-I%s' cc.option_define = '-D%s' cc.compile_options = '%{flags} -MMD -o %{outfile} -c %{infile}' - cc.cxx_compile_flag = '-x c++' + cc.cxx_compile_flag = '-x c++ -std=c++03' end [conf.cxx].each do |cxx| @@ -16,7 +16,7 @@ MRuby::Toolchain.new(:gcc) do |conf, _params| cxx.option_include_path = '-I%s' cxx.option_define = '-D%s' cxx.compile_options = '%{flags} -MMD -o %{outfile} -c %{infile}' - cxx.cxx_compile_flag = '-x c++' + cxx.cxx_compile_flag = '-x c++ -std=c++03' end conf.linker do |linker| -- cgit v1.2.3 From 798c69d1be8d9ab437defb25e5e652d355eef5d4 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 Nov 2016 09:23:55 +0900 Subject: Avoid casting from int to unsigned char for C++; ref #3267 --- src/object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/object.c b/src/object.c index 392432b0f..c61feb342 100644 --- a/src/object.c +++ b/src/object.c @@ -380,7 +380,7 @@ static const struct types { /* {MRB_TT_VARMAP, "Varmap"}, */ /* internal use: dynamic variables */ /* {MRB_TT_NODE, "Node"}, */ /* internal use: syntax tree node */ /* {MRB_TT_UNDEF, "undef"}, */ /* internal use: #undef; should not happen */ - {-1, 0} + {MRB_TT_MAXDEFINE, 0} }; MRB_API void -- cgit v1.2.3 From f5a86ca5305d70c16297b67df30ce37c102af183 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 Nov 2016 09:24:45 +0900 Subject: Add pointer casting from mrb_malloc(); ref #3267 --- src/variable.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/variable.c b/src/variable.c index 29f43e69d..45dc055af 100644 --- a/src/variable.c +++ b/src/variable.c @@ -44,7 +44,7 @@ iv_new(mrb_state *mrb) { iv_tbl *t; - t = mrb_malloc(mrb, sizeof(iv_tbl)); + t = (iv_tbl*)mrb_malloc(mrb, sizeof(iv_tbl)); t->size = 0; t->rootseg = NULL; t->last_len = 0; @@ -102,7 +102,7 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) return; } - seg = mrb_malloc(mrb, sizeof(segment)); + seg = (segment*)mrb_malloc(mrb, sizeof(segment)); if (!seg) return; seg->next = NULL; seg->key[0] = sym; -- cgit v1.2.3 From dc4be19aab7df7b3d31102a68c4ed12c63a5814c Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 Nov 2016 10:01:03 +0900 Subject: Add forgotten loop_pop() in NODE_OP_ASGN codegen --- mrbgems/mruby-compiler/core/codegen.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 85ca21dd4..6d3ece9aa 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1746,6 +1746,7 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_A(OP_RESCUE, exc)); genop(s, MKOP_A(OP_LOADF, exc)); dispatch(s, noexc); + loop_pop(s, NOVAL); } else if ((intptr_t)tree->car->car == NODE_CALL) { node *n = tree->car->cdr; -- cgit v1.2.3 From 1c9593954bfcdcd1c99732eb572c3995228d8fbb Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 Nov 2016 10:32:28 +0900 Subject: Add "void value expression" check to the parser. --- mrbgems/mruby-compiler/core/parse.y | 78 ++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 90b8812b9..ea7f809f3 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -41,6 +41,7 @@ static void yyerror(parser_state *p, const char *s); static void yywarn(parser_state *p, const char *s); static void yywarning(parser_state *p, const char *s); static void backref_error(parser_state *p, node *n); +static void void_expr_error(parser_state *p, node *n); static void tokadd(parser_state *p, int32_t c); #define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c)) @@ -1097,7 +1098,7 @@ heredoc_end(parser_state *p) %type literal numeric cpath symbol %type top_compstmt top_stmts top_stmt %type bodystmt compstmt stmts stmt expr arg primary command command_call method_call -%type expr_value arg_value arg_rhs primary_value +%type expr_value arg0 arg_rhs primary_value %type if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure %type args call_args opt_call_args %type paren_args opt_paren_args variable @@ -1322,7 +1323,7 @@ stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym { $$ = new_asgn(p, $1, new_array(p, $3)); } - | mlhs '=' arg_value + | mlhs '=' arg { $$ = new_masgn(p, $1, $3); } @@ -1395,13 +1396,16 @@ expr : command_call { $$ = call_uni_op(p, cond($2), "!"); } - | arg + | arg0 ; expr_value : expr { if (!$1) $$ = new_nil(p); - else $$ = $1; + else { + void_expr_error(p, $1); + $$ = $1; + } } ; @@ -1734,7 +1738,7 @@ reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__ | keyword_while | keyword_until ; -arg : lhs '=' arg_rhs +arg0 : lhs '=' arg_rhs { $$ = new_asgn(p, $1, $3); } @@ -1907,10 +1911,13 @@ arg : lhs '=' arg_rhs } ; -arg_value : arg +arg : arg0 { - $$ = $1; - if (!$$) $$ = new_nil(p); + if (!$1) $$ = new_nil(p); + else { + void_expr_error(p, $1); + $$ = $1; + } } ; @@ -1931,7 +1938,7 @@ aref_args : none } ; -arg_rhs : arg %prec tOP_ASGN +arg_rhs : arg %prec tOP_ASGN | arg modifier_rescue arg { $$ = new_mod_rescue(p, $1, $3); @@ -2005,7 +2012,7 @@ command_args : { } ; -block_arg : tAMPER arg_value +block_arg : tAMPER arg { $$ = new_block_arg(p, $2); } @@ -2021,43 +2028,43 @@ opt_block_arg : ',' block_arg } ; -args : arg_value +args : arg { $$ = cons($1, 0); NODE_LINENO($$, $1); } - | tSTAR arg_value + | tSTAR arg { $$ = cons(new_splat(p, $2), 0); NODE_LINENO($$, $2); } - | args ',' arg_value + | args ',' arg { $$ = push($1, $3); } - | args ',' tSTAR arg_value + | args ',' tSTAR arg { $$ = push($1, new_splat(p, $4)); } - | args ',' heredoc_bodies arg_value + | args ',' heredoc_bodies arg { $$ = push($1, $4); } - | args ',' heredoc_bodies tSTAR arg_value + | args ',' heredoc_bodies tSTAR arg { $$ = push($1, new_splat(p, $5)); } ; -mrhs : args ',' arg_value +mrhs : args ',' arg { $$ = push($1, $3); } - | args ',' tSTAR arg_value + | args ',' tSTAR arg { $$ = push($1, new_splat(p, $4)); } - | tSTAR arg_value + | tSTAR arg { $$ = list1(new_splat(p, $2)); } @@ -2688,7 +2695,7 @@ opt_rescue : keyword_rescue exc_list exc_var then | none ; -exc_list : arg_value +exc_list : arg { $$ = list1($1); } @@ -3115,7 +3122,7 @@ f_opt_asgn : tIDENTIFIER '=' } ; -f_opt : f_opt_asgn arg_value +f_opt : f_opt_asgn arg { $$ = cons(nsym($1), $2); } @@ -3233,23 +3240,23 @@ assocs : assoc } ; -assoc : arg_value tASSOC arg_value +assoc : arg tASSOC arg { $$ = cons($1, $3); } - | tLABEL arg_value + | tLABEL arg { $$ = cons(new_sym(p, $1), $2); } - | tLABEL_END arg_value + | tLABEL_END arg { $$ = cons(new_sym(p, new_strsym(p, $1)), $2); } - | tSTRING_BEG tLABEL_END arg_value + | tSTRING_BEG tLABEL_END arg { $$ = cons(new_sym(p, new_strsym(p, $2)), $3); } - | tSTRING_BEG string_rep tLABEL_END arg_value + | tSTRING_BEG string_rep tLABEL_END arg { $$ = cons(new_dsym(p, push($2, $3)), $4); } @@ -3430,6 +3437,25 @@ backref_error(parser_state *p, node *n) } } +static void +void_expr_error(parser_state *p, node *n) +{ + int c; + + c = (int)(intptr_t)n->car; + switch (c) { + case NODE_BREAK: + case NODE_RETURN: + case NODE_NEXT: + case NODE_REDO: + case NODE_RETRY: + yyerror(p, "void value expression"); + break; + default: + break; + } +} + static void pushback(parser_state *p, int c); static mrb_bool peeks(parser_state *p, const char *s); static mrb_bool skips(parser_state *p, const char *s); -- cgit v1.2.3 From 9e2faec8e4f5cb24ffc8a7f10284c05598b91acd Mon Sep 17 00:00:00 2001 From: ksss Date: Thu, 24 Nov 2016 10:34:14 +0900 Subject: Support object does'n have `<` method --- mrbgems/mruby-enum-ext/mrblib/enum.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb index 6724dff37..bd64cc6bd 100644 --- a/mrbgems/mruby-enum-ext/mrblib/enum.rb +++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb @@ -58,9 +58,8 @@ module Enumerable def take(n) raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) - raise ArgumentError, "attempt to take negative size" if n < 0 - - n = n.to_int + i = n.to_int + raise ArgumentError, "attempt to take negative size" if i < 0 ary = [] self.each do |*val| break if ary.size >= n -- cgit v1.2.3 From 5134734541dd993f74a40b1621009add2cf110bf Mon Sep 17 00:00:00 2001 From: ksss Date: Thu, 24 Nov 2016 10:35:15 +0900 Subject: Shouldn't call `each` method if size is 0 --- mrbgems/mruby-enum-ext/mrblib/enum.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb index bd64cc6bd..5b50aba00 100644 --- a/mrbgems/mruby-enum-ext/mrblib/enum.rb +++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb @@ -61,9 +61,11 @@ module Enumerable i = n.to_int raise ArgumentError, "attempt to take negative size" if i < 0 ary = [] + return ary if i == 0 self.each do |*val| - break if ary.size >= n ary << val.__svalue + i -= 1 + break if i == 0 end ary end -- cgit v1.2.3 From 227daa881137d5251e03eea0883b9b574a1f064e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 Nov 2016 11:22:54 +0900 Subject: Relax 'void value expression' check that was too strict --- mrbgems/mruby-compiler/core/parse.y | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index ea7f809f3..0ff7d819c 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -1098,7 +1098,7 @@ heredoc_end(parser_state *p) %type literal numeric cpath symbol %type top_compstmt top_stmts top_stmt %type bodystmt compstmt stmts stmt expr arg primary command command_call method_call -%type expr_value arg0 arg_rhs primary_value +%type expr_value arg_rhs primary_value %type if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure %type args call_args opt_call_args %type paren_args opt_paren_args variable @@ -1396,7 +1396,7 @@ expr : command_call { $$ = call_uni_op(p, cond($2), "!"); } - | arg0 + | arg ; expr_value : expr @@ -1738,7 +1738,7 @@ reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__ | keyword_while | keyword_until ; -arg0 : lhs '=' arg_rhs +arg : lhs '=' arg_rhs { $$ = new_asgn(p, $1, $3); } @@ -1911,16 +1911,6 @@ arg0 : lhs '=' arg_rhs } ; -arg : arg0 - { - if (!$1) $$ = new_nil(p); - else { - void_expr_error(p, $1); - $$ = $1; - } - } - ; - aref_args : none | args trailer { @@ -1939,8 +1929,14 @@ aref_args : none ; arg_rhs : arg %prec tOP_ASGN + { + void_expr_error(p, $1); + $$ = $1; + } | arg modifier_rescue arg { + void_expr_error(p, $1); + void_expr_error(p, $3); $$ = new_mod_rescue(p, $1, $3); } ; @@ -2030,42 +2026,51 @@ opt_block_arg : ',' block_arg args : arg { + void_expr_error(p, $1); $$ = cons($1, 0); NODE_LINENO($$, $1); } | tSTAR arg { + void_expr_error(p, $2); $$ = cons(new_splat(p, $2), 0); NODE_LINENO($$, $2); } | args ',' arg { + void_expr_error(p, $3); $$ = push($1, $3); } | args ',' tSTAR arg { + void_expr_error(p, $4); $$ = push($1, new_splat(p, $4)); } | args ',' heredoc_bodies arg { + void_expr_error(p, $4); $$ = push($1, $4); } | args ',' heredoc_bodies tSTAR arg { + void_expr_error(p, $5); $$ = push($1, new_splat(p, $5)); } ; mrhs : args ',' arg { + void_expr_error(p, $3); $$ = push($1, $3); } | args ',' tSTAR arg { + void_expr_error(p, $4); $$ = push($1, new_splat(p, $4)); } | tSTAR arg { + void_expr_error(p, $2); $$ = list1(new_splat(p, $2)); } ; -- cgit v1.2.3 From 23c73ff3998782f5e2a7f1f3755fddf8ceed0d30 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 Nov 2016 13:50:36 +0900 Subject: Time#initialize_copy: Check if source time is initialized. To prevent crash from nasty code like: class Time def initialize end end a = Time.new b = Time.new a.initialize_copy b --- mrbgems/mruby-time/src/time.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index 19ce32832..5c23bd44a 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -611,16 +611,23 @@ static mrb_value mrb_time_initialize_copy(mrb_state *mrb, mrb_value copy) { mrb_value src; + struct mrb_time *t1, *t2; mrb_get_args(mrb, "o", &src); if (mrb_obj_equal(mrb, copy, src)) return copy; if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) { mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class"); } - if (!DATA_PTR(copy)) { - mrb_data_init(copy, mrb_malloc(mrb, sizeof(struct mrb_time)), &mrb_time_type); + t1 = (struct mrb_time *)DATA_PTR(copy); + t2 = (struct mrb_time *)DATA_PTR(src); + if (!t2) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized time"); } - *(struct mrb_time *)DATA_PTR(copy) = *(struct mrb_time *)DATA_PTR(src); + if (!t1) { + t1 = (struct mrb_time *)mrb_malloc(mrb, sizeof(struct mrb_time)); + mrb_data_init(copy, t1, &mrb_time_type); + } + *t1 = *t2; return copy; } -- cgit v1.2.3 From cb5c9d34150c073b5cdde725cadd959839c9bc45 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 Nov 2016 18:09:04 +0900 Subject: always call Hash#default if no key found; fix #3272 --- src/hash.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/hash.c b/src/hash.c index 015b2d614..4df2babbe 100644 --- a/src/hash.c +++ b/src/hash.c @@ -172,11 +172,8 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) } /* not found */ - if (MRB_RHASH_DEFAULT_P(hash)) { - /* xxx mrb_funcall_tailcall(mrb, hash, "default", 1, key); */ - return mrb_funcall(mrb, hash, "default", 1, key); - } - return mrb_nil_value(); + /* xxx mrb_funcall_tailcall(mrb, hash, "default", 1, key); */ + return mrb_funcall(mrb, hash, "default", 1, key); } MRB_API mrb_value -- cgit v1.2.3 From 0c924b92872a96b29f3fe8462ab57d33dfb7b9b6 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 Nov 2016 19:30:21 +0900 Subject: fixed a bug in self modifying Array#[]=; fix #3274 --- src/array.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/array.c b/src/array.c index 5a319d809..106353c07 100644 --- a/src/array.c +++ b/src/array.c @@ -309,9 +309,12 @@ ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, mrb_int len) MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other) { + struct RArray *a1 = mrb_ary_ptr(self); struct RArray *a2 = mrb_ary_ptr(other); - ary_replace(mrb, mrb_ary_ptr(self), a2->ptr, a2->len); + if (a1 != a2) { + ary_replace(mrb, a1, a2->ptr, a2->len); + } } static mrb_value @@ -554,6 +557,15 @@ mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val) mrb_field_write_barrier_value(mrb, (struct RBasic*)a, val); } +static struct RArray* +ary_dup(mrb_state *mrb, struct RArray *a) +{ + struct RArray *d = ary_new_capa(mrb, a->len); + + ary_replace(mrb, d, a->ptr, a->len); + return d; +} + MRB_API mrb_value mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_value rpl) { @@ -583,6 +595,10 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val if (mrb_array_p(rpl)) { argc = RARRAY_LEN(rpl); argv = RARRAY_PTR(rpl); + if (argv == a->ptr) { + struct RArray *r = ary_dup(mrb, a); + argv = r->ptr; + } } else { argc = 1; -- cgit v1.2.3 From 3943ab5368119c91d44cb9f99a3d476240d7f37e Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Thu, 24 Nov 2016 12:34:36 +0100 Subject: Update AUTHORS --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 180fd752e..e3b95d728 100644 --- a/AUTHORS +++ b/AUTHORS @@ -34,3 +34,4 @@ Original Authors "mruby developers" are: Yuichi Osawa Terence Lee Zachary Scott + Tomasz Dąbrowski -- 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(-) 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 72ed7eebc30eaccf4175eaa7f62235bcb7a8901d Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Thu, 24 Nov 2016 12:50:49 +0100 Subject: Fixed Range.size to use proper floating point tolerance --- include/mruby.h | 7 +++++++ mrbgems/mruby-range-ext/src/range.c | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/mruby.h b/include/mruby.h index d40dce6d9..bc6800e29 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -64,6 +64,13 @@ #endif #include "mrbconf.h" + +#ifdef MRB_USE_FLOAT +#define MRB_FLOAT_EPSILON FLT_EPSILON +#else +#define MRB_FLOAT_EPSILON DBL_EPSILON +#endif + #include "mruby/common.h" #include #include diff --git a/mrbgems/mruby-range-ext/src/range.c b/mrbgems/mruby-range-ext/src/range.c index 32222a594..ccb5a9e45 100644 --- a/mrbgems/mruby-range-ext/src/range.c +++ b/mrbgems/mruby-range-ext/src/range.c @@ -140,7 +140,7 @@ mrb_range_size(mrb_state *mrb, mrb_value range) } if (num_p) { mrb_float n = end_f - beg_f; - mrb_float err = (fabs(beg_f) + fabs(end_f) + fabs(end_f-beg_f)) * DBL_EPSILON; + mrb_float err = (fabs(beg_f) + fabs(end_f) + fabs(end_f-beg_f)) * MRB_FLOAT_EPSILON; if (err>0.5) err=0.5; if (excl) { -- cgit v1.2.3 From 22f73250dbe38dd1b5878143b81284f510d91923 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 Nov 2016 21:25:27 +0900 Subject: redo should work well in for statement; fix #3275 --- mrbgems/mruby-compiler/core/codegen.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 6d3ece9aa..0c84dd558 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -588,9 +588,6 @@ for_body(codegen_scope *s, node *tree) push(); /* push for a block parameter */ - lp = loop_push(s, LOOP_FOR); - lp->pc1 = new_label(s); - /* generate loop variable */ n2 = tree->car; genop(s, MKOP_Ax(OP_ENTER, 0x40000)); @@ -600,6 +597,11 @@ for_body(codegen_scope *s, node *tree) else { gen_vmassignment(s, n2, 1, VAL); } + /* construct loop */ + lp = loop_push(s, LOOP_FOR); + lp->pc2 = new_label(s); + + /* loop body */ codegen(s, tree->cdr->cdr->car, VAL); pop(); if (s->pc > 0) { -- cgit v1.2.3 From a630c4f413f6af764e68210430e8b61a435d38d7 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 Nov 2016 22:10:54 +0900 Subject: use MRB_PRId instead of %d for mrb_int --- mrbgems/mruby-inline-struct/test/inline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgems/mruby-inline-struct/test/inline.c b/mrbgems/mruby-inline-struct/test/inline.c index 772248e9b..0baaab617 100644 --- a/mrbgems/mruby-inline-struct/test/inline.c +++ b/mrbgems/mruby-inline-struct/test/inline.c @@ -17,7 +17,7 @@ istruct_test_initialize(mrb_state *mrb, mrb_value self) } else if (mrb_fixnum_p(object)) { - snprintf(string, size, "fixnum(%d)", mrb_fixnum(object)); + snprintf(string, size, "fixnum(%" MRB_PRId ")", mrb_fixnum(object)); } else if (mrb_string_p(object)) { -- 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(+) 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 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: Wed, 16 Nov 2016 14:09:20 -0500 Subject: Remove constant when a struct is redefined. --- mrbgems/mruby-struct/src/struct.c | 2 +- mrbgems/mruby-struct/test/struct.rb | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index 0ccb7f4cb..8c8f54f27 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -203,7 +203,7 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k } if (mrb_const_defined_at(mrb, mrb_obj_value(klass), id)) { mrb_warn(mrb, "redefining constant Struct::%S", name); - /* ?rb_mod_remove_const(klass, mrb_sym2name(mrb, id)); */ + mrb_const_remove(mrb, mrb_obj_value(klass), id); } c = mrb_define_class_under(mrb, klass, RSTRING_PTR(name), klass); } diff --git a/mrbgems/mruby-struct/test/struct.rb b/mrbgems/mruby-struct/test/struct.rb index 02ecf69e4..bbfe18cb2 100644 --- a/mrbgems/mruby-struct/test/struct.rb +++ b/mrbgems/mruby-struct/test/struct.rb @@ -158,3 +158,24 @@ assert("Struct#dig") do assert_equal 1, a.dig(:purple, :red) assert_equal 1, a.dig(1, 0) end + +assert("Struct.new removes existing constant") do + begin + assert_not_equal Struct.new("Test", :a), Struct.new("Test", :a, :b) + ensure + Struct.remove_const :Test + end +end + +assert("Struct#initialize_copy requires struct to be the same type") do + begin + Struct.new("Test", :a) + a = Struct::Test.new("a") + Struct.new("Test", :a, :b) + assert_raise(TypeError) do + a.initialize_copy(Struct::Test.new("a", "b")) + end + ensure + Struct.remove_const :Test + end +end -- cgit v1.2.3 From b60d6c42aaa10ac99a03a92a3a34da4bee066af1 Mon Sep 17 00:00:00 2001 From: Clayton Smith Date: Wed, 16 Nov 2016 09:00:00 -0500 Subject: Don't allow array parameter in Struct.new --- mrbgems/mruby-struct/src/struct.c | 26 ++++++++------------------ mrbgems/mruby-struct/test/struct.rb | 6 ++++++ 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index 0ccb7f4cb..39c54639f 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -273,25 +273,15 @@ mrb_struct_s_def(mrb_state *mrb, mrb_value klass) } else { if (argc > 0) name = argv[0]; - if (argc > 1) rest = argv[1]; - if (mrb_array_p(rest)) { - if (!mrb_nil_p(name) && mrb_symbol_p(name)) { - /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */ - mrb_ary_unshift(mrb, rest, name); - name = mrb_nil_value(); - } - } - else { - pargv = &argv[1]; - argcnt = argc-1; - if (!mrb_nil_p(name) && mrb_symbol_p(name)) { - /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */ - name = mrb_nil_value(); - pargv = &argv[0]; - argcnt++; - } - rest = mrb_ary_new_from_values(mrb, argcnt, pargv); + pargv = &argv[1]; + argcnt = argc-1; + if (!mrb_nil_p(name) && mrb_symbol_p(name)) { + /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */ + name = mrb_nil_value(); + pargv = &argv[0]; + argcnt++; } + rest = mrb_ary_new_from_values(mrb, argcnt, pargv); for (i=0; i Date: Wed, 16 Nov 2016 14:01:49 -0500 Subject: Fix segfault when defining class inside instance_exec on primitive --- mrbgems/mruby-object-ext/test/object.rb | 28 ++++++++++++++++++++++++++++ src/vm.c | 14 ++++++++++---- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/mrbgems/mruby-object-ext/test/object.rb b/mrbgems/mruby-object-ext/test/object.rb index fe56f1ec5..f0742f8ce 100644 --- a/mrbgems/mruby-object-ext/test/object.rb +++ b/mrbgems/mruby-object-ext/test/object.rb @@ -23,3 +23,31 @@ assert('Object#tap') do ], ret assert_equal(:tap_ok, Class.new {def m; tap{return :tap_ok}; end}.new.m) end + +assert('instance_exec on primitives with class and module definition') do + begin + class A + 1.instance_exec do + class B + end + end + end + + assert_kind_of Class, A::B + ensure + Object.remove_const :A + end + + begin + class A + 1.instance_exec do + module B + end + end + end + + assert_kind_of Module, A::B + ensure + Object.remove_const :A + end +end diff --git a/src/vm.c b/src/vm.c index a7418e6e7..41e19b0c0 100644 --- a/src/vm.c +++ b/src/vm.c @@ -2261,7 +2261,7 @@ RETRY_TRY_BLOCK: CASE(OP_CLASS) { /* A B R(A) := newclass(R(A),Syms(B),R(A+1)) */ - struct RClass *c = 0; + struct RClass *c = 0, *baseclass; int a = GETARG_A(i); mrb_value base, super; mrb_sym id = syms[GETARG_B(i)]; @@ -2269,7 +2269,10 @@ RETRY_TRY_BLOCK: base = regs[a]; super = regs[a+1]; if (mrb_nil_p(base)) { - base = mrb_obj_value(mrb->c->ci->target_class); + baseclass = mrb->c->ci->proc->target_class; + if (!baseclass) baseclass = mrb->c->ci->target_class; + + base = mrb_obj_value(baseclass); } c = mrb_vm_define_class(mrb, base, super, id); regs[a] = mrb_obj_value(c); @@ -2279,14 +2282,17 @@ RETRY_TRY_BLOCK: CASE(OP_MODULE) { /* A B R(A) := newmodule(R(A),Syms(B)) */ - struct RClass *c = 0; + struct RClass *c = 0, *baseclass; int a = GETARG_A(i); mrb_value base; mrb_sym id = syms[GETARG_B(i)]; base = regs[a]; if (mrb_nil_p(base)) { - base = mrb_obj_value(mrb->c->ci->target_class); + baseclass = mrb->c->ci->proc->target_class; + if (!baseclass) baseclass = mrb->c->ci->target_class; + + base = mrb_obj_value(baseclass); } c = mrb_vm_define_module(mrb, base, id); regs[a] = mrb_obj_value(c); -- cgit v1.2.3 From 75b31d743813dd078c5b5c2ee5115b07b0c14f32 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl 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 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(-) 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 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 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(-) 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(-) 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 83005d83d8ba95524436409d5d73fd82b63bc115 Mon Sep 17 00:00:00 2001 From: Craig Lehmann Date: Tue, 15 Nov 2016 14:50:52 -0500 Subject: Read length after args in String#setbyte Prevents RCE Reported by https://hackerone.com/raydot --- mrbgems/mruby-string-ext/src/string.c | 3 ++- mrbgems/mruby-string-ext/test/string.rb | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index 122ee5454..dfac907ec 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -23,10 +23,11 @@ static mrb_value mrb_str_setbyte(mrb_state *mrb, mrb_value str) { mrb_int pos, byte; - long len = RSTRING_LEN(str); + long len; mrb_get_args(mrb, "ii", &pos, &byte); + len = RSTRING_LEN(str); if (pos < -len || len <= pos) mrb_raisef(mrb, E_INDEX_ERROR, "index %S is out of array", mrb_fixnum_value(pos)); if (pos < 0) diff --git a/mrbgems/mruby-string-ext/test/string.rb b/mrbgems/mruby-string-ext/test/string.rb index a5d55a7ee..228a236af 100644 --- a/mrbgems/mruby-string-ext/test/string.rb +++ b/mrbgems/mruby-string-ext/test/string.rb @@ -30,6 +30,18 @@ assert('String#setbyte') do assert_equal("Hello", str1) end +assert("String#setbyte raises IndexError if arg conversion resizes String") do + $s = "01234\n" + class Tmp + def to_i + $s.chomp! '' + 95 + end + end + tmp = Tmp.new + assert_raise(IndexError) { $s.setbyte(5, tmp) } +end + assert('String#byteslice') do str1 = "hello" assert_equal("e", str1.byteslice(1)) -- 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 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(-) 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 743c1e7be190eca83a08b95b0f6045cbdc9ba625 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 25 Nov 2016 09:44:22 +0900 Subject: stop warnings in the test; ref #3280 --- mrbgems/mruby-struct/test/struct.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mrbgems/mruby-struct/test/struct.rb b/mrbgems/mruby-struct/test/struct.rb index 3e5d00d1f..2fe684960 100644 --- a/mrbgems/mruby-struct/test/struct.rb +++ b/mrbgems/mruby-struct/test/struct.rb @@ -160,6 +160,7 @@ assert("Struct#dig") do end assert("Struct.new removes existing constant") do + skip "redefining Struct with same name cause warnings" begin assert_not_equal Struct.new("Test", :a), Struct.new("Test", :a, :b) ensure @@ -171,6 +172,7 @@ assert("Struct#initialize_copy requires struct to be the same type") do begin Struct.new("Test", :a) a = Struct::Test.new("a") + Struct.remove_const :Test Struct.new("Test", :a, :b) assert_raise(TypeError) do a.initialize_copy(Struct::Test.new("a", "b")) -- cgit v1.2.3 From c28a963bf426afb00f2ebb32c0dff65dd3ff4b3f Mon Sep 17 00:00:00 2001 From: ksss Date: Fri, 25 Nov 2016 22:20:33 +0900 Subject: Like a Enumerable#take --- mrbgems/mruby-enum-ext/mrblib/enum.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb index 5b50aba00..54db189f4 100644 --- a/mrbgems/mruby-enum-ext/mrblib/enum.rb +++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb @@ -222,14 +222,17 @@ module Enumerable end return nil else - a = [] - i = 0 + raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) + i = n.to_int + raise ArgumentError, "attempt to take negative size" if i < 0 + ary = [] + return ary if i == 0 self.each do |*val| - break if n<=i - a.push val.__svalue - i += 1 + ary << val.__svalue + i -= 1 + break if i == 0 end - a + ary end end -- cgit v1.2.3 From 1bf565ea0447f69d8ffcca756b82fa789f6afca0 Mon Sep 17 00:00:00 2001 From: ksss Date: Fri, 25 Nov 2016 22:25:48 +0900 Subject: Argument more strictly --- mrbgems/mruby-enum-ext/mrblib/enum.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb index 54db189f4..113b470a9 100644 --- a/mrbgems/mruby-enum-ext/mrblib/enum.rb +++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb @@ -215,13 +215,15 @@ module Enumerable # Returns the first element, or the first +n+ elements, of the enumerable. # If the enumerable is empty, the first form returns nil, and the # second form returns an empty array. - def first(n=NONE) - if n == NONE + def first(*args) + case args.length + when 0 self.each do |*val| return val.__svalue end return nil - else + when 1 + n = args[0] raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) i = n.to_int raise ArgumentError, "attempt to take negative size" if i < 0 @@ -233,6 +235,8 @@ module Enumerable break if i == 0 end ary + else + raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 0..1)" end end -- cgit v1.2.3 From b7f9a58757bdf30e9d64191ac47d81144e3f6098 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Wed, 16 Nov 2016 17:14:16 -0500 Subject: Fix null pointer dereference in mrb_time_initialize Reported by https://hackerone.com/raydot --- mrbgems/mruby-time/src/time.c | 4 ++-- mrbgems/mruby-time/test/time.rb | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index 5c23bd44a..dfd4450da 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -587,14 +587,14 @@ mrb_time_initialize(mrb_state *mrb, mrb_value self) int n; struct mrb_time *tm; + n = mrb_get_args(mrb, "|iiiiiii", + &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec); tm = (struct mrb_time*)DATA_PTR(self); if (tm) { mrb_free(mrb, tm); } mrb_data_init(self, NULL, &mrb_time_type); - n = mrb_get_args(mrb, "|iiiiiii", - &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec); if (n == 0) { tm = current_mrb_time(mrb); } diff --git a/mrbgems/mruby-time/test/time.rb b/mrbgems/mruby-time/test/time.rb index 759e2881d..91a646759 100644 --- a/mrbgems/mruby-time/test/time.rb +++ b/mrbgems/mruby-time/test/time.rb @@ -211,3 +211,14 @@ assert('2000 times 500us make a second') do end t.usec == 0 end + +assert("Time#initialize doens't leave uninitialized object accessible") do + assert_raise ArgumentError do + $x = Time.new + a = Object.new + def a.to_i + $x.mday + end + $x.initialize a + end +end -- cgit v1.2.3 From be5223371b6e07d44c02aec2bd22aa1a1be404eb Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Fri, 25 Nov 2016 23:15:37 +0100 Subject: Fix typo in istruct.h --- include/mruby/istruct.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mruby/istruct.h b/include/mruby/istruct.h index 293a13788..4d2393ccd 100644 --- a/include/mruby/istruct.h +++ b/include/mruby/istruct.h @@ -1,5 +1,5 @@ /* -** mruby/instruct.h - Inline structures +** mruby/istruct.h - Inline structures ** ** See Copyright Notice in mruby.h */ -- cgit v1.2.3 From 277e81a7c9d8689539d8087c512475c687c8680e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 26 Nov 2016 12:02:46 +0900 Subject: removed failing test for Time#initialize; ref #3295 --- mrbgems/mruby-time/test/time.rb | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/mrbgems/mruby-time/test/time.rb b/mrbgems/mruby-time/test/time.rb index 91a646759..759e2881d 100644 --- a/mrbgems/mruby-time/test/time.rb +++ b/mrbgems/mruby-time/test/time.rb @@ -211,14 +211,3 @@ assert('2000 times 500us make a second') do end t.usec == 0 end - -assert("Time#initialize doens't leave uninitialized object accessible") do - assert_raise ArgumentError do - $x = Time.new - a = Object.new - def a.to_i - $x.mday - end - $x.initialize a - end -end -- cgit v1.2.3 From 626648dc41314307ff4bab8e268d2dd013d63134 Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Sat, 26 Nov 2016 13:04:32 +0100 Subject: Fixed NaN boxing when MRB_INT16 is set --- include/mruby/boxing_nan.h | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/include/mruby/boxing_nan.h b/include/mruby/boxing_nan.h index 052164ffc..4cb82bf14 100644 --- a/include/mruby/boxing_nan.h +++ b/include/mruby/boxing_nan.h @@ -67,14 +67,12 @@ typedef struct mrb_value { #endif #define BOXNAN_SET_VALUE(o, tt, attr, v) do {\ - switch (tt) {\ - case MRB_TT_FALSE:\ - case MRB_TT_TRUE:\ - case MRB_TT_UNDEF:\ - case MRB_TT_FIXNUM:\ - case MRB_TT_SYMBOL: (o).attr = (v); break;\ - default: (o).value.i = 0; (o).value.p = (void*)((uintptr_t)(o).value.p | (((uintptr_t)(v))>>2)); break;\ - }\ + (o).attr = (v);\ + (o).value.ttt = 0xfff00000 | (((tt)+1)<<14);\ +} while (0) + +#define BOXNAN_SET_OBJ_VALUE(o, tt, v) do {\ + (o).value.p = (void*)((uintptr_t)(v)>>2);\ (o).value.ttt = (0xfff00000|(((tt)+1)<<14)|BOXNAN_SHIFT_LONG_POINTER(v));\ } while (0) @@ -92,8 +90,8 @@ typedef struct mrb_value { #define SET_BOOL_VALUE(r,b) BOXNAN_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1) #define SET_INT_VALUE(r,n) BOXNAN_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n)) #define SET_SYM_VALUE(r,v) BOXNAN_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v)) -#define SET_OBJ_VALUE(r,v) BOXNAN_SET_VALUE(r, (((struct RObject*)(v))->tt), value.p, (v)) -#define SET_CPTR_VALUE(mrb,r,v) BOXNAN_SET_VALUE(r, MRB_TT_CPTR, value.p, v) +#define SET_OBJ_VALUE(r,v) BOXNAN_SET_OBJ_VALUE(r, (((struct RObject*)(v))->tt), (v)) +#define SET_CPTR_VALUE(mrb,r,v) BOXNAN_SET_OBJ_VALUE(r, MRB_TT_CPTR, v) #define SET_UNDEF_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0) #endif /* MRUBY_BOXING_NAN_H */ -- cgit v1.2.3 From afee618c1bc25ca798863e07143e24a987758411 Mon Sep 17 00:00:00 2001 From: Herwin Weststrate Date: Sun, 27 Nov 2016 09:50:30 +0100 Subject: Added documentation on function for globals --- include/mruby/variable.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/include/mruby/variable.h b/include/mruby/variable.h index 15068039a..8b1cc2eef 100644 --- a/include/mruby/variable.h +++ b/include/mruby/variable.h @@ -54,9 +54,67 @@ MRB_API mrb_bool mrb_iv_defined(mrb_state*, mrb_value, mrb_sym); MRB_API mrb_value mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym); MRB_API void mrb_iv_copy(mrb_state *mrb, mrb_value dst, mrb_value src); MRB_API mrb_bool mrb_const_defined_at(mrb_state *mrb, mrb_value mod, mrb_sym id); + +/** + * Get a global variable. Will return nil if the var does not exist + * + * Example: + * + * !!!ruby + * # Ruby style + * var = $value + * + * !!!c + * // C style + * mrb_sym sym = mrb_intern_cstr(mrb, "$value"); + * mrb_value var = mrb_gv_get(mrb, sym); + * + * @param mrb The mruby state reference + * @param sym The name of the global variable + * @return The value of that global variable. May be nil + */ MRB_API mrb_value mrb_gv_get(mrb_state *mrb, mrb_sym sym); + +/** + * Set a global variable + * + * Example: + * + * !!!ruby + * # Ruby style + * $value = "foo" + * + * !!!c + * // C style + * mrb_sym sym = mrb_intern_cstr(mrb, "$value"); + * mrb_gv_set(mrb, sym, mrb_str_new_cstr("foo")); + * + * @param mrb The mruby state reference + * @param sym The name of the global variable + * @param val The value of the global variable + */ MRB_API void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value val); + +/** + * Remove a global variable. + * + * Example: + * + * !!!ruby + * # Ruby style + * $value = nil + * + * !!!c + * // C style + * mrb_sym sym = mrb_intern_cstr(mrb, "$value"); + * mrb_gv_remove(mrb, sym); + * + * @param mrb The mruby state reference + * @param sym The name of the global variable + * @param val The value of the global variable + */ MRB_API void mrb_gv_remove(mrb_state *mrb, mrb_sym sym); + MRB_API mrb_value mrb_cv_get(mrb_state *mrb, mrb_value mod, mrb_sym sym); MRB_API void mrb_mod_cv_set(mrb_state *mrb, struct RClass * c, mrb_sym sym, mrb_value v); MRB_API void mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v); -- cgit v1.2.3 From 3d9aa463f7ff5e813b04863c70d3aec0b0977946 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 26 Nov 2016 12:18:27 +0900 Subject: Add NULL checks for Time data retrieval --- mrbgems/mruby-time/src/time.c | 61 +++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index dfd4450da..089814890 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -368,6 +368,17 @@ mrb_time_local(mrb_state *mrb, mrb_value self) time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL)); } +static struct mrb_time* +time_get_ptr(mrb_state *mrb, mrb_value time) +{ + struct mrb_time *tm; + + tm = DATA_GET_PTR(mrb, time, &mrb_time_type, struct mrb_time); + if (!tm) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized time"); + } + return tm; +} static mrb_value mrb_time_eq(mrb_state *mrb, mrb_value self) @@ -377,7 +388,7 @@ mrb_time_eq(mrb_state *mrb, mrb_value self) mrb_bool eq_p; mrb_get_args(mrb, "o", &other); - tm1 = DATA_CHECK_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm1 = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time); eq_p = tm1 && tm2 && tm1->sec == tm2->sec && tm1->usec == tm2->usec; @@ -391,7 +402,7 @@ mrb_time_cmp(mrb_state *mrb, mrb_value self) struct mrb_time *tm1, *tm2; mrb_get_args(mrb, "o", &other); - tm1 = DATA_CHECK_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm1 = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time); if (!tm1 || !tm2) return mrb_nil_value(); if (tm1->sec > tm2->sec) { @@ -417,7 +428,7 @@ mrb_time_plus(mrb_state *mrb, mrb_value self) struct mrb_time *tm; mrb_get_args(mrb, "f", &f); - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec+f, (double)tm->usec, tm->timezone); } @@ -429,8 +440,7 @@ mrb_time_minus(mrb_state *mrb, mrb_value self) struct mrb_time *tm, *tm2; mrb_get_args(mrb, "o", &other); - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - + tm = time_get_ptr(mrb, self); tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time); if (tm2) { f = (mrb_float)(tm->sec - tm2->sec) @@ -450,7 +460,7 @@ mrb_time_wday(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); return mrb_fixnum_value(tm->datetime.tm_wday); } @@ -461,7 +471,7 @@ mrb_time_yday(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); return mrb_fixnum_value(tm->datetime.tm_yday + 1); } @@ -472,7 +482,7 @@ mrb_time_year(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); return mrb_fixnum_value(tm->datetime.tm_year + 1900); } @@ -483,7 +493,7 @@ mrb_time_zone(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); if (tm->timezone <= MRB_TIMEZONE_NONE) return mrb_nil_value(); if (tm->timezone >= MRB_TIMEZONE_LAST) return mrb_nil_value(); return mrb_str_new_static(mrb, @@ -501,7 +511,7 @@ mrb_time_asctime(mrb_state *mrb, mrb_value self) char buf[256]; int len; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); d = &tm->datetime; len = snprintf(buf, sizeof(buf), "%s %s %02d %02d:%02d:%02d %s%d", wday_names[d->tm_wday], mon_names[d->tm_mon], d->tm_mday, @@ -518,8 +528,7 @@ mrb_time_day(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - if (!tm) return mrb_nil_value(); + tm = time_get_ptr(mrb, self); return mrb_fixnum_value(tm->datetime.tm_mday); } @@ -531,7 +540,7 @@ mrb_time_dst_p(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); return mrb_bool_value(tm->datetime.tm_isdst); } @@ -543,7 +552,7 @@ mrb_time_getutc(mrb_state *mrb, mrb_value self) { struct mrb_time *tm, *tm2; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm)); *tm2 = *tm; tm2->timezone = MRB_TIMEZONE_UTC; @@ -558,7 +567,7 @@ mrb_time_getlocal(mrb_state *mrb, mrb_value self) { struct mrb_time *tm, *tm2; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm)); *tm2 = *tm; tm2->timezone = MRB_TIMEZONE_LOCAL; @@ -573,7 +582,7 @@ mrb_time_hour(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); return mrb_fixnum_value(tm->datetime.tm_hour); } @@ -638,7 +647,7 @@ mrb_time_localtime(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); tm->timezone = MRB_TIMEZONE_LOCAL; mrb_time_update_datetime(tm); return self; @@ -651,7 +660,7 @@ mrb_time_mday(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); return mrb_fixnum_value(tm->datetime.tm_mday); } @@ -662,7 +671,7 @@ mrb_time_min(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); return mrb_fixnum_value(tm->datetime.tm_min); } @@ -673,7 +682,7 @@ mrb_time_mon(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); return mrb_fixnum_value(tm->datetime.tm_mon + 1); } @@ -684,7 +693,7 @@ mrb_time_sec(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); return mrb_fixnum_value(tm->datetime.tm_sec); } @@ -696,7 +705,7 @@ mrb_time_to_f(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); return mrb_float_value(mrb, (mrb_float)tm->sec + (mrb_float)tm->usec/1.0e6); } @@ -707,7 +716,7 @@ mrb_time_to_i(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); if (tm->sec > MRB_INT_MAX || tm->sec < MRB_INT_MIN) { return mrb_float_value(mrb, (mrb_float)tm->sec); } @@ -721,7 +730,7 @@ mrb_time_usec(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); if (tm->usec > MRB_INT_MAX || tm->usec < MRB_INT_MIN) { return mrb_float_value(mrb, (mrb_float)tm->usec); } @@ -735,7 +744,7 @@ mrb_time_utc(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); tm->timezone = MRB_TIMEZONE_UTC; mrb_time_update_datetime(tm); return self; @@ -748,7 +757,7 @@ mrb_time_utc_p(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); + tm = time_get_ptr(mrb, self); return mrb_bool_value(tm->timezone == MRB_TIMEZONE_UTC); } -- cgit v1.2.3 From 3fdfd8cb4a80ff17a9478fa330cb2b544e76f088 Mon Sep 17 00:00:00 2001 From: Tomasz Dabrowski Date: Sun, 27 Nov 2016 12:49:36 +0100 Subject: Safeguard against using MRB_INT64 with MRB_WORD_BOXING in 32-bit mode --- include/mruby/boxing_word.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/mruby/boxing_word.h b/include/mruby/boxing_word.h index 8754087a3..30d69842f 100644 --- a/include/mruby/boxing_word.h +++ b/include/mruby/boxing_word.h @@ -11,6 +11,10 @@ # error MRB_INT16 is too small for MRB_WORD_BOXING. #endif +#if defined(MRB_INT64) && !defined(MRB_64BIT) +#error MRB_INT64 cannot be used with MRB_WORD_BOXING in 32-bit mode. +#endif + struct RFloat { MRB_OBJECT_HEADER; mrb_float f; -- cgit v1.2.3 From f9f19f34dd8b267895fb61223b194a6ae6bdc89e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 27 Nov 2016 20:53:25 +0900 Subject: replace _cstr by _lit for litral C strings; ref #3300 --- include/mruby.h | 10 +++++----- include/mruby/string.h | 12 ++++++------ include/mruby/variable.h | 8 ++++---- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/mruby.h b/include/mruby.h index bc6800e29..1e27b93fb 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -430,7 +430,7 @@ MRB_API void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_ * * mrb_value * mrb_example_method(mrb_state *mrb){ - * return mrb_str_new_cstr(mrb, "example"); + * return mrb_str_new_lit(mrb, "example"); * } * * void @@ -473,7 +473,7 @@ MRB_API void mrb_undef_method(mrb_state*, struct RClass*, const char*); * * mrb_value * mrb_example_method(mrb_state *mrb){ - * return mrb_str_new_cstr(mrb, "example"); + * return mrb_str_new_lit(mrb, "example"); * } * * void @@ -696,7 +696,7 @@ MRB_API mrb_value mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char * * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class); * mrb_define_method(mrb, example_class, "example_method", exampleMethod, MRB_ARGS_NONE()); - * mid = mrb_intern_str(mrb, mrb_str_new_cstr(mrb, "example_method" )); + * mid = mrb_intern_str(mrb, mrb_str_new_lit(mrb, "example_method" )); * obj_resp = mrb_obj_respond_to(mrb, example_class, mid); // => 1(true in Ruby world) * * // If mrb_obj_respond_to returns 1 then puts "True" @@ -884,7 +884,7 @@ MRB_API mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, mrb_int,...); * mrb_state *mrb = mrb_open(); * * if (!mrb) { } - * mrb_sym m_sym = mrb_intern_cstr(mrb, "method_name"); // Symbol for method. + * mrb_sym m_sym = mrb_intern_lit(mrb, "method_name"); // Symbol for method. * * FILE *fp = fopen("test.rb","r"); * mrb_value obj = mrb_load_file(mrb,fp); @@ -912,7 +912,7 @@ MRB_API mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, mrb_sym, mrb_int * :pizza # => :pizza * * // C style: - * mrb_sym m_sym = mrb_intern_cstr(mrb, "pizza"); // => :pizza + * mrb_sym m_sym = mrb_intern_lit(mrb, "pizza"); // => :pizza * @param [mrb_state*] mrb_state* The current mruby state. * @param [const char*] const char* The name of the method. * @return [mrb_sym] mrb_sym A symbol. diff --git a/include/mruby/string.h b/include/mruby/string.h index e45846e87..b30c1ed98 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -110,8 +110,8 @@ MRB_API void mrb_str_modify(mrb_state*, struct RString*); * } * * // Creates new Ruby strings. - * str1 = mrb_str_new_cstr(mrb, "abc"); - * str2 = mrb_str_new_cstr(mrb, "def"); + * str1 = mrb_str_new_lit(mrb, "abc"); + * str2 = mrb_str_new_lit(mrb, "def"); * * // Concatnates str2 to str1. * mrb_str_concat(mrb, str1, str2); @@ -158,8 +158,8 @@ MRB_API void mrb_str_concat(mrb_state*, mrb_value, mrb_value); * } * * // Creates two Ruby strings from the passed in C strings. - * a = mrb_str_new_cstr(mrb, "abc"); - * b = mrb_str_new_cstr(mrb, "def"); + * a = mrb_str_new_lit(mrb, "abc"); + * b = mrb_str_new_lit(mrb, "def"); * * // Prints both C strings. * mrb_p(mrb, a); @@ -227,7 +227,7 @@ MRB_API mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj); * // handle error * } * // Creates a new string. - * str = mrb_str_new_cstr(mrb, "Hello, world!"); + * str = mrb_str_new_lit(mrb, "Hello, world!"); * // Returns 5 characters of * mrb_str_resize(mrb, str, 5); * mrb_p(mrb, str); @@ -267,7 +267,7 @@ MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len); * // handle error * } * // Creates new string. - * str1 = mrb_str_new_cstr(mrb, "Hello, world!"); + * str1 = mrb_str_new_lit(mrb, "Hello, world!"); * // Returns a sub-string within the range of 0..2 * str2 = mrb_str_substr(mrb, str1, 0, 2); * diff --git a/include/mruby/variable.h b/include/mruby/variable.h index 8b1cc2eef..2f2bbbf98 100644 --- a/include/mruby/variable.h +++ b/include/mruby/variable.h @@ -66,7 +66,7 @@ MRB_API mrb_bool mrb_const_defined_at(mrb_state *mrb, mrb_value mod, mrb_sym id) * * !!!c * // C style - * mrb_sym sym = mrb_intern_cstr(mrb, "$value"); + * mrb_sym sym = mrb_intern_lit(mrb, "$value"); * mrb_value var = mrb_gv_get(mrb, sym); * * @param mrb The mruby state reference @@ -86,8 +86,8 @@ MRB_API mrb_value mrb_gv_get(mrb_state *mrb, mrb_sym sym); * * !!!c * // C style - * mrb_sym sym = mrb_intern_cstr(mrb, "$value"); - * mrb_gv_set(mrb, sym, mrb_str_new_cstr("foo")); + * mrb_sym sym = mrb_intern_lit(mrb, "$value"); + * mrb_gv_set(mrb, sym, mrb_str_new_lit("foo")); * * @param mrb The mruby state reference * @param sym The name of the global variable @@ -106,7 +106,7 @@ MRB_API void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value val); * * !!!c * // C style - * mrb_sym sym = mrb_intern_cstr(mrb, "$value"); + * mrb_sym sym = mrb_intern_lit(mrb, "$value"); * mrb_gv_remove(mrb, sym); * * @param mrb The mruby state reference -- cgit v1.2.3 From 36fc1f1431d9aa85c167f91ef30abe0953c56400 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 27 Nov 2016 22:17:51 +0900 Subject: Added Exception check in mrb_exc_set(); close #3292 PR #3293 just checks for NoMethodError. --- src/error.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/error.c b/src/error.c index 13032b136..9ff570bf6 100644 --- a/src/error.c +++ b/src/error.c @@ -278,6 +278,8 @@ 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); } } -- cgit v1.2.3 From 27ceb848180463e66e080d13c3a96b1e56dbddbd Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 27 Nov 2016 22:43:46 +0900 Subject: parse.y: use opt_paren_args to simplify yield rule --- mrbgems/mruby-compiler/core/parse.y | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index c44669f45..3a14b4fcc 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -2137,17 +2137,9 @@ primary : literal { $$ = new_return(p, 0); } - | keyword_yield '(' call_args rparen + | keyword_yield opt_paren_args { - $$ = new_yield(p, $3); - } - | keyword_yield '(' rparen - { - $$ = new_yield(p, 0); - } - | keyword_yield - { - $$ = new_yield(p, 0); + $$ = new_yield(p, $2); } | keyword_not '(' expr rparen { -- cgit v1.2.3 From 9fc62d28d0e5738368571d70f1be191876e91d8b Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 28 Nov 2016 09:52:57 +0900 Subject: pre-allocate arena overflow error --- include/mruby.h | 3 +++ src/error.c | 5 ++++- src/gc.c | 5 ++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/mruby.h b/include/mruby.h index 1e27b93fb..6e222057f 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -221,6 +221,9 @@ typedef struct mrb_state { struct RClass *eException_class; struct RClass *eStandardError_class; struct RObject *nomem_err; /* pre-allocated NoMemoryError */ +#ifdef MRB_GC_FIXED_ARENA + struct RObject *arena_err; /* pre-allocated arena overfow error */ +#endif void *ud; /* auxiliary data */ diff --git a/src/error.c b/src/error.c index 9ff570bf6..b24aed798 100644 --- a/src/error.c +++ b/src/error.c @@ -465,7 +465,7 @@ exception_call: } if (argc > 0) { if (!mrb_obj_is_kind_of(mrb, mesg, mrb->eException_class)) - mrb_raise(mrb, E_TYPE_ERROR, "exception object expected"); + mrb_raise(mrb, mrb->eException_class, "exception object expected"); if (argc > 2) set_backtrace(mrb, mesg, argv[2]); } @@ -532,6 +532,9 @@ mrb_init_exception(mrb_state *mrb) mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */ runtime_error = mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */ mrb->nomem_err = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, runtime_error, "Out of memory")); +#ifdef MRB_GC_FIXED_ARENA + mrb->arena_err = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, runtime_error, "arena overflow error")); +#endif script_error = mrb_define_class(mrb, "ScriptError", mrb->eException_class); /* 15.2.37 */ mrb_define_class(mrb, "SyntaxError", script_error); /* 15.2.38 */ mrb_define_class(mrb, "SystemStackError", exception); diff --git a/src/gc.c b/src/gc.c index b29df1f02..ecc09374e 100644 --- a/src/gc.c +++ b/src/gc.c @@ -403,7 +403,7 @@ gc_protect(mrb_state *mrb, mrb_gc *gc, struct RBasic *p) if (gc->arena_idx >= MRB_GC_ARENA_SIZE) { /* arena overflow error */ gc->arena_idx = MRB_GC_ARENA_SIZE - 4; /* force room in arena */ - mrb_raise(mrb, E_RUNTIME_ERROR, "arena overflow error"); + mrb_exc_raise(mrb, mrb_obj_value(mrb->arena_err)); } #else if (gc->arena_idx >= gc->arena_capa) { @@ -816,6 +816,9 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc) mrb_gc_mark(mrb, (struct RBasic*)mrb->exc); /* mark pre-allocated exception */ mrb_gc_mark(mrb, (struct RBasic*)mrb->nomem_err); +#ifdef MRB_GC_FIXED_ARENA + mrb_gc_mark(mrb, (struct RBasic*)mrb->arena_err); +#endif mark_context(mrb, mrb->root_c); if (mrb->root_c->fib) { -- cgit v1.2.3 From 246a9a8acd4e45a184ffd11bdd92a5b7736bf1cd Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 29 Nov 2016 22:36:11 +0900 Subject: ary_concat: support self concatenation; fix #3302 --- src/array.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/array.c b/src/array.c index 106353c07..ed83bd446 100644 --- a/src/array.c +++ b/src/array.c @@ -245,13 +245,15 @@ mrb_ary_s_create(mrb_state *mrb, mrb_value self) } static void -ary_concat(mrb_state *mrb, struct RArray *a, mrb_value *ptr, mrb_int blen) +ary_concat(mrb_state *mrb, struct RArray *a, struct RArray *a2) { - mrb_int len = a->len + blen; + mrb_int len = a->len + a2->len; ary_modify(mrb, a); - if (a->aux.capa < len) ary_expand_capa(mrb, a, len); - array_copy(a->ptr+a->len, ptr, blen); + if (a->aux.capa < len) { + ary_expand_capa(mrb, a, len); + } + array_copy(a->ptr+a->len, a2->ptr, a2->len); mrb_write_barrier(mrb, (struct RBasic*)a); a->len = len; } @@ -261,17 +263,16 @@ mrb_ary_concat(mrb_state *mrb, mrb_value self, mrb_value other) { struct RArray *a2 = mrb_ary_ptr(other); - ary_concat(mrb, mrb_ary_ptr(self), a2->ptr, a2->len); + ary_concat(mrb, mrb_ary_ptr(self), a2); } static mrb_value mrb_ary_concat_m(mrb_state *mrb, mrb_value self) { - mrb_value *ptr; - mrb_int blen; + mrb_value ary; - mrb_get_args(mrb, "a", &ptr, &blen); - ary_concat(mrb, mrb_ary_ptr(self), ptr, blen); + mrb_get_args(mrb, "A", &ary); + mrb_ary_concat(mrb, self, ary); return self; } -- cgit v1.2.3 From 523c267020787c3545bd72f27362cf8727372c0d Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 28 Nov 2016 13:37:20 -0500 Subject: Interpret argument in 'f ()' as nil instead of nothing --- mrbgems/mruby-compiler/bintest/mrbc.rb | 9 +++++++++ mrbgems/mruby-compiler/core/parse.y | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-compiler/bintest/mrbc.rb b/mrbgems/mruby-compiler/bintest/mrbc.rb index e4dc6a9a8..e27365edb 100644 --- a/mrbgems/mruby-compiler/bintest/mrbc.rb +++ b/mrbgems/mruby-compiler/bintest/mrbc.rb @@ -10,3 +10,12 @@ assert('Compiling multiple files without new line in last line. #2361') do assert_equal "#{cmd('mrbc')}:#{a.path}:Syntax OK", result.chomp assert_equal 0, $?.exitstatus end + +assert('parsing function with void argument') do + a, out = Tempfile.new('a.rb'), Tempfile.new('out.mrb') + a.write('f ()') + a.flush + result = `#{cmd('mrbc')} -c -o #{out.path} #{a.path} 2>&1` + assert_equal "#{cmd('mrbc')}:#{a.path}:Syntax OK", result.chomp + assert_equal 0, $?.exitstatus +end diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 3a14b4fcc..9f6914104 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -2109,7 +2109,7 @@ primary : literal } | tLPAREN_ARG {p->lstate = EXPR_ENDARG;} rparen { - $$ = 0; + $$ = new_nil(p); } | tLPAREN compstmt ')' { -- cgit v1.2.3 From b633aa9ad466277cf583f60b8e424e516362f0bf Mon Sep 17 00:00:00 2001 From: Clayton Smith Date: Tue, 29 Nov 2016 10:26:02 -0500 Subject: Use size_t to calculate bytes needed for array. --- src/array.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/array.c b/src/array.c index ed83bd446..df037a121 100644 --- a/src/array.c +++ b/src/array.c @@ -20,15 +20,12 @@ static struct RArray* ary_new_capa(mrb_state *mrb, mrb_int capa) { struct RArray *a; - mrb_int blen; + size_t blen; if (capa > ARY_MAX_SIZE) { mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } blen = capa * sizeof(mrb_value); - if (blen < capa) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); - } a = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class); a->ptr = (mrb_value *)mrb_malloc(mrb, blen); -- cgit v1.2.3 From 630733f34698047e3b7b4e66cf929f626123b14e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 30 Nov 2016 03:38:55 +0900 Subject: check ttype before object allocation; fix #3294 --- src/gc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/gc.c b/src/gc.c index ecc09374e..69708e40b 100644 --- a/src/gc.c +++ b/src/gc.c @@ -479,6 +479,17 @@ mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) static const RVALUE RVALUE_zero = { { { MRB_TT_FALSE } } }; mrb_gc *gc = &mrb->gc; + if (cls) { + enum mrb_vtype tt = MRB_INSTANCE_TT(cls); + if (tt != MRB_TT_FALSE && + ttype != MRB_TT_SCLASS && + ttype != MRB_TT_ICLASS && + ttype != MRB_TT_ENV && + ttype != tt) { + mrb_raisef(mrb, E_TYPE_ERROR, "allocation failure of %S", mrb_obj_value(cls)); + } + } + #ifdef MRB_GC_STRESS mrb_full_gc(mrb); #endif -- cgit v1.2.3 From 37743111d98558e6467f9d5e5498031b3300581f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 30 Nov 2016 03:49:56 +0900 Subject: should not refer Struct class by name; fix #3296 --- mrbgems/mruby-struct/src/struct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index edb6f6a0a..93bd1e2b2 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -287,7 +287,7 @@ mrb_struct_s_def(mrb_state *mrb, mrb_value klass) mrb_ary_set(mrb, rest, i, mrb_symbol_value(id)); } } - st = make_struct(mrb, name, rest, struct_class(mrb)); + st = make_struct(mrb, name, rest, mrb_class_ptr(klass)); if (!mrb_nil_p(b)) { mrb_yield_with_class(mrb, b, 1, &st, st, mrb_class_ptr(st)); } -- cgit v1.2.3 From 5771c9778e917803adeb6e3f6ab7b0680d10aaa1 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 30 Nov 2016 03:51:23 +0900 Subject: add a test for #3296 --- mrbgems/mruby-struct/test/struct.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mrbgems/mruby-struct/test/struct.rb b/mrbgems/mruby-struct/test/struct.rb index 2fe684960..1c0939e7f 100644 --- a/mrbgems/mruby-struct/test/struct.rb +++ b/mrbgems/mruby-struct/test/struct.rb @@ -187,3 +187,13 @@ assert("Struct.new does not allow array") do Struct.new("Test", [:a]) end end + +assert("Struct.new generates subclass of Struct") do + begin + original_struct = Struct + Struct = String + assert_equal original_struct, original_struct.new.superclass + ensure + Struct = original_struct + end +end -- cgit v1.2.3 From 2bb47addadb3eda796520837c21d694c8d6e3320 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 30 Nov 2016 10:36:17 +0900 Subject: Prohibit instantiation of immediate objects --- src/class.c | 3 +++ src/numeric.c | 3 +++ src/object.c | 4 ++++ src/symbol.c | 3 +++ 4 files changed, 13 insertions(+) diff --git a/src/class.c b/src/class.c index d120f1fec..bac1d2984 100644 --- a/src/class.c +++ b/src/class.c @@ -1348,6 +1348,9 @@ mrb_instance_alloc(mrb_state *mrb, mrb_value cv) mrb_raise(mrb, E_TYPE_ERROR, "can't create instance of singleton class"); if (ttype == 0) ttype = MRB_TT_OBJECT; + if (ttype <= MRB_TT_CPTR) { + mrb_raisef(mrb, E_TYPE_ERROR, "can't create instance of %S", cv); + } o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c); return mrb_obj_value(o); } diff --git a/src/numeric.c b/src/numeric.c index c86373318..25a411de8 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef MRB_USE_FLOAT #define trunc(f) truncf(f) @@ -1265,6 +1266,7 @@ mrb_init_numeric(mrb_state *mrb) /* Integer Class */ integer = mrb_define_class(mrb, "Integer", numeric); /* 15.2.8 */ + MRB_SET_INSTANCE_TT(integer, MRB_TT_FIXNUM); mrb_undef_class_method(mrb, integer, "new"); mrb_define_method(mrb, integer, "to_i", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.24 */ mrb_define_method(mrb, integer, "to_int", int_to_i, MRB_ARGS_NONE()); @@ -1291,6 +1293,7 @@ mrb_init_numeric(mrb_state *mrb) /* Float Class */ mrb->float_class = fl = mrb_define_class(mrb, "Float", numeric); /* 15.2.9 */ + MRB_SET_INSTANCE_TT(fl, MRB_TT_FLOAT); mrb_undef_class_method(mrb, fl, "new"); mrb_define_method(mrb, fl, "+", flo_plus, MRB_ARGS_REQ(1)); /* 15.2.9.3.1 */ mrb_define_method(mrb, fl, "-", flo_minus, MRB_ARGS_REQ(1)); /* 15.2.9.3.2 */ diff --git a/src/object.c b/src/object.c index c61feb342..f76ee68a2 100644 --- a/src/object.c +++ b/src/object.c @@ -8,6 +8,7 @@ #include #include #include +#include MRB_API mrb_bool mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2) @@ -265,6 +266,7 @@ mrb_init_object(mrb_state *mrb) struct RClass *f; mrb->nil_class = n = mrb_define_class(mrb, "NilClass", mrb->object_class); + MRB_SET_INSTANCE_TT(n, MRB_TT_TRUE); mrb_undef_class_method(mrb, n, "new"); mrb_define_method(mrb, n, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.4.3.1 */ mrb_define_method(mrb, n, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.4.3.2 */ @@ -274,6 +276,7 @@ mrb_init_object(mrb_state *mrb) mrb_define_method(mrb, n, "inspect", nil_inspect, MRB_ARGS_NONE()); mrb->true_class = t = mrb_define_class(mrb, "TrueClass", mrb->object_class); + MRB_SET_INSTANCE_TT(t, MRB_TT_TRUE); mrb_undef_class_method(mrb, t, "new"); mrb_define_method(mrb, t, "&", true_and, MRB_ARGS_REQ(1)); /* 15.2.5.3.1 */ mrb_define_method(mrb, t, "^", true_xor, MRB_ARGS_REQ(1)); /* 15.2.5.3.2 */ @@ -282,6 +285,7 @@ mrb_init_object(mrb_state *mrb) mrb_define_method(mrb, t, "inspect", true_to_s, MRB_ARGS_NONE()); mrb->false_class = f = mrb_define_class(mrb, "FalseClass", mrb->object_class); + MRB_SET_INSTANCE_TT(f, MRB_TT_TRUE); mrb_undef_class_method(mrb, f, "new"); mrb_define_method(mrb, f, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.6.3.1 */ mrb_define_method(mrb, f, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.6.3.2 */ diff --git a/src/symbol.c b/src/symbol.c index 25ae132e1..a3ab05c85 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -10,6 +10,7 @@ #include #include #include +#include /* ------------------------------------------------------ */ typedef struct symbol_name { @@ -481,6 +482,8 @@ mrb_init_symbol(mrb_state *mrb) struct RClass *sym; mrb->symbol_class = sym = mrb_define_class(mrb, "Symbol", mrb->object_class); /* 15.2.11 */ + MRB_SET_INSTANCE_TT(sym, MRB_TT_SYMBOL); + mrb_undef_class_method(mrb, sym, "new"); mrb_define_method(mrb, sym, "===", sym_equal, MRB_ARGS_REQ(1)); /* 15.2.11.3.1 */ mrb_define_method(mrb, sym, "id2name", mrb_sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.2 */ -- cgit v1.2.3 From 8675975ba212be389624ed165c287e9988e916db Mon Sep 17 00:00:00 2001 From: ksss Date: Wed, 30 Nov 2016 11:02:02 +0900 Subject: Implement Enumerable::Lazy#to_enum and enum_for --- mrbgems/mruby-enum-lazy/mrblib/lazy.rb | 9 +++++++++ mrbgems/mruby-enum-lazy/test/lazy.rb | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/mrbgems/mruby-enum-lazy/mrblib/lazy.rb b/mrbgems/mruby-enum-lazy/mrblib/lazy.rb index 8ce363c6d..c9c3cc5fd 100644 --- a/mrbgems/mruby-enum-lazy/mrblib/lazy.rb +++ b/mrbgems/mruby-enum-lazy/mrblib/lazy.rb @@ -40,6 +40,15 @@ module Enumerable } end + def to_enum(meth=:each, *args, &block) + lz = Lazy.new(self, &block) + lz.obj = self + lz.meth = meth + lz.args = args + lz + end + alias enum_for to_enum + def map(&block) Lazy.new(self){|yielder, val| yielder << block.call(val) diff --git a/mrbgems/mruby-enum-lazy/test/lazy.rb b/mrbgems/mruby-enum-lazy/test/lazy.rb index ca009d34c..5218f97d9 100644 --- a/mrbgems/mruby-enum-lazy/test/lazy.rb +++ b/mrbgems/mruby-enum-lazy/test/lazy.rb @@ -40,6 +40,12 @@ assert("Enumerable::Lazy laziness") do assert_equal [10,20], a.b end +assert("Enumrable::Lazy#to_enum") do + lazy_enum = (0..Float::INFINITY).lazy.to_enum(:each_slice, 2) + assert_kind_of Enumerable::Lazy, lazy_enum + assert_equal [0*1, 2*3, 4*5, 6*7], lazy_enum.map { |a| a.first * a.last }.first(4) +end + assert("Enumerable::Lazy#zip with cycle") do e1 = [1, 2, 3].cycle e2 = [:a, :b].cycle -- cgit v1.2.3 From 0f90227907b15f879319600cfa523be5928c5da9 Mon Sep 17 00:00:00 2001 From: ksss Date: Wed, 30 Nov 2016 12:36:22 +0900 Subject: Change Lazy class outer Lazy class should be under Enumerator instead of Enumerable --- mrbgems/default.gembox | 2 +- mrbgems/mruby-enum-lazy/mrbgem.rake | 2 +- mrbgems/mruby-enum-lazy/mrblib/lazy.rb | 6 ++++-- mrbgems/mruby-enum-lazy/test/lazy.rb | 8 ++++---- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/mrbgems/default.gembox b/mrbgems/default.gembox index dab7230aa..64f05de10 100644 --- a/mrbgems/default.gembox +++ b/mrbgems/default.gembox @@ -53,7 +53,7 @@ MRuby::GemBox.new do |conf| # Use Enumerator class (require mruby-fiber) conf.gem :core => "mruby-enumerator" - # Use Enumerable::Lazy class (require mruby-enumerator) + # Use Enumerator::Lazy class (require mruby-enumerator) conf.gem :core => "mruby-enum-lazy" # Use toplevel object (main) methods extension diff --git a/mrbgems/mruby-enum-lazy/mrbgem.rake b/mrbgems/mruby-enum-lazy/mrbgem.rake index 219141e98..682134c41 100644 --- a/mrbgems/mruby-enum-lazy/mrbgem.rake +++ b/mrbgems/mruby-enum-lazy/mrbgem.rake @@ -1,7 +1,7 @@ MRuby::Gem::Specification.new('mruby-enum-lazy') do |spec| spec.license = 'MIT' spec.author = 'mruby developers' - spec.summary = 'Enumerable::Lazy class' + spec.summary = 'Enumerator::Lazy class' spec.add_dependency('mruby-enumerator', :core => 'mruby-enumerator') spec.add_dependency('mruby-enum-ext', :core => 'mruby-enum-ext') end diff --git a/mrbgems/mruby-enum-lazy/mrblib/lazy.rb b/mrbgems/mruby-enum-lazy/mrblib/lazy.rb index 8ce363c6d..28cffdc03 100644 --- a/mrbgems/mruby-enum-lazy/mrblib/lazy.rb +++ b/mrbgems/mruby-enum-lazy/mrblib/lazy.rb @@ -2,7 +2,7 @@ module Enumerable # = Enumerable#lazy implementation # - # Enumerable#lazy returns an instance of Enumerable::Lazy. + # Enumerable#lazy returns an instance of Enumerator::Lazy. # You can use it just like as normal Enumerable object, # except these methods act as 'lazy': # @@ -16,9 +16,11 @@ module Enumerable # - flat_map collect_concat # - zip def lazy - Lazy.new(self) + Enumerator::Lazy.new(self) end +end +class Enumerator # == Acknowledgements # # Based on https://github.com/yhara/enumerable-lazy diff --git a/mrbgems/mruby-enum-lazy/test/lazy.rb b/mrbgems/mruby-enum-lazy/test/lazy.rb index ca009d34c..422e0baeb 100644 --- a/mrbgems/mruby-enum-lazy/test/lazy.rb +++ b/mrbgems/mruby-enum-lazy/test/lazy.rb @@ -1,9 +1,9 @@ -assert("Enumerable::Lazy") do +assert("Enumerator::Lazy") do a = [1, 2] - assert_equal Enumerable::Lazy, a.lazy.class + assert_equal Enumerator::Lazy, a.lazy.class end -assert("Enumerable::Lazy laziness") do +assert("Enumerator::Lazy laziness") do a = Object.new def a.each return to_enum :each unless block_given? @@ -40,7 +40,7 @@ assert("Enumerable::Lazy laziness") do assert_equal [10,20], a.b end -assert("Enumerable::Lazy#zip with cycle") do +assert("Enumerator::Lazy#zip with cycle") do e1 = [1, 2, 3].cycle e2 = [:a, :b].cycle assert_equal [[1,:a],[2,:b],[3,:a]], e1.lazy.zip(e2).first(3) -- cgit v1.2.3 From 8461a31cb491f272524d14a9e54fcc9fae7a22c1 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 30 Nov 2016 13:04:50 +0900 Subject: Fixed too much void_expr_error(); fix #3307 --- mrbgems/mruby-compiler/core/parse.y | 1 - 1 file changed, 1 deletion(-) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 9f6914104..ef522d239 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -1936,7 +1936,6 @@ arg_rhs : arg %prec tOP_ASGN | arg modifier_rescue arg { void_expr_error(p, $1); - void_expr_error(p, $3); $$ = new_mod_rescue(p, $1, $3); } ; -- cgit v1.2.3 From acdddb4f1431945e61030a436f4a611307bc4420 Mon Sep 17 00:00:00 2001 From: Clayton Smith Date: Wed, 30 Nov 2016 13:55:09 -0500 Subject: Prevent array size calculation overflows. --- src/array.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/array.c b/src/array.c index df037a121..8902f2dda 100644 --- a/src/array.c +++ b/src/array.c @@ -118,7 +118,7 @@ ary_modify(mrb_state *mrb, struct RArray *a) } else { mrb_value *ptr, *p; - mrb_int len; + size_t len; p = a->ptr; len = a->len * sizeof(mrb_value); @@ -244,6 +244,9 @@ mrb_ary_s_create(mrb_state *mrb, mrb_value self) static void ary_concat(mrb_state *mrb, struct RArray *a, struct RArray *a2) { + 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; ary_modify(mrb, a); @@ -559,7 +562,7 @@ static struct RArray* ary_dup(mrb_state *mrb, struct RArray *a) { struct RArray *d = ary_new_capa(mrb, a->len); - + ary_replace(mrb, d, a->ptr, a->len); return d; } -- cgit v1.2.3 From 31f0ffeac8dc2214d432be3ef78f9776dad32cb0 Mon Sep 17 00:00:00 2001 From: ksss Date: Thu, 1 Dec 2016 10:39:46 +0900 Subject: Support Enumerable methods --- mrbgems/mruby-enumerator/mrblib/enumerator.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/mrbgems/mruby-enumerator/mrblib/enumerator.rb b/mrbgems/mruby-enumerator/mrblib/enumerator.rb index 9abaca38a..1515a7a89 100644 --- a/mrbgems/mruby-enumerator/mrblib/enumerator.rb +++ b/mrbgems/mruby-enumerator/mrblib/enumerator.rb @@ -516,6 +516,7 @@ class Enumerator # just for internal class Generator + include Enumerable def initialize(&block) raise TypeError, "wrong argument type #{self.class} (expected Proc)" unless block.kind_of? Proc -- 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(+) 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 0f774ff4dfc168aa90764b0130d60f14b837cc53 Mon Sep 17 00:00:00 2001 From: ksss Date: Thu, 1 Dec 2016 15:29:43 +0900 Subject: Support nil argument as no argument --- mrbgems/mruby-enumerator/mrblib/enumerator.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/mrbgems/mruby-enumerator/mrblib/enumerator.rb b/mrbgems/mruby-enumerator/mrblib/enumerator.rb index 1515a7a89..694ad4270 100644 --- a/mrbgems/mruby-enumerator/mrblib/enumerator.rb +++ b/mrbgems/mruby-enumerator/mrblib/enumerator.rb @@ -153,9 +153,15 @@ class Enumerator # def with_index(offset=0) return to_enum :with_index, offset unless block_given? - raise TypeError, "no implicit conversion of #{offset.class} into Integer" unless offset.respond_to?(:to_int) + offset = if offset.nil? + 0 + elsif offset.respond_to?(:to_int) + offset.to_int + else + raise TypeError, "no implicit conversion of #{offset.class} into Integer" + end - n = offset.to_int - 1 + n = offset - 1 enumerator_block_call do |i| n += 1 yield [i,n] -- cgit v1.2.3 From 2718fed1248872e6af436159a8f336fb54b86df2 Mon Sep 17 00:00:00 2001 From: ksss Date: Thu, 1 Dec 2016 15:32:29 +0900 Subject: Support svalue --- mrbgems/mruby-enumerator/mrblib/enumerator.rb | 4 ++-- mrbgems/mruby-enumerator/test/enumerator.rb | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/mrbgems/mruby-enumerator/mrblib/enumerator.rb b/mrbgems/mruby-enumerator/mrblib/enumerator.rb index 694ad4270..89b66cd45 100644 --- a/mrbgems/mruby-enumerator/mrblib/enumerator.rb +++ b/mrbgems/mruby-enumerator/mrblib/enumerator.rb @@ -162,9 +162,9 @@ class Enumerator end n = offset - 1 - enumerator_block_call do |i| + enumerator_block_call do |*i| n += 1 - yield [i,n] + yield i.__svalue, n end end diff --git a/mrbgems/mruby-enumerator/test/enumerator.rb b/mrbgems/mruby-enumerator/test/enumerator.rb index 2e45dae4b..e86e874f0 100644 --- a/mrbgems/mruby-enumerator/test/enumerator.rb +++ b/mrbgems/mruby-enumerator/test/enumerator.rb @@ -50,6 +50,9 @@ end assert 'Enumerator#with_index' do assert_equal([[1,0],[2,1],[3,2]], @obj.to_enum(:foo, 1, 2, 3).with_index.to_a) assert_equal([[1,5],[2,6],[3,7]], @obj.to_enum(:foo, 1, 2, 3).with_index(5).to_a) + a = [] + @obj.to_enum(:foo, 1, 2, 3).with_index(10).with_index(20) { |*i| a << i } + assert_equal [[[1, 10], 20], [[2, 11], 21], [[3, 12], 22]], a end assert 'Enumerator#with_index nonnum offset' do -- cgit v1.2.3 From e4086d4014df49cb49e1c3391964cf064d42a3d4 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 1 Dec 2016 16:46:59 +0900 Subject: Fix compile error by #3309 --- src/array.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/array.c b/src/array.c index 8902f2dda..9013492fb 100644 --- a/src/array.c +++ b/src/array.c @@ -244,10 +244,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) { -- 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(-) 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 fed40b44b8ec56c977b85be65ff460dcf713dc3c Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 1 Dec 2016 11:30:07 +0900 Subject: Extract read_escape_unicode from read_escape --- mrbgems/mruby-compiler/core/parse.y | 88 +++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index ef522d239..65b89bed3 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, size_t 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 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 */ -- 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(+) 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 ab4ab7c8a0e5226e4a76f7c37bdb79d2c92c004f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 1 Dec 2016 18:37:03 +0900 Subject: Fix compile error by #3309 --- src/array.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/array.c b/src/array.c index 8902f2dda..9013492fb 100644 --- a/src/array.c +++ b/src/array.c @@ -244,10 +244,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) { -- cgit v1.2.3 From 2cca9d368815e9c83a7489c40d69937d68cb43a2 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 1 Dec 2016 18:49:39 +0900 Subject: avoid comparison between signed and unsigned integer; ref #3312 --- mrbgems/mruby-compiler/core/parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index f0c45b85b..bf893fb37 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3753,7 +3753,7 @@ scan_hex(const int *start, int len, int *retlen) } static int32_t -read_escape_unicode(parser_state *p, size_t limit) +read_escape_unicode(parser_state *p, int limit) { int32_t c; int buf[9]; -- cgit v1.2.3 From 2bc3a5fb781056675931c1a3da435c24ad57b4bd Mon Sep 17 00:00:00 2001 From: Clayton Smith Date: Wed, 30 Nov 2016 16:30:30 -0500 Subject: Fix more integer overflows. --- src/array.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/array.c b/src/array.c index 9013492fb..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); @@ -503,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 */ { -- cgit v1.2.3 From 7d07466b437910d560fda2f78d2f7b93205eaa22 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Tue, 29 Nov 2016 10:54:21 -0500 Subject: Fix stack move segfaulting in OP_ARYCAT Reported by https://hackerone.com/haquaman Testcase (couldn't get it to work as a test): def nil.b b *nil end nil.b --- src/vm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vm.c b/src/vm.c index 41e19b0c0..f0dc338d0 100644 --- a/src/vm.c +++ b/src/vm.c @@ -2134,8 +2134,8 @@ RETRY_TRY_BLOCK: CASE(OP_ARYCAT) { /* A B mrb_ary_concat(R(A),R(B)) */ - mrb_ary_concat(mrb, regs[GETARG_A(i)], - mrb_ary_splat(mrb, regs[GETARG_B(i)])); + mrb_value splat = mrb_ary_splat(mrb, regs[GETARG_B(i)]); + mrb_ary_concat(mrb, regs[GETARG_A(i)], splat); ARENA_RESTORE(mrb, ai); NEXT; } -- 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(-) 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(-) 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(-) 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 79a621dd739faf4cc0958e11d6a887331cf79e48 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 3 Dec 2016 12:27:48 +0900 Subject: Check before retrieving struct RRange pointer; fix #3320 range->edges may be NULL for example when #initialize_copy removed. --- include/mruby/range.h | 3 ++- mrbgems/mruby-range-ext/src/range.c | 6 +++--- src/range.c | 39 ++++++++++++++++++++++++------------- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/include/mruby/range.h b/include/mruby/range.h index cf42ce133..fb602b3f3 100644 --- a/include/mruby/range.h +++ b/include/mruby/range.h @@ -25,7 +25,8 @@ struct RRange { mrb_bool excl : 1; }; -#define mrb_range_ptr(v) ((struct RRange*)(mrb_ptr(v))) +MRB_API struct RRange* mrb_range_ptr(mrb_state *mrb, mrb_value v); +#define mrb_range_raw_ptr(v) ((struct RRange*)mrb_ptr(v)) #define mrb_range_value(p) mrb_obj_value((void*)(p)) /* diff --git a/mrbgems/mruby-range-ext/src/range.c b/mrbgems/mruby-range-ext/src/range.c index ccb5a9e45..8aa1379b0 100644 --- a/mrbgems/mruby-range-ext/src/range.c +++ b/mrbgems/mruby-range-ext/src/range.c @@ -44,7 +44,7 @@ static mrb_value mrb_range_cover(mrb_state *mrb, mrb_value range) { mrb_value val; - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); mrb_value beg, end; mrb_get_args(mrb, "o", &val); @@ -87,7 +87,7 @@ mrb_range_last(mrb_state *mrb, mrb_value range) { mrb_value num; mrb_value array; - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); if (mrb_get_args(mrb, "|o", &num) == 0) { return r->edges->end; @@ -111,7 +111,7 @@ mrb_range_last(mrb_state *mrb, mrb_value range) static mrb_value mrb_range_size(mrb_state *mrb, mrb_value range) { - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); mrb_value beg, end; mrb_float beg_f, end_f; mrb_bool num_p = TRUE; diff --git a/src/range.c b/src/range.c index f0a976e53..417957420 100644 --- a/src/range.c +++ b/src/range.c @@ -12,6 +12,17 @@ #define RANGE_CLASS (mrb_class_get(mrb, "Range")) +MRB_API struct RRange* +mrb_range_ptr(mrb_state *mrb, mrb_value v) +{ + struct RRange *r = (struct RRange*)mrb_ptr(v); + + if (r->edges == NULL) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized range"); + } + return r; +} + static void range_check(mrb_state *mrb, mrb_value a, mrb_value b) { @@ -57,7 +68,7 @@ mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, mrb_bool excl) mrb_value mrb_range_beg(mrb_state *mrb, mrb_value range) { - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); return r->edges->beg; } @@ -76,7 +87,7 @@ mrb_range_beg(mrb_state *mrb, mrb_value range) mrb_value mrb_range_end(mrb_state *mrb, mrb_value range) { - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); return r->edges->end; } @@ -90,7 +101,7 @@ mrb_range_end(mrb_state *mrb, mrb_value range) mrb_value mrb_range_excl(mrb_state *mrb, mrb_value range) { - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); return mrb_bool_value(r->excl); } @@ -98,7 +109,7 @@ mrb_range_excl(mrb_state *mrb, mrb_value range) static void range_init(mrb_state *mrb, mrb_value range, mrb_value beg, mrb_value end, mrb_bool exclude_end) { - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_raw_ptr(range); range_check(mrb, beg, end); r->excl = exclude_end; @@ -129,7 +140,7 @@ 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) { + if (mrb_range_raw_ptr(range)->edges) { mrb_name_error(mrb, mrb_intern_lit(mrb, "initialize"), "`initialize' called twice"); } range_init(mrb, range, beg, end, exclusive); @@ -164,8 +175,8 @@ mrb_range_eq(mrb_state *mrb, mrb_value range) return mrb_false_value(); } - rr = mrb_range_ptr(range); - ro = mrb_range_ptr(obj); + rr = mrb_range_ptr(mrb, range); + ro = mrb_range_ptr(mrb, obj); v1 = mrb_funcall(mrb, rr->edges->beg, "==", 1, ro->edges->beg); v2 = mrb_funcall(mrb, rr->edges->end, "==", 1, ro->edges->end); if (!mrb_bool(v1) || !mrb_bool(v2) || rr->excl != ro->excl) { @@ -222,7 +233,7 @@ mrb_value mrb_range_include(mrb_state *mrb, mrb_value range) { mrb_value val; - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); mrb_value beg, end; mrb_bool include_p; @@ -241,7 +252,7 @@ static mrb_bool range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc) { mrb_int beg, end; - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); if (mrb_type(range) != MRB_TT_RANGE) return FALSE; @@ -287,7 +298,7 @@ static mrb_value range_to_s(mrb_state *mrb, mrb_value range) { mrb_value str, str2; - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); str = mrb_obj_as_string(mrb, r->edges->beg); str2 = mrb_obj_as_string(mrb, r->edges->end); @@ -312,7 +323,7 @@ static mrb_value range_inspect(mrb_state *mrb, mrb_value range) { mrb_value str, str2; - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); str = mrb_inspect(mrb, r->edges->beg); str2 = mrb_inspect(mrb, r->edges->end); @@ -352,8 +363,8 @@ range_eql(mrb_state *mrb, mrb_value range) } if (mrb_type(obj) != MRB_TT_RANGE) return mrb_false_value(); - r = mrb_range_ptr(range); - o = mrb_range_ptr(obj); + r = mrb_range_ptr(mrb, range); + o = mrb_range_ptr(mrb, obj); if (!mrb_eql(mrb, r->edges->beg, o->edges->beg) || !mrb_eql(mrb, r->edges->end, o->edges->end) || (r->excl != o->excl)) { @@ -376,7 +387,7 @@ range_initialize_copy(mrb_state *mrb, mrb_value copy) mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class"); } - r = mrb_range_ptr(src); + r = mrb_range_ptr(mrb, src); range_init(mrb, copy, r->edges->beg, r->edges->end, r->excl); return copy; -- cgit v1.2.3 From c029c6c4440c730c1ed5b0d6a10e81cebe23ac9c Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 3 Dec 2016 14:50:36 +0900 Subject: codegen: avoid unnecessary OP_MOVE after CASE --- mrbgems/mruby-compiler/core/codegen.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 2c75c8aed..414ca2627 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1520,7 +1520,9 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_A(OP_LOADNIL, cursp())); if (pos3) dispatch_linked(s, pos3); if (head) pop(); - genop(s, MKOP_AB(OP_MOVE, cursp(), pos)); + if (cursp() != pos) { + genop(s, MKOP_AB(OP_MOVE, cursp(), pos)); + } push(); } else { -- cgit v1.2.3 From 6b84ff4a443d55a5b94d3bfa8b0a7ba9ee9646dc Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 3 Dec 2016 16:21:15 +0900 Subject: Print NODE_SCALL (&.) from mrb_parser_dump() --- mrbgems/mruby-compiler/core/parse.y | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index bf893fb37..dc09d33ff 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -6067,7 +6067,17 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset) case NODE_FCALL: case NODE_CALL: - printf("NODE_CALL:\n"); + case NODE_SCALL: + switch (nodetype) { + case NODE_FCALL: + printf("NODE_FCALL:\n"); break; + case NODE_CALL: + printf("NODE_CALL(.):\n"); break; + case NODE_SCALL: + printf("NODE_SCALL(&.):\n"); break; + default: + break; + } mrb_parser_dump(mrb, tree->car, offset+1); dump_prefix(tree, offset+1); printf("method='%s' (%d)\n", -- cgit v1.2.3 From f6d199919d433adad03f2eb27757503bc61a5507 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 3 Dec 2016 16:38:43 +0900 Subject: Needed to apply block from safe-navigation operators; fix #3310 --- mrbgems/mruby-compiler/core/parse.y | 1 + 1 file changed, 1 insertion(+) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index dc09d33ff..e81d191d9 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -871,6 +871,7 @@ call_with_block(parser_state *p, node *a, node *b) break; case NODE_CALL: case NODE_FCALL: + case NODE_SCALL: n = a->cdr->cdr->cdr; if (!n->car) n->car = cons(0, b); else { -- 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(-) 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 a0fbc46ccd3e129532b05a9fe4f13f42a3c349b2 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 3 Dec 2016 18:47:04 +0900 Subject: Import locale insensitive strtod() from Ruby1.8; fix #3270 The function was renamed to `mrb_float_read(const char*, char**)`. --- include/mruby/value.h | 5 +- mrbgems/mruby-compiler/core/codegen.c | 4 +- mrbgems/mruby-compiler/core/parse.y | 2 +- src/string.c | 242 +++++++++++++++++++++++++++++++++- 4 files changed, 245 insertions(+), 8 deletions(-) diff --git a/include/mruby/value.h b/include/mruby/value.h index 61110e3dd..54d197f8f 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -62,12 +62,12 @@ struct mrb_state; # define MRB_PRIx PRIx32 #endif + +MRB_API double mrb_float_read(const char*, char**); #ifdef MRB_USE_FLOAT typedef float mrb_float; -# define str_to_mrb_float(buf) strtof(buf, NULL) #else typedef double mrb_float; -# define str_to_mrb_float(buf) strtod(buf, NULL) #endif #if defined _MSC_VER && _MSC_VER < 1900 @@ -85,7 +85,6 @@ MRB_API int mrb_msvc_snprintf(char *s, size_t n, const char *format, ...); # define isnan _isnan # define isinf(n) (!_finite(n) && !_isnan(n)) # define signbit(n) (_copysign(1.0, (n)) < 0.0) -# define strtof (float)strtod static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000; # define INFINITY (*(float *)&IEEE754_INFINITY_BITS_SINGLE) # define NAN ((float)(INFINITY - INFINITY)) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 414ca2627..b2cd12225 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2211,7 +2211,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_FLOAT: if (val) { char *p = (char*)tree; - mrb_float f = str_to_mrb_float(p); + mrb_float f = mrb_float_read(p, NULL); int off = new_lit(s, mrb_float_value(s->mrb, f)); genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); @@ -2227,7 +2227,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_FLOAT: { char *p = (char*)tree; - mrb_float f = str_to_mrb_float(p); + mrb_float f = mrb_float_read(p, NULL); int off = new_lit(s, mrb_float_value(s->mrb, -f)); genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index e81d191d9..19cb88e5b 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -4912,7 +4912,7 @@ parser_yylex(parser_state *p) char *endp; errno = 0; - d = strtod(tok(p), &endp); + d = mrb_float_read(tok(p), &endp); if (d == 0 && endp == tok(p)) { yywarning_s(p, "corrupted float value %s", tok(p)); } diff --git a/src/string.c b/src/string.c index f47294291..e3a268f78 100644 --- a/src/string.c +++ b/src/string.c @@ -2286,7 +2286,7 @@ mrb_cstr_to_dbl(mrb_state *mrb, const char * p, mrb_bool badcheck) if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { return 0.0; } - d = strtod(p, &end); + d = mrb_float_read(p, &end); if (p == end) { if (badcheck) { bad: @@ -2324,7 +2324,7 @@ bad: return 0.0; } - d = strtod(p, &end); + d = mrb_float_read(p, &end); if (badcheck) { if (!end || p == end) goto bad; while (*end && ISSPACE(*end)) end++; @@ -2749,3 +2749,241 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "freeze", mrb_str_freeze, MRB_ARGS_NONE()); } + +/* + * Source code for the "strtod" library procedure. + * + * Copyright (c) 1988-1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + * + * RCS: @(#) $Id: strtod.c 11708 2007-02-12 23:01:19Z shyouhei $ + */ + +#include +#include +extern int errno; + +#ifndef __STDC__ +# ifdef __GNUC__ +# define const __const__ +# else +# define const +# endif +#endif + +static const int maxExponent = 511; /* Largest possible base 10 exponent. Any + * exponent larger than this will already + * produce underflow or overflow, so there's + * no need to worry about additional digits. + */ +static const double powersOf10[] = {/* Table giving binary powers of 10. Entry */ + 10., /* is 10^2^i. Used to convert decimal */ + 100., /* exponents into floating-point numbers. */ + 1.0e4, + 1.0e8, + 1.0e16, + 1.0e32, + 1.0e64, + 1.0e128, + 1.0e256 +}; + +double +mrb_float_read(const char *string, char **endPtr) +/* const char *string; A decimal ASCII floating-point number, + * optionally preceded by white space. + * Must have form "-I.FE-X", where I is the + * integer part of the mantissa, F is the + * fractional part of the mantissa, and X + * is the exponent. Either of the signs + * may be "+", "-", or omitted. Either I + * or F may be omitted, or both. The decimal + * point isn't necessary unless F is present. + * The "E" may actually be an "e". E and X + * may both be omitted (but not just one). + */ +/* char **endPtr; If non-NULL, store terminating character's + * address here. */ +{ + int sign, expSign = FALSE; + double fraction, dblExp; + const double *d; + register const char *p; + register int c; + int exp = 0; /* Exponent read from "EX" field. */ + int fracExp = 0; /* Exponent that derives from the fractional + * part. Under normal circumstatnces, it is + * the negative of the number of digits in F. + * However, if I is very long, the last digits + * of I get dropped (otherwise a long I with a + * large negative exponent could cause an + * unnecessary overflow on I alone). In this + * case, fracExp is incremented one for each + * dropped digit. */ + int mantSize; /* Number of digits in mantissa. */ + int decPt; /* Number of mantissa digits BEFORE decimal + * point. */ + const char *pExp; /* Temporarily holds location of exponent + * in string. */ + + /* + * Strip off leading blanks and check for a sign. + */ + + p = string; + while (isspace(*p)) { + p += 1; + } + if (*p == '-') { + sign = TRUE; + p += 1; + } else { + if (*p == '+') { + p += 1; + } + sign = FALSE; + } + + /* + * Count the number of digits in the mantissa (including the decimal + * point), and also locate the decimal point. + */ + + decPt = -1; + for (mantSize = 0; ; mantSize += 1) + { + c = *p; + if (!isdigit(c)) { + if ((c != '.') || (decPt >= 0)) { + break; + } + decPt = mantSize; + } + p += 1; + } + + /* + * Now suck up the digits in the mantissa. Use two integers to + * collect 9 digits each (this is faster than using floating-point). + * If the mantissa has more than 18 digits, ignore the extras, since + * they can't affect the value anyway. + */ + + pExp = p; + p -= mantSize; + if (decPt < 0) { + decPt = mantSize; + } else { + mantSize -= 1; /* One of the digits was the point. */ + } + if (mantSize > 18) { + fracExp = decPt - 18; + mantSize = 18; + } else { + fracExp = decPt - mantSize; + } + if (mantSize == 0) { + fraction = 0.0; + p = string; + goto done; + } else { + int frac1, frac2; + frac1 = 0; + for ( ; mantSize > 9; mantSize -= 1) + { + c = *p; + p += 1; + if (c == '.') { + c = *p; + p += 1; + } + frac1 = 10*frac1 + (c - '0'); + } + frac2 = 0; + for (; mantSize > 0; mantSize -= 1) + { + c = *p; + p += 1; + if (c == '.') { + c = *p; + p += 1; + } + frac2 = 10*frac2 + (c - '0'); + } + fraction = (1.0e9 * frac1) + frac2; + } + + /* + * Skim off the exponent. + */ + + p = pExp; + if ((*p == 'E') || (*p == 'e')) { + p += 1; + if (*p == '-') { + expSign = TRUE; + p += 1; + } else { + if (*p == '+') { + p += 1; + } + expSign = FALSE; + } + while (isdigit(*p)) { + exp = exp * 10 + (*p - '0'); + p += 1; + } + } + if (expSign) { + exp = fracExp - exp; + } else { + exp = fracExp + exp; + } + + /* + * Generate a floating-point number that represents the exponent. + * Do this by processing the exponent one bit at a time to combine + * many powers of 2 of 10. Then combine the exponent with the + * fraction. + */ + + if (exp < 0) { + expSign = TRUE; + exp = -exp; + } else { + expSign = FALSE; + } + if (exp > maxExponent) { + exp = maxExponent; + errno = ERANGE; + } + dblExp = 1.0; + for (d = powersOf10; exp != 0; exp >>= 1, d += 1) { + if (exp & 01) { + dblExp *= *d; + } + } + if (expSign) { + fraction /= dblExp; + } else { + fraction *= dblExp; + } + +done: + if (endPtr != NULL) { + *endPtr = (char *) p; + } + + if (sign) { + return -fraction; + } + return fraction; +} -- cgit v1.2.3 From 5c651d6ce94449df8f096b624bc99fd4de3d698e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 3 Dec 2016 18:55:52 +0900 Subject: add MRB_API to mrb_float_read(); ref #3270 --- src/string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string.c b/src/string.c index e3a268f78..4f722b273 100644 --- a/src/string.c +++ b/src/string.c @@ -2796,7 +2796,7 @@ static const double powersOf10[] = {/* Table giving binary powers of 10. Entry 1.0e256 }; -double +MRB_API double mrb_float_read(const char *string, char **endPtr) /* const char *string; A decimal ASCII floating-point number, * optionally preceded by white space. -- cgit v1.2.3 From ac561a52f583ce154a27622642a37a7a386cbcd9 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 4 Dec 2016 10:41:01 +0900 Subject: Add symbol type check for Module#undef_method --- src/class.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class.c b/src/class.c index bac1d2984..e724dbb91 100644 --- a/src/class.c +++ b/src/class.c @@ -1817,7 +1817,7 @@ mrb_mod_undef(mrb_state *mrb, mrb_value mod) mrb_get_args(mrb, "*", &argv, &argc); while (argc--) { - undef_method(mrb, c, mrb_symbol(*argv)); + undef_method(mrb, c, to_sym(mrb, *argv)); argv++; } return mrb_nil_value(); -- cgit v1.2.3 From 43512cc7bdb4949a24e310aa03e67a95c59b5f1b Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 5 Dec 2016 02:55:39 +0900 Subject: Reorganize heredoc rules; fix #3273 The following codes used to be SyntaxError: (1) a = <<-EOD; hello EOD (2) <<-EOD.bla begin k EOD end --- mrbgems/mruby-compiler/core/parse.y | 41 +++++++++++++++---------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 19cb88e5b..05b948f8e 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -1918,7 +1918,7 @@ aref_args : none $$ = $1; NODE_LINENO($$, $1); } - | args ',' assocs trailer + | args comma assocs trailer { $$ = push($1, new_hash(p, $3)); } @@ -1958,7 +1958,7 @@ opt_call_args : none $$ = cons($1,0); NODE_LINENO($$, $1); } - | args ',' assocs ',' + | args comma assocs ',' { $$ = cons(push($1, new_hash(p, $3)), 0); NODE_LINENO($$, $1); @@ -1985,7 +1985,7 @@ call_args : command $$ = cons(list1(new_hash(p, $1)), $2); NODE_LINENO($$, $1); } - | args ',' assocs opt_block_arg + | args comma assocs opt_block_arg { $$ = cons(push($1, new_hash(p, $3)), $4); NODE_LINENO($$, $1); @@ -2014,7 +2014,7 @@ block_arg : tAMPER arg } ; -opt_block_arg : ',' block_arg +opt_block_arg : comma block_arg { $$ = $2; } @@ -2024,6 +2024,10 @@ opt_block_arg : ',' block_arg } ; +comma : ',' + | ',' heredoc_bodies + ; + args : arg { void_expr_error(p, $1); @@ -2036,34 +2040,24 @@ args : arg $$ = cons(new_splat(p, $2), 0); NODE_LINENO($$, $2); } - | args ',' arg + | args comma arg { void_expr_error(p, $3); $$ = push($1, $3); } - | args ',' tSTAR arg + | args comma tSTAR arg { void_expr_error(p, $4); $$ = push($1, new_splat(p, $4)); } - | args ',' heredoc_bodies arg - { - void_expr_error(p, $4); - $$ = push($1, $4); - } - | args ',' heredoc_bodies tSTAR arg - { - void_expr_error(p, $5); - $$ = push($1, new_splat(p, $5)); - } ; -mrhs : args ',' arg +mrhs : args comma arg { void_expr_error(p, $3); $$ = push($1, $3); } - | args ',' tSTAR arg + | args comma tSTAR arg { void_expr_error(p, $4); $$ = push($1, new_splat(p, $4)); @@ -2787,10 +2781,6 @@ regexp : tREGEXP_BEG tREGEXP heredoc : tHEREDOC_BEG ; -opt_heredoc_bodies : /* none */ - | heredoc_bodies - ; - heredoc_bodies : heredoc_body | heredoc_bodies heredoc_body ; @@ -3312,11 +3302,12 @@ rbracket : opt_nl ']' trailer : /* none */ | nl - | ',' + | comma ; term : ';' {yyerrok;} | nl + | heredoc_body ; nl : '\n' @@ -3324,10 +3315,10 @@ nl : '\n' p->lineno++; p->column = 0; } - opt_heredoc_bodies + ; terms : term - | terms ';' {yyerrok;} + | terms term ; none : /* none */ -- cgit v1.2.3 From 9a962ed2c3057be75cd77d31bfeca0ce50eb89d1 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 6 Dec 2016 10:25:07 +0900 Subject: Raise an exception in time_update_datetime(). The function used to return NULL on error, but not checked in the caller site. --- mrbgems/mruby-time/src/time.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index 089814890..9ac0d2002 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -183,7 +183,7 @@ static const struct mrb_data_type mrb_time_type = { "Time", mrb_free }; /** Updates the datetime of a mrb_time based on it's timezone and seconds setting. Returns self on success, NULL of failure. */ static struct mrb_time* -mrb_time_update_datetime(struct mrb_time *self) +time_update_datetime(mrb_state *mrb, struct mrb_time *self) { struct tm *aid; @@ -193,7 +193,11 @@ mrb_time_update_datetime(struct mrb_time *self) else { aid = localtime_r(&self->sec, &self->datetime); } - if (!aid) return NULL; + if (!aid) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_float_value(mrb, self->sec)); + /* not reached */ + return NULL; + } #ifdef NO_GMTIME_R self->datetime = *aid; /* copy data */ #endif @@ -238,7 +242,7 @@ time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone) tm->usec -= 1000000; } tm->timezone = timezone; - mrb_time_update_datetime(tm); + time_update_datetime(mrb, tm); return tm; } @@ -290,7 +294,7 @@ current_mrb_time(mrb_state *mrb) } #endif tm->timezone = MRB_TIMEZONE_LOCAL; - mrb_time_update_datetime(tm); + time_update_datetime(mrb, tm); return tm; } @@ -556,7 +560,7 @@ mrb_time_getutc(mrb_state *mrb, mrb_value self) tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm)); *tm2 = *tm; tm2->timezone = MRB_TIMEZONE_UTC; - mrb_time_update_datetime(tm2); + time_update_datetime(mrb, tm2); return mrb_time_wrap(mrb, mrb_obj_class(mrb, self), tm2); } @@ -571,7 +575,7 @@ mrb_time_getlocal(mrb_state *mrb, mrb_value self) tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm)); *tm2 = *tm; tm2->timezone = MRB_TIMEZONE_LOCAL; - mrb_time_update_datetime(tm2); + time_update_datetime(mrb, tm2); return mrb_time_wrap(mrb, mrb_obj_class(mrb, self), tm2); } @@ -649,7 +653,7 @@ mrb_time_localtime(mrb_state *mrb, mrb_value self) tm = time_get_ptr(mrb, self); tm->timezone = MRB_TIMEZONE_LOCAL; - mrb_time_update_datetime(tm); + time_update_datetime(mrb, tm); return self; } @@ -746,7 +750,7 @@ mrb_time_utc(mrb_state *mrb, mrb_value self) tm = time_get_ptr(mrb, self); tm->timezone = MRB_TIMEZONE_UTC; - mrb_time_update_datetime(tm); + time_update_datetime(mrb, tm); return self; } -- cgit v1.2.3 From 3623a833a4304fc15ec78dbae17f25af906b44f2 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 6 Dec 2016 11:23:23 +0900 Subject: Protect exceptions within main() function --- mrbgems/mruby-bin-mruby/tools/mruby/mruby.c | 105 +++++++++++++++------------- 1 file changed, 58 insertions(+), 47 deletions(-) diff --git a/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c b/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c index ab6c6688f..d10535140 100644 --- a/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c +++ b/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c @@ -6,6 +6,7 @@ #include #include #include +#include #ifdef MRB_DISABLE_STDIO static void @@ -176,6 +177,8 @@ main(int argc, char **argv) mrbc_context *c; mrb_value v; mrb_sym zero_sym; + struct mrb_jmpbuf c_jmp; + int ai; if (mrb == NULL) { fputs("Invalid mrb_state, exiting mruby\n", stderr); @@ -189,59 +192,67 @@ main(int argc, char **argv) return n; } - ARGV = mrb_ary_new_capa(mrb, args.argc); - for (i = 0; i < args.argc; i++) { - char* utf8 = mrb_utf8_from_locale(args.argv[i], -1); - if (utf8) { - mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8)); - mrb_utf8_free(utf8); + ai = mrb_gc_arena_save(mrb); + MRB_TRY(&c_jmp) { + mrb->jmp = &c_jmp; + ARGV = mrb_ary_new_capa(mrb, args.argc); + for (i = 0; i < args.argc; i++) { + char* utf8 = mrb_utf8_from_locale(args.argv[i], -1); + if (utf8) { + mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8)); + mrb_utf8_free(utf8); + } } - } - mrb_define_global_const(mrb, "ARGV", ARGV); - - c = mrbc_context_new(mrb); - if (args.verbose) - c->dump_result = TRUE; - if (args.check_syntax) - c->no_exec = TRUE; - - /* Set $0 */ - zero_sym = mrb_intern_lit(mrb, "$0"); - if (args.rfp) { - const char *cmdline; - cmdline = args.cmdline ? args.cmdline : "-"; - mrbc_filename(mrb, c, cmdline); - mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline)); - } - else { - mrbc_filename(mrb, c, "-e"); - mrb_gv_set(mrb, zero_sym, mrb_str_new_lit(mrb, "-e")); - } + mrb_define_global_const(mrb, "ARGV", ARGV); - /* Load program */ - if (args.mrbfile) { - v = mrb_load_irep_file_cxt(mrb, args.rfp, c); - } - else if (args.rfp) { - v = mrb_load_file_cxt(mrb, args.rfp, c); - } - else { - char* utf8 = mrb_utf8_from_locale(args.cmdline, -1); - if (!utf8) abort(); - v = mrb_load_string_cxt(mrb, utf8, c); - mrb_utf8_free(utf8); - } + c = mrbc_context_new(mrb); + if (args.verbose) + c->dump_result = TRUE; + if (args.check_syntax) + c->no_exec = TRUE; + + /* Set $0 */ + zero_sym = mrb_intern_lit(mrb, "$0"); + if (args.rfp) { + const char *cmdline; + cmdline = args.cmdline ? args.cmdline : "-"; + mrbc_filename(mrb, c, cmdline); + mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline)); + } + else { + mrbc_filename(mrb, c, "-e"); + mrb_gv_set(mrb, zero_sym, mrb_str_new_lit(mrb, "-e")); + } + + /* Load program */ + if (args.mrbfile) { + v = mrb_load_irep_file_cxt(mrb, args.rfp, c); + } + else if (args.rfp) { + v = mrb_load_file_cxt(mrb, args.rfp, c); + } + else { + char* utf8 = mrb_utf8_from_locale(args.cmdline, -1); + if (!utf8) abort(); + v = mrb_load_string_cxt(mrb, utf8, c); + mrb_utf8_free(utf8); + } - mrbc_context_free(mrb, c); - if (mrb->exc) { - if (!mrb_undef_p(v)) { - mrb_print_error(mrb); + mrb_gc_arena_restore(mrb, ai); + mrbc_context_free(mrb, c); + if (mrb->exc) { + if (!mrb_undef_p(v)) { + mrb_print_error(mrb); + } + n = -1; + } + else if (args.check_syntax) { + printf("Syntax OK\n"); } - n = -1; } - else if (args.check_syntax) { - printf("Syntax OK\n"); + MRB_CATCH(&c_jmp) { /* error */ } + MRB_END_EXC(&c_jmp); cleanup(mrb, &args); return n == 0 ? EXIT_SUCCESS : EXIT_FAILURE; -- cgit v1.2.3 From dffb4d82dc83054eade20679f069979d242d9745 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 6 Dec 2016 11:40:49 +0900 Subject: Add type check for cls before allocation --- src/gc.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/gc.c b/src/gc.c index 69708e40b..470fffc5f 100644 --- a/src/gc.c +++ b/src/gc.c @@ -480,7 +480,18 @@ mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) mrb_gc *gc = &mrb->gc; if (cls) { - enum mrb_vtype tt = MRB_INSTANCE_TT(cls); + enum mrb_vtype tt; + + switch (cls->tt) { + case MRB_TT_CLASS: + case MRB_TT_SCLASS: + case MRB_TT_MODULE: + case MRB_TT_ENV: + break; + default: + mrb_raise(mrb, E_TYPE_ERROR, "allocation failure"); + } + tt = MRB_INSTANCE_TT(cls); if (tt != MRB_TT_FALSE && ttype != MRB_TT_SCLASS && ttype != MRB_TT_ICLASS && -- cgit v1.2.3 From b491f4b06a586916965526597136bd3a255bc9ee Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Wed, 7 Dec 2016 15:31:32 +0900 Subject: set `MRB_64BIT` if the sizeof(size_t) is 8 --- include/mrbconf.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/mrbconf.h b/include/mrbconf.h index d47f46ae4..4796919c2 100644 --- a/include/mrbconf.h +++ b/include/mrbconf.h @@ -7,10 +7,13 @@ #ifndef MRUBYCONF_H #define MRUBYCONF_H +#include +#include + /* architecture selection: */ /* specify -DMRB_32BIT or -DMRB_64BIT to override */ #if !defined(MRB_32BIT) && !defined(MRB_64BIT) -#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) || defined(__aarch64__) +#if UINT64_MAX == SIZE_MAX #define MRB_64BIT #else #define MRB_32BIT -- cgit v1.2.3 From 6187c21bd96d120c4e58ebeae83749ab9f56a16c Mon Sep 17 00:00:00 2001 From: Felix Jones Date: Wed, 7 Dec 2016 12:46:47 +0000 Subject: Wrapped string.c errno with ifndef macro for platforms that use inbuilt errno macro --- src/string.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/string.c b/src/string.c index 4f722b273..4189d84d0 100644 --- a/src/string.c +++ b/src/string.c @@ -2750,7 +2750,7 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "freeze", mrb_str_freeze, MRB_ARGS_NONE()); } -/* +/* * Source code for the "strtod" library procedure. * * Copyright (c) 1988-1993 The Regents of the University of California. @@ -2769,7 +2769,9 @@ mrb_init_string(mrb_state *mrb) #include #include +#ifndef errno extern int errno; +#endif #ifndef __STDC__ # ifdef __GNUC__ @@ -2876,7 +2878,7 @@ mrb_float_read(const char *string, char **endPtr) * If the mantissa has more than 18 digits, ignore the extras, since * they can't affect the value anyway. */ - + pExp = p; p -= mantSize; if (decPt < 0) { @@ -2954,7 +2956,7 @@ mrb_float_read(const char *string, char **endPtr) * many powers of 2 of 10. Then combine the exponent with the * fraction. */ - + if (exp < 0) { expSign = TRUE; exp = -exp; -- 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(-) 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 fe86cf4c916b2ef89abd1ac7cd7eca63b7ae953e Mon Sep 17 00:00:00 2001 From: Felix Jones Date: Wed, 7 Dec 2016 14:17:09 +0000 Subject: Removed the errno declaration from string.c --- src/string.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/string.c b/src/string.c index 4189d84d0..a9351619b 100644 --- a/src/string.c +++ b/src/string.c @@ -2769,9 +2769,6 @@ mrb_init_string(mrb_state *mrb) #include #include -#ifndef errno -extern int errno; -#endif #ifndef __STDC__ # ifdef __GNUC__ -- cgit v1.2.3 From f7a891fa8979bdb82410e1adc98765013cc29a79 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Tue, 6 Dec 2016 10:30:08 -0500 Subject: Mark all the built-in classes during GC sweep Reported by https://hackerone.com/haquaman --- mrbgems/mruby-bin-mruby/bintest/mruby.rb | 14 ++++++++++++++ src/gc.c | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/mrbgems/mruby-bin-mruby/bintest/mruby.rb b/mrbgems/mruby-bin-mruby/bintest/mruby.rb index 01fc94632..ad8ec3a0f 100644 --- a/mrbgems/mruby-bin-mruby/bintest/mruby.rb +++ b/mrbgems/mruby-bin-mruby/bintest/mruby.rb @@ -44,3 +44,17 @@ EOS script.flush assert_equal "\"test\"\n\"fin\"\n", `#{cmd('mruby')} #{script.path}` end + +assert('garbage collecting built-in classes') do + script = Tempfile.new('test.rb') + + script.write <object_class); + + /* mark built-in classes */ + mrb_gc_mark(mrb, (struct RBasic*)mrb->class_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->module_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->proc_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->string_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->array_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->hash_class); + + mrb_gc_mark(mrb, (struct RBasic*)mrb->float_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->fixnum_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->true_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->false_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->nil_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->symbol_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->kernel_module); + + mrb_gc_mark(mrb, (struct RBasic*)mrb->eException_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->eStandardError_class); + /* mark top_self */ mrb_gc_mark(mrb, (struct RBasic*)mrb->top_self); /* mark exception */ -- 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(+) 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 0360a744b5fae6c29d91ba9729b7445415b9e293 Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Wed, 7 Dec 2016 21:12:59 +0100 Subject: Promote load_exec to mruby API as mrb_load_exec (fixes #3248) --- include/mruby/compile.h | 1 + mrbgems/mruby-compiler/core/parse.y | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/mruby/compile.h b/include/mruby/compile.h index 3ccaf9f6a..ebcb3f355 100644 --- a/include/mruby/compile.h +++ b/include/mruby/compile.h @@ -174,6 +174,7 @@ MRB_API struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*); MRB_API struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrbc_context*); MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,int,mrbc_context*); MRB_API struct RProc* mrb_generate_code(mrb_state*, struct mrb_parser_state*); +MRB_API mrb_value mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c); /* program load functions */ #ifndef MRB_DISABLE_STDIO diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 05b948f8e..957ad5815 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -5692,8 +5692,8 @@ mrb_parse_string(mrb_state *mrb, const char *s, mrbc_context *c) return mrb_parse_nstring(mrb, s, strlen(s), c); } -static mrb_value -load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c) +MRB_API mrb_value +mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c) { struct RClass *target = mrb->object_class; struct RProc *proc; @@ -5752,7 +5752,7 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c) MRB_API mrb_value mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c) { - return load_exec(mrb, mrb_parse_file(mrb, f, c), c); + return mrb_load_exec(mrb, mrb_parse_file(mrb, f, c), c); } MRB_API mrb_value @@ -5765,7 +5765,7 @@ mrb_load_file(mrb_state *mrb, FILE *f) MRB_API mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *c) { - return load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c); + return mrb_load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c); } MRB_API mrb_value -- cgit v1.2.3 From c2e749f878049204239ad63ac9546253aeb6ceeb Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 8 Dec 2016 10:22:14 +0900 Subject: fix issues of mrb_gc_unregister introduced in 09b1185 * fixes partial copy of objects in GC root array (due to missing `* sizeof(mrb_value)`) * restores the behavior that permitted an unregistered object to be used as an argument --- src/gc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/gc.c b/src/gc.c index 470fffc5f..f928cc49b 100644 --- a/src/gc.c +++ b/src/gc.c @@ -453,7 +453,7 @@ mrb_gc_unregister(mrb_state *mrb, mrb_value obj) mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME); mrb_value table = mrb_gv_get(mrb, root); struct RArray *a; - mrb_int i, len; + mrb_int i; if (mrb_nil_p(table)) return; if (mrb_type(table) != MRB_TT_ARRAY) { @@ -462,14 +462,13 @@ mrb_gc_unregister(mrb_state *mrb, mrb_value obj) } a = mrb_ary_ptr(table); mrb_ary_modify(mrb, a); - len = a->len-1; - for (i=0; ilen; i++) { if (mrb_obj_eq(mrb, a->ptr[i], obj)) { - memmove(&a->ptr[i], &a->ptr[i+1], len-i); + a->len--; + memmove(&a->ptr[i], &a->ptr[i + 1], (a->len - i) * sizeof(a->ptr[i])); break; } } - a->len--; } MRB_API struct RBasic* -- cgit v1.2.3 From eda6c1dc0550249b6e2d92c60aaa683d2b154eaf Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Thu, 8 Dec 2016 15:38:19 +0900 Subject: fix build on vs2013-vs2015 --- include/mruby/compile.h | 1 + src/numeric.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/include/mruby/compile.h b/include/mruby/compile.h index 3ccaf9f6a..459d88596 100644 --- a/include/mruby/compile.h +++ b/include/mruby/compile.h @@ -163,6 +163,7 @@ struct mrb_parser_state { MRB_API struct mrb_parser_state* mrb_parser_new(mrb_state*); MRB_API void mrb_parser_free(struct mrb_parser_state*); MRB_API void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*); +MRB_API double mrb_float_read(const char*, char**); MRB_API void mrb_parser_set_filename(struct mrb_parser_state*, char const*); MRB_API char const* mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx); diff --git a/src/numeric.c b/src/numeric.c index 25a411de8..a9a2a641b 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -357,7 +357,11 @@ flo_shift(mrb_state *mrb, mrb_value x, mrb_int width) while (width++) { val /= 2; } +#if defined(_ISOC99_SOURCE) val = trunc(val); +#else + val = val > 0 ? floor(val) : ceil(val); +#endif if (val == 0 && mrb_float(x) < 0) { return mrb_fixnum_value(-1); } -- cgit v1.2.3 From c27dbfedf4dbd95ef17c6ad2b84933088e56d2cd Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Thu, 8 Dec 2016 15:56:50 +0900 Subject: disable define const on VS --- src/string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string.c b/src/string.c index a9351619b..c921ca56d 100644 --- a/src/string.c +++ b/src/string.c @@ -2773,7 +2773,7 @@ mrb_init_string(mrb_state *mrb) #ifndef __STDC__ # ifdef __GNUC__ # define const __const__ -# else +# elif !defined(_MSC_VER) # define const # endif #endif -- cgit v1.2.3 From 2827655b9cf3099ef323cfb7967e5ddaa8ba28e1 Mon Sep 17 00:00:00 2001 From: Felix Jones Date: Thu, 8 Dec 2016 12:38:00 +0000 Subject: Removed unnecessary const macro - const keyword is already a dependency --- src/string.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/string.c b/src/string.c index c921ca56d..a4f8085ec 100644 --- a/src/string.c +++ b/src/string.c @@ -2770,14 +2770,6 @@ mrb_init_string(mrb_state *mrb) #include #include -#ifndef __STDC__ -# ifdef __GNUC__ -# define const __const__ -# elif !defined(_MSC_VER) -# define const -# endif -#endif - static const int maxExponent = 511; /* Largest possible base 10 exponent. Any * exponent larger than this will already * produce underflow or overflow, so there's -- 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(-) 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(-) 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 7b968ca893b5c24e07ba67e4e5100d93a4024418 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 10 Dec 2016 12:34:23 +0900 Subject: Clear parsing_heredoc at the end of file --- mrbgems/mruby-compiler/core/parse.y | 1 + 1 file changed, 1 insertion(+) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 957ad5815..ee3373fbf 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3946,6 +3946,7 @@ parse_string(parser_state *p) } } if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) { + if (c < 0) p->parsing_heredoc = NULL; return tHEREDOC_END; } } -- cgit v1.2.3 From 2ef634edb5ce70331a6a66d1c36726db904492bf Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 10 Dec 2016 15:11:07 +0900 Subject: do not destroy a page with an active TT_ENV (e.g. an env referred from TT_FIBER) --- src/gc.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/gc.c b/src/gc.c index f928cc49b..5525f0593 100644 --- a/src/gc.c +++ b/src/gc.c @@ -741,10 +741,12 @@ obj_free(mrb_state *mrb, struct RBasic *obj) { struct REnv *e = (struct REnv*)obj; - if (!MRB_ENV_STACK_SHARED_P(e)) { - mrb_free(mrb, e->stack); - e->stack = NULL; + if (MRB_ENV_STACK_SHARED_P(e)) { + /* cannot be freed */ + return; } + mrb_free(mrb, e->stack); + e->stack = NULL; } break; @@ -998,9 +1000,13 @@ incremental_sweep_phase(mrb_state *mrb, mrb_gc *gc, size_t limit) if (is_dead(gc, &p->as.basic)) { if (p->as.basic.tt != MRB_TT_FREE) { obj_free(mrb, &p->as.basic); - p->as.free.next = page->freelist; - page->freelist = (struct RBasic*)p; - freed++; + if (p->as.basic.tt == MRB_TT_FREE) { + p->as.free.next = page->freelist; + page->freelist = (struct RBasic*)p; + freed++; + } else { + dead_slot = 0; + } } } else { -- cgit v1.2.3 From 0af170fbec1bbf412b009117736d22e6f5c39b03 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 10 Dec 2016 15:34:32 +0900 Subject: gc.c: dead_slot is boolean; ref #3339 --- src/gc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/gc.c b/src/gc.c index 5525f0593..e8523af79 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1004,15 +1004,16 @@ incremental_sweep_phase(mrb_state *mrb, mrb_gc *gc, size_t limit) p->as.free.next = page->freelist; page->freelist = (struct RBasic*)p; freed++; - } else { - dead_slot = 0; + } + else { + dead_slot = FALSE; } } } else { if (!is_generational(gc)) paint_partial_white(gc, &p->as.basic); /* next gc target */ - dead_slot = 0; + dead_slot = FALSE; } p++; } -- 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(-) 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 237d26fd86871cfd1e3531af87b1bf7654887bc3 Mon Sep 17 00:00:00 2001 From: Kouhei Sutou Date: Sun, 11 Dec 2016 21:27:47 +0900 Subject: Support pkg-config in mrbgem.rake Example usage: MRuby::Gem::Specification.new('mruby-onig-regexp') do |spec| # ... if spec.search_package('onigmo') # Use onigmo.h when onigmo.pc exist. spec.cc.defines += ["HAVE_ONIGMO_H"] elsif spec.search_package('oniguruma') # Use oniguruma.h when oniguruma.pc exist. spec.cc.defines += ["HAVE_ONIGURUMA_H"] else # Use bundled Onigmo otherwise. # ... end end --- tasks/mrbgem_spec.rake | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tasks/mrbgem_spec.rake b/tasks/mrbgem_spec.rake index 78d912980..0aeeddaf1 100644 --- a/tasks/mrbgem_spec.rake +++ b/tasks/mrbgem_spec.rake @@ -1,6 +1,7 @@ require 'pathname' require 'forwardable' require 'tsort' +require 'shellwords' module MRuby module Gem @@ -126,6 +127,21 @@ module MRuby "#{build_dir}/gem_test.c" end + def search_package(name, version_query=nil) + package_query = name + package_query += " #{version_query}" if version_query + _pp "PKG-CONFIG", package_query + escaped_package_query = Shellwords.escape(package_query) + if system("pkg-config --exists #{escaped_package_query}") + cc.flags += [`pkg-config --cflags #{escaped_package_query}`.strip] + cxx.flags += [`pkg-config --cflags #{escaped_package_query}`.strip] + linker.flags += [`pkg-config --libs #{escaped_package_query}`.strip] + true + else + false + end + end + def funcname @funcname ||= @name.gsub('-', '_') end -- cgit v1.2.3 From 92c843dd07211d698a6dac90fbd740e483ae34af Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 12 Dec 2016 00:54:36 +0900 Subject: rename prefix RBASIC_ to MRB_; ref #3340 --- include/mruby/object.h | 6 +++--- src/array.c | 2 +- src/hash.c | 6 +++--- src/kernel.c | 2 +- src/string.c | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/mruby/object.h b/include/mruby/object.h index da44027e1..9347981d4 100644 --- a/include/mruby/object.h +++ b/include/mruby/object.h @@ -22,9 +22,9 @@ 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) +#define MRB_FROZEN_P(o) ((o)->flags & MRB_FLAG_IS_FROZEN) +#define MRB_SET_FROZEN_FLAG(o) ((o)->flags |= MRB_FLAG_IS_FROZEN) +#define MRB_UNSET_FROZEN_FLAG(o) ((o)->flags &= ~MRB_FLAG_IS_FROZEN) struct RObject { MRB_OBJECT_HEADER; diff --git a/src/array.c b/src/array.c index c6bac7b47..7601e9c17 100644 --- a/src/array.c +++ b/src/array.c @@ -108,7 +108,7 @@ 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)) { + if (MRB_FROZEN_P(a)) { mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen array"); } diff --git a/src/hash.c b/src/hash.c index d0e865b5c..c65c8926e 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) && !RBASIC_FROZEN_P(mrb_str_ptr(key))) { + if (mrb_string_p(key) && !MRB_FROZEN_P(mrb_str_ptr(key))) { key = mrb_str_dup(mrb, key); - RBASIC_SET_FROZEN_FLAG(mrb_str_ptr(key)); + MRB_SET_FROZEN_FLAG(mrb_str_ptr(key)); } return key; } @@ -278,7 +278,7 @@ 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))) { + if (MRB_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 78e57a17a..a5166deb2 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -455,7 +455,7 @@ mrb_obj_freeze(mrb_state *mrb, mrb_value self) { struct RBasic *b = mrb_basic_ptr(self); - RBASIC_SET_FROZEN_FLAG(b); + MRB_SET_FROZEN_FLAG(b); return self; } diff --git a/src/string.c b/src/string.c index 7234ecf2b..ee5aa04f3 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 (RBASIC_FROZEN_P(s)) { + if (MRB_FROZEN_P(s)) { mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen string"); } } @@ -2208,7 +2208,7 @@ mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr) char *p = RSTR_PTR(ps); if (!p || p[len] != '\0') { - if (RBASIC_FROZEN_P(ps)) { + if (MRB_FROZEN_P(ps)) { *ptr = str = mrb_str_dup(mrb, str); ps = mrb_str_ptr(str); } -- cgit v1.2.3 From 761562b65f33f47a18eae2c5db26ec48818498fc Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 12 Dec 2016 01:00:24 +0900 Subject: freeze instance variables; ref #3340 --- src/variable.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/variable.c b/src/variable.c index 45dc055af..390da5455 100644 --- a/src/variable.c +++ b/src/variable.c @@ -489,6 +489,9 @@ mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v) { iv_tbl *t = obj->iv; + if (MRB_FROZEN_P(obj)) { + mrb_raisef(mrb, E_RUNTIME_ERROR, "can't modify frozen %S", mrb_obj_value(obj)); + } if (!t) { t = obj->iv = iv_new(mrb); } -- cgit v1.2.3 From 1164463a7c21699cfee2e0fb610ae9931b830cc0 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 12 Dec 2016 01:05:07 +0900 Subject: freeze classes/modules; ref #3340 --- src/class.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/class.c b/src/class.c index e724dbb91..de68087cb 100644 --- a/src/class.c +++ b/src/class.c @@ -370,6 +370,12 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RPro MRB_CLASS_ORIGIN(c); h = c->mt; + if (MRB_FROZEN_P(c)) { + if (c->tt == MRB_TT_MODULE) + mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen module"); + else + mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen class"); + } if (!h) h = c->mt = kh_init(mt, mrb); k = kh_put(mt, mrb, h, mid); kh_value(h, k) = p; -- cgit v1.2.3 From 9cef2654025e6646b1d0ff259086fc9eb02fff84 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 12 Dec 2016 10:34:21 +0900 Subject: should not try to set classpath for frozen classes; ref #3340 --- src/class.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/class.c b/src/class.c index de68087cb..fed259b5b 100644 --- a/src/class.c +++ b/src/class.c @@ -1589,7 +1589,9 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) name = mrb_sym2name_len(mrb, sym, &len); path = mrb_str_new(mrb, name, len); } - mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path); + if (!MRB_FROZEN_P(c)) { + mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path); + } } return mrb_str_dup(mrb, path); } -- cgit v1.2.3 From a4ae22ae0cfe5efe420cb6b8c68c6ebadb9cead8 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 13 Dec 2016 01:55:08 +0900 Subject: Failed to realloc irep->syms in certain condition. Also msym size changed to 512 from 256. --- mrbgems/mruby-compiler/core/codegen.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 38da952b4..33d3f96d4 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -500,7 +500,12 @@ new_lit(codegen_scope *s, mrb_value val) return i; } -static inline int +/* method symbols should be fit in 9 bits */ +#define MAXMSYMLEN 512 +/* maximum symbol numbers */ +#define MAXSYMLEN 65536 + +static int new_msym(codegen_scope *s, mrb_sym sym) { size_t i, len; @@ -508,20 +513,20 @@ new_msym(codegen_scope *s, mrb_sym sym) mrb_assert(s->irep); len = s->irep->slen; - if (len > 256) len = 256; + if (len > MAXMSYMLEN) len = MAXMSYMLEN; for (i=0; iirep->syms[i] == sym) return i; if (s->irep->syms[i] == 0) break; } - if (i == 256) { - codegen_error(s, "too many symbols (max 256)"); + if (i == MAXMSYMLEN) { + codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXMSYMLEN) ")"); } s->irep->syms[i] = sym; if (i == s->irep->slen) s->irep->slen++; return i; } -static inline int +static int new_sym(codegen_scope *s, mrb_sym sym) { size_t i; @@ -529,13 +534,17 @@ new_sym(codegen_scope *s, mrb_sym sym) for (i=0; iirep->slen; i++) { if (s->irep->syms[i] == sym) return i; } - if (s->irep->slen > 125 && s->irep->slen < 256) { - s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*65536); - for (i = 0; i < 256 - s->irep->slen; i++) { + if (s->irep->slen == MAXSYMLEN) { + codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXSYMLEN) ")"); + } + if (s->scapa == MAXMSYMLEN) { + s->scapa = MAXSYMLEN; + s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*MAXSYMLEN); + for (i = s->irep->slen; i < MAXMSYMLEN; i++) { static const mrb_sym mrb_sym_zero = { 0 }; - s->irep->syms[i + s->irep->slen] = mrb_sym_zero; + s->irep->syms[i] = mrb_sym_zero; } - s->irep->slen = 256; + s->irep->slen = MAXMSYMLEN; } s->irep->syms[s->irep->slen] = sym; return s->irep->slen++; @@ -2760,7 +2769,7 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa); p->irep->plen = 0; - p->scapa = 256; + p->scapa = MAXMSYMLEN; p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa); p->irep->slen = 0; -- cgit v1.2.3 From 647ad29a7a1147e2c3ed93329cabbb974482697f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 13 Dec 2016 02:32:50 +0900 Subject: Fixed wrong condition in new_sym() that breaks symbol data. --- mrbgems/mruby-compiler/core/codegen.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 33d3f96d4..90bafb3c2 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -537,7 +537,8 @@ new_sym(codegen_scope *s, mrb_sym sym) if (s->irep->slen == MAXSYMLEN) { codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXSYMLEN) ")"); } - if (s->scapa == MAXMSYMLEN) { + + if (s->irep->slen > MAXMSYMLEN/2 && s->scapa == MAXMSYMLEN) { s->scapa = MAXSYMLEN; s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*MAXSYMLEN); for (i = s->irep->slen; i < MAXMSYMLEN; i++) { -- cgit v1.2.3 From 3a7c3695360e598ce4279a979cc9138a35971615 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 13 Dec 2016 10:48:36 +0900 Subject: Make sure str->capa is under MRB_INT_MAX; fix #3342 --- src/string.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/string.c b/src/string.c index ee5aa04f3..dfe4fa3b1 100644 --- a/src/string.c +++ b/src/string.c @@ -156,14 +156,14 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len) else capa = s->as.heap.aux.capa; - if (RSTR_LEN(s) >= MRB_INT_MAX - (mrb_int)len) { + total = RSTR_LEN(s)+len; + if (total >= MRB_INT_MAX) { mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big"); } - total = RSTR_LEN(s)+len; if (capa <= total) { while (total > capa) { if (capa + 1 >= MRB_INT_MAX / 2) { - capa = (total + 4095) / 4096; + capa = MRB_INT_MAX; break; } capa = (capa + 1) * 2; -- cgit v1.2.3 From 3bedd22d55fafef83f2ddf387cb595cf5ea60e63 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 13 Dec 2016 10:50:04 +0900 Subject: Add assertion to make sure new capacity does not overflow. --- src/string.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/string.c b/src/string.c index dfe4fa3b1..0049fdd5b 100644 --- a/src/string.c +++ b/src/string.c @@ -118,8 +118,8 @@ mrb_str_buf_new(mrb_state *mrb, size_t capa) return mrb_obj_value(s); } -static inline void -resize_capa(mrb_state *mrb, struct RString *s, mrb_int capacity) +static void +resize_capa(mrb_state *mrb, struct RString *s, size_t capacity) { if (RSTR_EMBED_P(s)) { if (RSTRING_EMBED_LEN_MAX < capacity) { @@ -133,6 +133,9 @@ resize_capa(mrb_state *mrb, struct RString *s, mrb_int capacity) } } else { +#if SIZE_MAX > MRB_INT_MAX + mrb_assert(capacity <= MRB_INT_MAX); +#endif s->as.heap.ptr = (char *)mrb_realloc(mrb, RSTR_PTR(s), capacity+1); s->as.heap.aux.capa = capacity; } -- cgit v1.2.3 From d196e4dd04d2b1879401f31788d4630d3c1c972a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 13 Dec 2016 11:18:05 +0900 Subject: void_expr_error(): n may be NULL. Reported from @clayton-shopify. --- mrbgems/mruby-compiler/core/parse.y | 1 + 1 file changed, 1 insertion(+) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index ee3373fbf..d70125a0b 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3430,6 +3430,7 @@ void_expr_error(parser_state *p, node *n) { int c; + if (n == NULL) return; c = (int)(intptr_t)n->car; switch (c) { case NODE_BREAK: -- cgit v1.2.3 From df350766025e97f55b86ee51f71509cfa6b1e005 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 13 Dec 2016 17:17:47 +0900 Subject: Restore callinfo offset in mrb_yield_with_class() --- src/vm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vm.c b/src/vm.c index 76f56298f..1ea23afc7 100644 --- a/src/vm.c +++ b/src/vm.c @@ -654,11 +654,13 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value if (MRB_PROC_CFUNC_P(p)) { val = p->body.func(mrb, self); mrb->c->stack = mrb->c->ci->stackent; - cipop(mrb); } else { + int cioff = mrb->c->ci - mrb->c->cibase; val = mrb_run(mrb, p, self); + mrb->c->ci = mrb->c->cibase + cioff; } + cipop(mrb); return val; } -- cgit v1.2.3 From fead715cef36abe7fe448b240636312acdd10775 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 13 Dec 2016 23:44:10 +0900 Subject: tLABEL should not come after conditional ternary; fix #3344 --- mrbgems/mruby-compiler/core/parse.y | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index d70125a0b..821411cf4 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3923,6 +3923,7 @@ parse_string(parser_state *p) int beg = (intptr_t)p->lex_strterm->cdr->cdr->car; int end = (intptr_t)p->lex_strterm->cdr->cdr->cdr; parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL; + int cmd_state = p->cmd_start; if (beg == 0) beg = -3; /* should never happen */ if (end == 0) end = -3; @@ -4127,10 +4128,13 @@ parse_string(parser_state *p) return tREGEXP; } yylval.nd = new_str(p, tok(p), toklen(p)); - if (IS_LABEL_SUFFIX(0)) { - p->lstate = EXPR_BEG; - nextc(p); - return tLABEL_END; + if (IS_LABEL_POSSIBLE()) { + if (IS_LABEL_SUFFIX(0)) { + fprintf(stderr, "tLABEL_END: %d->%d\n", p->lstate, EXPR_BEG); + p->lstate = EXPR_BEG; + nextc(p); + return tLABEL_END; + } } return tSTRING; -- cgit v1.2.3 From 73ad7395c066c4ffbf9c082be6bb45b2214e9286 Mon Sep 17 00:00:00 2001 From: Clayton Smith Date: Tue, 13 Dec 2016 10:04:15 -0500 Subject: Check type before calling mrb_range_ptr. --- src/range.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/range.c b/src/range.c index 417957420..73fe7589b 100644 --- a/src/range.c +++ b/src/range.c @@ -252,9 +252,10 @@ static mrb_bool range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc) { mrb_int beg, end; - struct RRange *r = mrb_range_ptr(mrb, range); + struct RRange *r; if (mrb_type(range) != MRB_TT_RANGE) return FALSE; + r = mrb_range_ptr(mrb, range); beg = mrb_int(mrb, r->edges->beg); end = mrb_int(mrb, r->edges->end); -- cgit v1.2.3 From 73cc08772f1a11140b238525698bce0664326a50 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 14 Dec 2016 13:34:24 +0900 Subject: remove debug code; ref #3344 --- mrbgems/mruby-compiler/core/parse.y | 1 - 1 file changed, 1 deletion(-) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 821411cf4..fac779b07 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -4130,7 +4130,6 @@ parse_string(parser_state *p) yylval.nd = new_str(p, tok(p), toklen(p)); if (IS_LABEL_POSSIBLE()) { if (IS_LABEL_SUFFIX(0)) { - fprintf(stderr, "tLABEL_END: %d->%d\n", p->lstate, EXPR_BEG); p->lstate = EXPR_BEG; nextc(p); return tLABEL_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(-) 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 b0886d5692dd58bed608fe8fb2be0c017c729060 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 17 Dec 2016 15:08:05 +0900 Subject: Zero length heredoc still crashed; ref Shopify/mruby-internal#81 --- mrbgems/mruby-compiler/core/parse.y | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index fac779b07..ec9b652d7 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3948,8 +3948,12 @@ parse_string(parser_state *p) } } if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) { - if (c < 0) p->parsing_heredoc = NULL; - return tHEREDOC_END; + if (c < 0) { + p->parsing_heredoc = NULL; + } + else { + return tHEREDOC_END; + } } } if (c < 0) { -- cgit v1.2.3 From c2bbfa5b61450426f286f5a5e45c7ea479edf90c Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 17 Dec 2016 15:29:28 +0900 Subject: NODE_NEGATE cdr may not be code-node; fix #3348 ref #3324 Reported by Denis Kasak https://hackerone.com/dkasak --- mrbgems/mruby-compiler/core/codegen.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 90bafb3c2..fc54a0647 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2231,13 +2231,9 @@ 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: - { + if (val) { char *p = (char*)tree; mrb_float f = mrb_float_read(p, NULL); int off = new_lit(s, mrb_float_value(s->mrb, -f)); @@ -2248,7 +2244,7 @@ codegen(codegen_scope *s, node *tree, int val) break; case NODE_INT: - { + if (val) { char *p = (char*)tree->car; int base = (intptr_t)tree->cdr->car; mrb_int i; @@ -2277,7 +2273,7 @@ codegen(codegen_scope *s, node *tree, int val) break; default: - { + if (val) { int sym = new_msym(s, mrb_intern_lit(s->mrb, "-")); genop(s, MKOP_ABx(OP_LOADI, cursp(), 0)); @@ -2286,6 +2282,9 @@ codegen(codegen_scope *s, node *tree, int val) pop(); pop(); genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2)); } + else { + codegen(s, tree, NOVAL); + } break; } } -- cgit v1.2.3 From 9781f7f0eace3b39355e65ad8ba0183be4ece417 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 17 Dec 2016 22:25:58 +0900 Subject: Add "not reached" mark in mrb_ary_concat() --- src/array.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/array.c b/src/array.c index 7601e9c17..056d72920 100644 --- a/src/array.c +++ b/src/array.c @@ -937,6 +937,7 @@ mrb_ary_splat(mrb_state *mrb, mrb_value v) recv_class, mrb_obj_value(mrb_obj_class(mrb, a)) ); + /* not reached */ return mrb_undef_value(); } } -- cgit v1.2.3 From 2edf15bed8026754ba09a770903bd7c50c9a81b8 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 17 Dec 2016 23:35:50 +0900 Subject: Prohibit mixture of posarg and nextarg; ref #3347 --- mrbgems/mruby-sprintf/src/sprintf.c | 69 +++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index 696d0939f..d4290ec59 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -136,29 +136,62 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base) blen += (l);\ } while (0) -#define GETARG() (!mrb_undef_p(nextvalue) ? nextvalue : \ - posarg == -1 ? \ - (mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%S) mixed with numbered", mrb_fixnum_value(nextarg)), mrb_undef_value()) : \ - posarg == -2 ? \ - (mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%S) mixed with named", mrb_fixnum_value(nextarg)), mrb_undef_value()) : \ +static void +check_next_arg(mrb_state *mrb, int posarg, int nextarg) +{ + switch (posarg) { + case -1: + mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%S) mixed with numbered", mrb_fixnum_value(nextarg)); + break; + case -2: + mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%S) mixed with named", mrb_fixnum_value(nextarg)); + break; + default: + break; + } +} + +static void +check_pos_arg(mrb_state *mrb, int posarg, int n) +{ + if (posarg > 0) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%S) after unnumbered(%S)", mrb_fixnum_value(n)); + } + if (posarg == -2) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%S) after named", mrb_fixnum_value(n)); + } + if (n < 1) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid index - %S$", mrb_fixnum_value(n)); + } +} + +static void +check_name_arg(mrb_state *mrb, int posarg, const char *name, int len) +{ + if (posarg > 0) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%S after unnumbered(%S)", + mrb_str_new(mrb, (name), (len)), mrb_fixnum_value(posarg)); + } + if (posarg == -1) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%S after numbered", mrb_str_new(mrb, (name), (len))); + } +} + +#define GETNEXTARG() (\ + check_next_arg(mrb, posarg, nextarg),\ (posarg = nextarg++, GETNTHARG(posarg))) -#define GETPOSARG(n) (posarg > 0 ? \ - (mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%S) after unnumbered(%S)", mrb_fixnum_value(n), mrb_fixnum_value(posarg)), mrb_undef_value()) : \ - posarg == -2 ? \ - (mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%S) after named", mrb_fixnum_value(n)), mrb_undef_value()) : \ - ((n < 1) ? \ - (mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid index - %S$", mrb_fixnum_value(n)), mrb_undef_value()) : \ - (posarg = -1, GETNTHARG(n)))) +#define GETARG() (!mrb_undef_p(nextvalue) ? nextvalue : GETNEXTARG()) + +#define GETPOSARG(n) (\ + check_pos_arg(mrb, posarg, n),\ + (posarg = -1, GETNTHARG(n))) #define GETNTHARG(nth) \ ((nth >= argc) ? (mrb_raise(mrb, E_ARGUMENT_ERROR, "too few arguments"), mrb_undef_value()) : argv[nth]) -#define GETNAMEARG(id, name, len) ( \ - posarg > 0 ? \ - (mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%S after unnumbered(%S)", mrb_str_new(mrb, (name), (len)), mrb_fixnum_value(posarg)), mrb_undef_value()) : \ - posarg == -1 ? \ - (mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%S after numbered", mrb_str_new(mrb, (name), (len))), mrb_undef_value()) : \ +#define GETNAMEARG(id, name, len) (\ + check_name_arg(mrb, posarg, name, len),\ (posarg = -2, mrb_hash_fetch(mrb, get_hash(mrb, &hash, argc, argv), id, mrb_undef_value()))) #define GETNUM(n, val) \ @@ -182,7 +215,7 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base) tmp_v = GETPOSARG(n); \ } \ else { \ - tmp_v = GETARG(); \ + tmp_v = GETNEXTARG(); \ p = t; \ } \ num = mrb_fixnum(tmp_v); \ -- cgit v1.2.3 From 432570723d027313f0d8dd5d3724fbc53f160e5c Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 17 Dec 2016 23:37:35 +0900 Subject: Check if width is zero or negative before fill; fix #3347 Reported by https://hackerone.com/haquaman. --- mrbgems/mruby-sprintf/src/sprintf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index d4290ec59..b5f9284d9 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -720,10 +720,10 @@ retry: CHECK(n); memcpy(buf+blen, c, n); blen += n; - FILL(' ', width-1); + if (width>0) FILL(' ', width-1); } else { - FILL(' ', width-1); + if (width>0) FILL(' ', width-1); CHECK(n); memcpy(buf+blen, c, n); blen += n; -- cgit v1.2.3 From 76eb7147a444c831503dd426ccec5e6ecd61ee22 Mon Sep 17 00:00:00 2001 From: Jun Takeda Date: Wed, 21 Dec 2016 00:51:18 +0900 Subject: Added example for cross-compiling for Renesas RX630 --- examples/targets/build_config_RX630.rb | 82 ++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 examples/targets/build_config_RX630.rb diff --git a/examples/targets/build_config_RX630.rb b/examples/targets/build_config_RX630.rb new file mode 100644 index 000000000..8e387c29d --- /dev/null +++ b/examples/targets/build_config_RX630.rb @@ -0,0 +1,82 @@ +MRuby::Build.new do |conf| + + # Gets set by the VS command prompts. + if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] + toolchain :visualcpp + else + toolchain :gcc + end + + enable_debug + + # include the default GEMs + conf.gembox 'default' + +end + +# Cross Compiling configuration for RX630 +# http://gadget.renesas.com/ +# +# Requires gnurx_v14.03 +MRuby::CrossBuild.new("RX630") do |conf| + toolchain :gcc + + # Linux + BIN_PATH = "/usr/share/gnurx_v14.03_elf-1/bin" + + conf.cc do |cc| + cc.command = "#{BIN_PATH}/rx-elf-gcc" + cc.flags = "-Wall -g -O2 -flto -mcpu=rx600 -m64bit-doubles" + cc.compile_options = "%{flags} -o %{outfile} -c %{infile}" + + #configuration for low memory environment + cc.defines << %w(MRB_USE_FLOAT) + cc.defines << %w(MRB_HEAP_PAGE_SIZE=64) + cc.defines << %w(MRB_USE_IV_SEGLIST) + cc.defines << %w(KHASH_DEFAULT_SIZE=8) + cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20) + cc.defines << %w(MRB_GC_STRESS) + cc.defines << %w(MRB_DISABLE_STDIO) #if you dont need stdio. + #cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval + end + + conf.cxx do |cxx| + cxx.command = conf.cc.command.dup + cxx.include_paths = conf.cc.include_paths.dup + cxx.flags = conf.cc.flags.dup + cxx.defines = conf.cc.defines.dup + cxx.compile_options = conf.cc.compile_options.dup + end + + conf.linker do |linker| + linker.command="#{BIN_PATH}/rx-elf-ld" + end + + conf.archiver do |archiver| + archiver.command = "#{BIN_PATH}/rx-elf-ar" + archiver.archive_options = 'rcs %{outfile} %{objs}' + end + + #no executables + conf.bins = [] + + #do not build executable test + conf.build_mrbtest_lib_only + + #disable C++ exception + conf.disable_cxx_exception + + #gems from core + conf.gem :core => "mruby-sprintf" + conf.gem :core => "mruby-print" + conf.gem :core => "mruby-math" + conf.gem :core => "mruby-enum-ext" + conf.gem :core => "mruby-numeric-ext" + + #light-weight regular expression + #conf.gem :github => "masamitsu-murase/mruby-hs-regexp", :branch => "master" + + #Arduino API + #conf.gem :github =>"kyab/mruby-arduino", :branch => "master" + +end -- 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(-) 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 5e3077c00da721ede78c07d2f2e261aded74e7b6 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 21 Dec 2016 16:44:17 +0900 Subject: One less argument for raisef(); fix #3355 This issue was reported by https://hackerone.com/mg36 --- mrbgems/mruby-sprintf/src/sprintf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index b5f9284d9..af0ca08ba 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -155,7 +155,8 @@ static void check_pos_arg(mrb_state *mrb, int posarg, int n) { if (posarg > 0) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%S) after unnumbered(%S)", mrb_fixnum_value(n)); + mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%S) after unnumbered(%S)", + mrb_fixnum_value(n), mrb_fixnum_value(posarg)); } if (posarg == -2) { mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%S) after named", mrb_fixnum_value(n)); -- 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(-) 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 0de65a88d44c108ec5035be2741bed486ad88de5 Mon Sep 17 00:00:00 2001 From: ksss Date: Fri, 23 Dec 2016 23:13:23 +0900 Subject: Do nothing when empty string Fix #3361 --- src/string.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/string.c b/src/string.c index ce27cdaa1..a177aafba 100644 --- a/src/string.c +++ b/src/string.c @@ -754,6 +754,9 @@ mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other) other = mrb_str_to_str(mrb, other); } s2 = mrb_str_ptr(other); + if (RSTR_LEN(s2) == 0) { + return; + } len = RSTR_LEN(s1) + RSTR_LEN(s2); if (RSTRING_CAPA(self) < len) { -- cgit v1.2.3 From c626b823cabf8ee7acbdf57e44597de3974c5f17 Mon Sep 17 00:00:00 2001 From: ksss Date: Fri, 23 Dec 2016 23:30:35 +0900 Subject: Check overflow string length Fix #3360 --- src/string.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/string.c b/src/string.c index ce27cdaa1..2d5006612 100644 --- a/src/string.c +++ b/src/string.c @@ -756,6 +756,9 @@ mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other) s2 = mrb_str_ptr(other); len = RSTR_LEN(s1) + RSTR_LEN(s2); + if (len < 0 || len >= MRB_INT_MAX) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big"); + } if (RSTRING_CAPA(self) < len) { resize_capa(mrb, s1, len); } -- 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(-) 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 caba1a19dc3f9e31612d8439cfa7fbf60d05bbb0 Mon Sep 17 00:00:00 2001 From: ksss Date: Tue, 27 Dec 2016 15:48:53 +0900 Subject: Check array max size Fix #3354 --- src/array.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/array.c b/src/array.c index 056d72920..2ce4e5dc6 100644 --- a/src/array.c +++ b/src/array.c @@ -619,6 +619,10 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val size = head + argc; if (tail < a->len) size += a->len - tail; + + if (size < 0 || size > ARY_MAX_SIZE) + mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); + if (size > a->aux.capa) ary_expand_capa(mrb, a, size); -- cgit v1.2.3 From 803bf010ca9a963abfab2ec348ae1c5c98f41bc2 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 25 Dec 2016 00:44:33 +0900 Subject: save/restore arena index around yield; ref #3359 --- mrbgems/mruby-string-ext/src/string.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index dfac907ec..d48028b4a 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -315,7 +315,7 @@ mrb_str_lines(mrb_state *mrb, mrb_value self) mrb_get_args(mrb, "&", &blk); result = mrb_ary_new(mrb); - + ai = mrb_gc_arena_save(mrb); if (!mrb_nil_p(blk)) { while (p < e) { t = p; @@ -324,6 +324,7 @@ mrb_str_lines(mrb_state *mrb, mrb_value self) len = (mrb_int) (p - t); arg = mrb_str_new(mrb, t, len); mrb_yield_argv(mrb, blk, 1, &arg); + mrb_gc_arena_restore(mrb, ai); if (b != RSTRING_PTR(self)) { ptrdiff_t diff = p - b; b = RSTRING_PTR(self); @@ -334,7 +335,6 @@ mrb_str_lines(mrb_state *mrb, mrb_value self) return self; } while (p < e) { - ai = mrb_gc_arena_save(mrb); t = p; while (p < e && *p != '\n') p++; if (*p == '\n') p++; -- cgit v1.2.3 From 270ea41b376d82b9685746ea363f64cbc84e79c9 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 30 Dec 2016 22:09:32 +0900 Subject: method_missing() may have CALL_MAXARGS-1 arguments; fix #3351 The issue was reported by https://hackerone.com/ston3 --- src/vm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vm.c b/src/vm.c index 1ea23afc7..cca0fd03b 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1143,6 +1143,9 @@ RETRY_TRY_BLOCK: else { value_move(regs+a+2, regs+a+1, ++n); regs[a+1] = sym; + if (n == CALL_MAXARGS) { + regs[a+1] = mrb_ary_new_from_values(mrb, n, regs+a+1); + } } } -- cgit v1.2.3 From 9d84f0d47b474711e8e8d944a1433154a4d85662 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 31 Dec 2016 23:09:56 +0900 Subject: ary_expand_capa(): size calculation by size_t; fix #3353 Also more size checks added. --- src/array.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/array.c b/src/array.c index 2ce4e5dc6..385f603ed 100644 --- a/src/array.c +++ b/src/array.c @@ -165,9 +165,9 @@ ary_make_shared(mrb_state *mrb, struct RArray *a) } static void -ary_expand_capa(mrb_state *mrb, struct RArray *a, mrb_int len) +ary_expand_capa(mrb_state *mrb, struct RArray *a, size_t len) { - mrb_int capa = a->aux.capa; + size_t capa = a->aux.capa; if (len > ARY_MAX_SIZE) { mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); @@ -177,14 +177,16 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, mrb_int len) capa = ARY_DEFAULT_LEN; } while (capa < len) { - if (capa <= ARY_MAX_SIZE / 2) { - capa *= 2; - } else { + capa *= 2; + if (capa > ARY_MAX_SIZE) { capa = ARY_MAX_SIZE; } } + if (capa < len || capa > MRB_INT_MAX) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); + } - if (capa > a->aux.capa) { + if (capa > (size_t)a->aux.capa) { mrb_value *expanded_ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa); a->aux.capa = capa; -- cgit v1.2.3 From cfdd1e3cc6ec9ac7ba81ec6fad5d5ba4d11334b9 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 31 Dec 2016 23:22:17 +0900 Subject: ary_expand_capa(): refine conditions to avoid infinite loop; ref #3353 --- src/array.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/array.c b/src/array.c index 385f603ed..54ff26721 100644 --- a/src/array.c +++ b/src/array.c @@ -170,6 +170,7 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, size_t len) size_t capa = a->aux.capa; if (len > ARY_MAX_SIZE) { + size_error: mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } @@ -177,13 +178,15 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, size_t len) capa = ARY_DEFAULT_LEN; } while (capa < len) { - capa *= 2; - if (capa > ARY_MAX_SIZE) { - capa = ARY_MAX_SIZE; + if (capa <= ARY_MAX_SIZE / 2) { + capa *= 2; + } + else { + goto size_error; } } if (capa < len || capa > MRB_INT_MAX) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); + goto size_error; } if (capa > (size_t)a->aux.capa) { -- cgit v1.2.3 From 342b1de65c5f044e1f3dc08b6e04c9cd0206abc3 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 31 Dec 2016 23:31:45 +0900 Subject: str_buf_cat(): should allocate at least RSTRING_EMBED_LEN_MAX+1. --- src/string.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/string.c b/src/string.c index 56eeef3a2..d41237f44 100644 --- a/src/string.c +++ b/src/string.c @@ -158,6 +158,8 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len) capa = RSTRING_EMBED_LEN_MAX; else capa = s->as.heap.aux.capa; + if (capa <= RSTRING_EMBED_LEN_MAX) + capa = RSTRING_EMBED_LEN_MAX+1; total = RSTR_LEN(s)+len; if (total >= MRB_INT_MAX) { -- cgit v1.2.3 From 1ed4de58d016a25d8a6ae4576e447dab1709535c Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 31 Dec 2016 23:33:34 +0900 Subject: str_buf_cat(): better size check added; ref #3342 --- src/string.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/string.c b/src/string.c index d41237f44..072bf2226 100644 --- a/src/string.c +++ b/src/string.c @@ -163,15 +163,20 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len) total = RSTR_LEN(s)+len; if (total >= MRB_INT_MAX) { + size_error: mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big"); } if (capa <= total) { while (total > capa) { - if (capa + 1 >= MRB_INT_MAX / 2) { - capa = MRB_INT_MAX; - break; + if (capa <= MRB_INT_MAX / 2) { + capa *= 2; + } + else { + goto size_error; } - capa = (capa + 1) * 2; + } + if (capa < total || capa > MRB_INT_MAX) { + goto size_error; } resize_capa(mrb, s, capa); } -- cgit v1.2.3 From 8b779796678b5cbd8e24a0d86f97701d20aa56c0 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 1 Jan 2017 00:45:14 +0900 Subject: Initialize potentially uninitialized variable z --- src/numeric.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/numeric.c b/src/numeric.c index a9a2a641b..0306b1363 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -1044,7 +1044,7 @@ fix_to_f(mrb_state *mrb, mrb_value num) MRB_API mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x) { - mrb_int z; + mrb_int z = 0; if (!mrb_float_p(x)) { mrb_raise(mrb, E_TYPE_ERROR, "non float value"); -- cgit v1.2.3 From 07167b8f5eb7e0ff7b4048ffcfefe9a38c904a75 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 1 Jan 2017 00:47:45 +0900 Subject: Initialize potentially uninitialized variable tsec. --- mrbgems/mruby-time/src/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index 9ac0d2002..cf0926849 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -217,7 +217,7 @@ static struct mrb_time* time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone) { struct mrb_time *tm; - time_t tsec; + time_t tsec = 0; if (sizeof(time_t) == 4 && (sec > (double)INT32_MAX || (double)INT32_MIN > sec)) { goto out_of_range; -- cgit v1.2.3 From 30b6648b9c53f8c3f5156910758cb37eb0d654a7 Mon Sep 17 00:00:00 2001 From: ksss Date: Mon, 2 Jan 2017 16:33:58 +0900 Subject: Small refactoring: should use RSTR_CAPA --- src/string.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/string.c b/src/string.c index 072bf2226..b57f1cec4 100644 --- a/src/string.c +++ b/src/string.c @@ -154,10 +154,7 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len) off = ptr - RSTR_PTR(s); } - if (RSTR_EMBED_P(s)) - capa = RSTRING_EMBED_LEN_MAX; - else - capa = s->as.heap.aux.capa; + capa = RSTR_CAPA(s); if (capa <= RSTRING_EMBED_LEN_MAX) capa = RSTRING_EMBED_LEN_MAX+1; -- cgit v1.2.3 From 8a9a24152a23595fba0802f555d49e0c263836af Mon Sep 17 00:00:00 2001 From: ksss Date: Mon, 2 Jan 2017 16:54:34 +0900 Subject: Fix memory error on str_buf_cat Modify from nofree to embed string --- src/string.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/string.c b/src/string.c index b57f1cec4..ae2e5ccc8 100644 --- a/src/string.c +++ b/src/string.c @@ -695,14 +695,21 @@ mrb_str_modify(mrb_state *mrb, struct RString *s) } if (RSTR_NOFREE_P(s)) { char *p = s->as.heap.ptr; + mrb_int len = s->as.heap.len; - s->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)s->as.heap.len+1); + RSTR_UNSET_NOFREE_FLAG(s); + if (len < RSTRING_EMBED_LEN_MAX) { + RSTR_SET_EMBED_FLAG(s); + RSTR_SET_EMBED_LEN(s, len); + } + else { + s->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)len+1); + s->as.heap.aux.capa = len; + } if (p) { - memcpy(RSTR_PTR(s), p, s->as.heap.len); + memcpy(RSTR_PTR(s), p, len); } - RSTR_PTR(s)[s->as.heap.len] = '\0'; - s->as.heap.aux.capa = s->as.heap.len; - RSTR_UNSET_NOFREE_FLAG(s); + RSTR_PTR(s)[len] = '\0'; return; } } -- cgit v1.2.3 From f388b6d612158f4b08cd1bedb92dec8c50e5576d Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 1 Jan 2017 01:15:38 +0900 Subject: use size_t instead of int --- src/vm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vm.c b/src/vm.c index cca0fd03b..3023710d4 100644 --- a/src/vm.c +++ b/src/vm.c @@ -134,8 +134,8 @@ static void stack_extend_alloc(mrb_state *mrb, int room, int keep) { mrb_value *oldbase = mrb->c->stbase; - int size = mrb->c->stend - mrb->c->stbase; - int off = mrb->c->stack - mrb->c->stbase; + size_t size = mrb->c->stend - mrb->c->stbase; + size_t off = mrb->c->stack - mrb->c->stbase; #ifdef MRB_STACK_EXTEND_DOUBLING if (room <= size) -- cgit v1.2.3 From bc1259de3b3e1b2ba690ec5a122e95fb9a7c0d5a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 1 Jan 2017 01:19:12 +0900 Subject: add explicit casts --- mrbgems/mruby-range-ext/src/range.c | 2 +- mrbgems/mruby-time/src/time.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mrbgems/mruby-range-ext/src/range.c b/mrbgems/mruby-range-ext/src/range.c index 8aa1379b0..3131192ff 100644 --- a/mrbgems/mruby-range-ext/src/range.c +++ b/mrbgems/mruby-range-ext/src/range.c @@ -156,7 +156,7 @@ mrb_range_size(mrb_state *mrb, mrb_value range) } if (isinf(n+1)) return mrb_float_value(mrb, INFINITY); - return mrb_fixnum_value(n+1); + return mrb_fixnum_value((mrb_int)n+1); } return mrb_nil_value(); } diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index cf0926849..8cadfbcff 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -194,7 +194,7 @@ time_update_datetime(mrb_state *mrb, struct mrb_time *self) aid = localtime_r(&self->sec, &self->datetime); } if (!aid) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_float_value(mrb, self->sec)); + mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_float_value(mrb, (mrb_float)self->sec)); /* not reached */ return NULL; } -- cgit v1.2.3 From eeca6ec8f511933e9a403e6b6166b874eead25b1 Mon Sep 17 00:00:00 2001 From: ksss Date: Wed, 4 Jan 2017 14:00:28 +0900 Subject: Rewrite String#prepend with Ruby Fix #3357 --- mrbgems/mruby-string-ext/mrblib/string.rb | 14 +++++++++++ mrbgems/mruby-string-ext/src/string.c | 39 ------------------------------- 2 files changed, 14 insertions(+), 39 deletions(-) diff --git a/mrbgems/mruby-string-ext/mrblib/string.rb b/mrbgems/mruby-string-ext/mrblib/string.rb index e6fbe7ddc..6e5f3c73d 100644 --- a/mrbgems/mruby-string-ext/mrblib/string.rb +++ b/mrbgems/mruby-string-ext/mrblib/string.rb @@ -385,4 +385,18 @@ class String end end alias each_codepoint codepoints + + ## + # call-seq: + # str.prepend(other_str) -> str + # + # Prepend---Prepend the given string to str. + # + # a = "world" + # a.prepend("hello ") #=> "hello world" + # a #=> "hello world" + def prepend(arg) + self[0, 0] = arg + self + end end diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index d48028b4a..c6a9e1d0b 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -437,44 +437,6 @@ mrb_str_succ(mrb_state *mrb, mrb_value self) return str; } -/* - * call-seq: - * str.prepend(other_str) -> str - * - * Prepend---Prepend the given string to str. - * - * a = "world" - * a.prepend("hello ") #=> "hello world" - * a #=> "hello world" - */ -static mrb_value -mrb_str_prepend(mrb_state *mrb, mrb_value self) -{ - struct RString *s1 = mrb_str_ptr(self), *s2, *temp_s; - mrb_int len; - mrb_value other, temp_str; - - mrb_get_args(mrb, "S", &other); - - mrb_str_modify(mrb, s1); - if (!mrb_string_p(other)) { - other = mrb_str_to_str(mrb, other); - } - s2 = mrb_str_ptr(other); - len = RSTR_LEN(s1) + RSTR_LEN(s2); - temp_str = mrb_str_new(mrb, NULL, RSTR_LEN(s1)); - temp_s = mrb_str_ptr(temp_str); - memcpy(RSTR_PTR(temp_s), RSTR_PTR(s1), RSTR_LEN(s1)); - if (RSTRING_CAPA(self) < len) { - mrb_str_resize(mrb, self, len); - } - memcpy(RSTR_PTR(s1), RSTR_PTR(s2), RSTR_LEN(s2)); - memcpy(RSTR_PTR(s1) + RSTR_LEN(s2), RSTR_PTR(temp_s), RSTR_LEN(temp_s)); - RSTR_SET_LEN(s1, len); - RSTR_PTR(s1)[len] = '\0'; - return self; -} - #ifdef MRB_UTF8_STRING static const char utf8len_codepage_zero[256] = { @@ -562,7 +524,6 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb) mrb_define_method(mrb, s, "lines", mrb_str_lines, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "succ", mrb_str_succ, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "succ!", mrb_str_succ_bang, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "prepend", mrb_str_prepend, MRB_ARGS_REQ(1)); mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next"), mrb_intern_lit(mrb, "succ")); mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next!"), mrb_intern_lit(mrb, "succ!")); mrb_define_method(mrb, s, "ord", mrb_str_ord, MRB_ARGS_NONE()); -- cgit v1.2.3 From 2e0c2b58076ce24508a584091f8af9bf8c22f64d Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 5 Jan 2017 16:46:08 +0900 Subject: Add mrb_hash_modify() to Hash#{delete,clear}; ref #3370 This issue was reported by https://hackerone.com/an0n-j --- src/hash.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hash.c b/src/hash.c index c65c8926e..98feaceac 100644 --- a/src/hash.c +++ b/src/hash.c @@ -554,6 +554,7 @@ mrb_hash_delete(mrb_state *mrb, mrb_value self) mrb_value key; mrb_get_args(mrb, "o", &key); + mrb_hash_modify(mrb, self); return mrb_hash_delete_key(mrb, self, key); } @@ -620,6 +621,7 @@ mrb_hash_clear(mrb_state *mrb, mrb_value hash) { khash_t(ht) *h = RHASH_TBL(hash); + mrb_hash_modify(mrb, hash); if (h) kh_clear(ht, mrb, h); return hash; } -- cgit v1.2.3 From 36f5b44578791a12619c189808dbc3cb4758e32a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 5 Jan 2017 17:49:21 +0900 Subject: Add new method Kernel#frozen?; ref #3370 --- src/kernel.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/kernel.c b/src/kernel.c index 5e44d73b4..677c0d519 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -473,6 +473,29 @@ mrb_obj_freeze(mrb_state *mrb, mrb_value self) return self; } +static mrb_value +mrb_obj_frozen(mrb_state *mrb, mrb_value 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 mrb_true_value(); + default: + break; + } + + b = mrb_basic_ptr(self); + if (!MRB_FROZEN_P(b)) { + return mrb_false_value(); + } + return mrb_true_value(); +} + /* 15.3.1.3.15 */ /* * call-seq: @@ -1148,6 +1171,7 @@ mrb_init_kernel(mrb_state *mrb) 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, "frozen?", mrb_obj_frozen, 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 */ -- cgit v1.2.3 From fe0884f37f0ff454ae9d87b76a24b63d206d2419 Mon Sep 17 00:00:00 2001 From: Jun Takeda Date: Thu, 5 Jan 2017 22:42:25 +0900 Subject: Removed ununnecessary escape character '\' for MRUBY_XXX in libmruby.flags.mak --- tasks/libmruby.rake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasks/libmruby.rake b/tasks/libmruby.rake index 095bedd52..23663d0a5 100644 --- a/tasks/libmruby.rake +++ b/tasks/libmruby.rake @@ -5,17 +5,17 @@ MRuby.each_target do file "#{build_dir}/lib/libmruby.flags.mak" => [__FILE__, libfile("#{build_dir}/lib/libmruby")] do |t| open(t.name, 'w') do |f| - f.puts "MRUBY_CFLAGS = #{cc.all_flags.gsub('"', '\\"')}" + f.puts "MRUBY_CFLAGS = #{cc.all_flags}" gem_flags = gems.map { |g| g.linker.flags } gem_library_paths = gems.map { |g| g.linker.library_paths } - f.puts "MRUBY_LDFLAGS = #{linker.all_flags(gem_library_paths, gem_flags).gsub('"', '\\"')} #{linker.option_library_path % "#{build_dir}/lib"}" + f.puts "MRUBY_LDFLAGS = #{linker.all_flags(gem_library_paths, gem_flags)} #{linker.option_library_path % "#{build_dir}/lib"}" gem_flags_before_libraries = gems.map { |g| g.linker.flags_before_libraries } - f.puts "MRUBY_LDFLAGS_BEFORE_LIBS = #{[linker.flags_before_libraries, gem_flags_before_libraries].flatten.join(' ').gsub('"', '\\"')}" + f.puts "MRUBY_LDFLAGS_BEFORE_LIBS = #{[linker.flags_before_libraries, gem_flags_before_libraries].flatten.join(' ')}" gem_libraries = gems.map { |g| g.linker.libraries } - f.puts "MRUBY_LIBS = #{linker.option_library % 'mruby'} #{linker.library_flags(gem_libraries).gsub('"', '\\"')}" + f.puts "MRUBY_LIBS = #{linker.option_library % 'mruby'} #{linker.library_flags(gem_libraries)}" end end task :all => "#{build_dir}/lib/libmruby.flags.mak" -- cgit v1.2.3 From f53f73f30ca390d27994e9092ff9b6b18aa615bf Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 6 Jan 2017 14:25:01 +0900 Subject: Should not deallocate shared string referring static; fix #3373 --- src/string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string.c b/src/string.c index ae2e5ccc8..d011f60ca 100644 --- a/src/string.c +++ b/src/string.c @@ -669,7 +669,7 @@ mrb_str_modify(mrb_state *mrb, struct RString *s) if (RSTR_SHARED_P(s)) { mrb_shared_string *shared = s->as.heap.aux.shared; - if (shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) { + if (shared->nofree == 0 && shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) { s->as.heap.ptr = shared->ptr; s->as.heap.aux.capa = shared->len; RSTR_PTR(s)[s->as.heap.len] = '\0'; -- cgit v1.2.3 From 9a76a0bd809e06089e6a09aa72e01ccf82806056 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 6 Jan 2017 14:51:21 +0900 Subject: Move mrb_assert() position. --- src/string.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/string.c b/src/string.c index d011f60ca..5aaef5826 100644 --- a/src/string.c +++ b/src/string.c @@ -121,6 +121,9 @@ mrb_str_buf_new(mrb_state *mrb, size_t capa) static void resize_capa(mrb_state *mrb, struct RString *s, size_t capacity) { +#if SIZE_MAX > MRB_INT_MAX + mrb_assert(capacity < MRB_INT_MAX); +#endif if (RSTR_EMBED_P(s)) { if (RSTRING_EMBED_LEN_MAX < capacity) { char *const tmp = (char *)mrb_malloc(mrb, capacity+1); @@ -133,9 +136,6 @@ resize_capa(mrb_state *mrb, struct RString *s, size_t capacity) } } else { -#if SIZE_MAX > MRB_INT_MAX - mrb_assert(capacity <= MRB_INT_MAX); -#endif s->as.heap.ptr = (char *)mrb_realloc(mrb, RSTR_PTR(s), capacity+1); s->as.heap.aux.capa = capacity; } -- cgit v1.2.3 From c6a11725923090278bb4941579751650d9aaebce Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 6 Jan 2017 14:52:04 +0900 Subject: Add pointer cast to pacify warnings. --- src/string.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/string.c b/src/string.c index 5aaef5826..976c34687 100644 --- a/src/string.c +++ b/src/string.c @@ -132,12 +132,12 @@ resize_capa(mrb_state *mrb, struct RString *s, size_t capacity) RSTR_UNSET_EMBED_FLAG(s); s->as.heap.ptr = tmp; s->as.heap.len = len; - s->as.heap.aux.capa = capacity; + s->as.heap.aux.capa = (mrb_int)capacity; } } else { - s->as.heap.ptr = (char *)mrb_realloc(mrb, RSTR_PTR(s), capacity+1); - s->as.heap.aux.capa = capacity; + s->as.heap.ptr = (char*)mrb_realloc(mrb, RSTR_PTR(s), capacity+1); + s->as.heap.aux.capa = (mrb_int)capacity; } } -- cgit v1.2.3 From 885d929398cf6962f3b0d292cf44105976f6c848 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 6 Jan 2017 14:53:00 +0900 Subject: Improve capacity enhancing conditions --- src/array.c | 4 ++-- src/string.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/array.c b/src/array.c index 54ff26721..420907866 100644 --- a/src/array.c +++ b/src/array.c @@ -182,10 +182,10 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, size_t len) capa *= 2; } else { - goto size_error; + capa = len; } } - if (capa < len || capa > MRB_INT_MAX) { + if (capa < len || capa > ARY_MAX_SIZE) { goto size_error; } diff --git a/src/string.c b/src/string.c index 976c34687..b4746545a 100644 --- a/src/string.c +++ b/src/string.c @@ -169,7 +169,7 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len) capa *= 2; } else { - goto size_error; + capa = total; } } if (capa < total || capa > MRB_INT_MAX) { -- cgit v1.2.3 From 2c77dfab0499863a71d4bebef665947c603fe4fa Mon Sep 17 00:00:00 2001 From: Daniel Bovensiepen Date: Fri, 6 Jan 2017 14:27:57 +0800 Subject: Update Copyright to 2017 Signed-off-by: Daniel Bovensiepen --- MITL | 2 +- include/mruby.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MITL b/MITL index 38fdbe231..d02b8fe1c 100644 --- a/MITL +++ b/MITL @@ -1,4 +1,4 @@ -Copyright (c) 2016 mruby developers +Copyright (c) 2017 mruby developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/include/mruby.h b/include/mruby.h index 6e222057f..76a028ad4 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -1,7 +1,7 @@ /* ** mruby - An embeddable Ruby implementation ** -** Copyright (c) mruby developers 2010-2016 +** Copyright (c) mruby developers 2010-2017 ** ** Permission is hereby granted, free of charge, to any person obtaining ** a copy of this software and associated documentation files (the -- cgit v1.2.3 From ddcb30d84bfad619184a504b76e153bed0b875b9 Mon Sep 17 00:00:00 2001 From: ksss Date: Fri, 6 Jan 2017 16:27:19 +0900 Subject: Check intern object returned by mrb_check_string_type --- src/kernel.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/kernel.c b/src/kernel.c index 5e44d73b4..0791bbd92 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -965,14 +965,17 @@ obj_respond_to(mrb_state *mrb, mrb_value self) } else { mrb_value tmp; - if (!mrb_string_p(mid)) { + if (mrb_string_p(mid)) { + tmp = mrb_check_intern_str(mrb, mid); + } + else { tmp = mrb_check_string_type(mrb, mid); if (mrb_nil_p(tmp)) { tmp = mrb_inspect(mrb, mid); mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", tmp); } + tmp = mrb_check_intern_str(mrb, tmp); } - tmp = mrb_check_intern_str(mrb, mid); if (mrb_nil_p(tmp)) { respond_to_p = FALSE; } -- cgit v1.2.3 From 392d7fbef9aa64134b33ac562f125df45b450ec0 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 7 Jan 2017 12:24:56 +0900 Subject: Add ary_modify() checks; close #3379 This issue was reported by https://hackerone.com/an0n-j --- src/array.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/array.c b/src/array.c index 420907866..99f9fc8b2 100644 --- a/src/array.c +++ b/src/array.c @@ -440,6 +440,7 @@ mrb_ary_pop(mrb_state *mrb, mrb_value ary) { struct RArray *a = mrb_ary_ptr(ary); + ary_modify(mrb, a); if (a->len == 0) return mrb_nil_value(); return a->ptr[--a->len]; } @@ -452,6 +453,7 @@ mrb_ary_shift(mrb_state *mrb, mrb_value self) struct RArray *a = mrb_ary_ptr(self); mrb_value val; + ary_modify(mrb, a); if (a->len == 0) return mrb_nil_value(); if (ARY_SHARED_P(a)) { L_SHIFT: @@ -964,6 +966,7 @@ mrb_ary_clear(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); + ary_modify(mrb, a); if (ARY_SHARED_P(a)) { mrb_ary_decref(mrb, a->aux.shared); ARY_UNSET_SHARED_FLAG(a); -- 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(-) 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 ee7fc56dd0d7bd2aa8be8a24290ae1de32b0dcec Mon Sep 17 00:00:00 2001 From: Sorah Fukumori Date: Mon, 9 Jan 2017 10:08:06 +0900 Subject: Put package's libs flag after %{objs} In case LDFLAG contains "-Wl,--as-needed" or "--as-needed" is enabled by default, "-l" flags should appear after objs specifiction. --- tasks/mrbgem_spec.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/mrbgem_spec.rake b/tasks/mrbgem_spec.rake index 0aeeddaf1..3053c3d49 100644 --- a/tasks/mrbgem_spec.rake +++ b/tasks/mrbgem_spec.rake @@ -135,7 +135,7 @@ module MRuby if system("pkg-config --exists #{escaped_package_query}") cc.flags += [`pkg-config --cflags #{escaped_package_query}`.strip] cxx.flags += [`pkg-config --cflags #{escaped_package_query}`.strip] - linker.flags += [`pkg-config --libs #{escaped_package_query}`.strip] + linker.flags_before_libraries += [`pkg-config --libs #{escaped_package_query}`.strip] true else false -- cgit v1.2.3 From c4491e477b40adc842ef76e524647607780c8f25 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 9 Jan 2017 10:42:11 +0900 Subject: Validate tm values before timegm(); close #3368 This issue was reported by https://hackerone.com/volc --- mrbgems/mruby-time/src/time.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index 8cadfbcff..43d87e5ff 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -332,6 +332,15 @@ time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday, nowtime.tm_min = (int)amin; nowtime.tm_sec = (int)asec; nowtime.tm_isdst = -1; + + if (nowtime.tm_mon < 0 || nowtime.tm_mon > 11 + || nowtime.tm_mday < 1 || nowtime.tm_mday > 31 + || nowtime.tm_hour < 0 || nowtime.tm_hour > 24 + || (nowtime.tm_hour == 24 && (nowtime.tm_min > 0 || nowtime.tm_sec > 0)) + || nowtime.tm_min < 0 || nowtime.tm_min > 59 + || nowtime.tm_sec < 0 || nowtime.tm_sec > 60) + mrb_raise(mrb, E_RUNTIME_ERROR, "argument out of range"); + if (timezone == MRB_TIMEZONE_UTC) { nowsecs = timegm(&nowtime); } -- cgit v1.2.3 From 7523cdf3404230213cb858f38bd91135d478a7f3 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 11 Jan 2017 09:51:52 +0900 Subject: Exception#initialize to take arbitrary number of args; ref #3384 --- src/error.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/error.c b/src/error.c index b24aed798..fda2cd15c 100644 --- a/src/error.c +++ b/src/error.c @@ -44,8 +44,10 @@ static mrb_value exc_initialize(mrb_state *mrb, mrb_value exc) { mrb_value mesg; + int argc; + mrb_value *argv; - if (mrb_get_args(mrb, "|o", &mesg) == 1) { + if (mrb_get_args(mrb, "|o*", &mesg, &argv, &argc) >= 1) { mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "mesg"), mesg); } return exc; -- cgit v1.2.3 From 44edc51612536a9e23dabf7c87afc3996efde027 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 11 Jan 2017 09:53:31 +0900 Subject: Raises Exception if raising exception class is redefined close #3384 This issue was reported by https://hackerone.com/brakhane --- include/mruby.h | 44 ++++++++++++++++++++++++++------------------ src/class.c | 14 ++++++++++++++ 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/include/mruby.h b/include/mruby.h index 76a028ad4..99d06146f 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -607,6 +607,14 @@ MRB_API mrb_bool mrb_class_defined(mrb_state *mrb, const char *name); */ MRB_API struct RClass * mrb_class_get(mrb_state *mrb, const char *name); +/** + * Gets a exception class. + * @param [mrb_state*] mrb The current mruby state. + * @param [const char *] name The name of the class. + * @return [struct RClass *] A reference to the class. +*/ +MRB_API struct RClass * mrb_exc_get(mrb_state *mrb, const char *name); + /** * Returns an mrb_bool. True if inner class was defined, and false if the inner class was not defined. * @@ -1091,23 +1099,23 @@ MRB_API void mrb_print_error(mrb_state *mrb); + those E_* macros requires mrb_state* variable named mrb. + exception objects obtained from those macros are local to mrb */ -#define E_RUNTIME_ERROR (mrb_class_get(mrb, "RuntimeError")) -#define E_TYPE_ERROR (mrb_class_get(mrb, "TypeError")) -#define E_ARGUMENT_ERROR (mrb_class_get(mrb, "ArgumentError")) -#define E_INDEX_ERROR (mrb_class_get(mrb, "IndexError")) -#define E_RANGE_ERROR (mrb_class_get(mrb, "RangeError")) -#define E_NAME_ERROR (mrb_class_get(mrb, "NameError")) -#define E_NOMETHOD_ERROR (mrb_class_get(mrb, "NoMethodError")) -#define E_SCRIPT_ERROR (mrb_class_get(mrb, "ScriptError")) -#define E_SYNTAX_ERROR (mrb_class_get(mrb, "SyntaxError")) -#define E_LOCALJUMP_ERROR (mrb_class_get(mrb, "LocalJumpError")) -#define E_REGEXP_ERROR (mrb_class_get(mrb, "RegexpError")) -#define E_SYSSTACK_ERROR (mrb_class_get(mrb, "SystemStackError")) - -#define E_NOTIMP_ERROR (mrb_class_get(mrb, "NotImplementedError")) -#define E_FLOATDOMAIN_ERROR (mrb_class_get(mrb, "FloatDomainError")) - -#define E_KEY_ERROR (mrb_class_get(mrb, "KeyError")) +#define E_RUNTIME_ERROR (mrb_exc_get(mrb, "RuntimeError")) +#define E_TYPE_ERROR (mrb_exc_get(mrb, "TypeError")) +#define E_ARGUMENT_ERROR (mrb_exc_get(mrb, "ArgumentError")) +#define E_INDEX_ERROR (mrb_exc_get(mrb, "IndexError")) +#define E_RANGE_ERROR (mrb_exc_get(mrb, "RangeError")) +#define E_NAME_ERROR (mrb_exc_get(mrb, "NameError")) +#define E_NOMETHOD_ERROR (mrb_exc_get(mrb, "NoMethodError")) +#define E_SCRIPT_ERROR (mrb_exc_get(mrb, "ScriptError")) +#define E_SYNTAX_ERROR (mrb_exc_get(mrb, "SyntaxError")) +#define E_LOCALJUMP_ERROR (mrb_exc_get(mrb, "LocalJumpError")) +#define E_REGEXP_ERROR (mrb_exc_get(mrb, "RegexpError")) +#define E_SYSSTACK_ERROR (mrb_exc_get(mrb, "SystemStackError")) + +#define E_NOTIMP_ERROR (mrb_exc_get(mrb, "NotImplementedError")) +#define E_FLOATDOMAIN_ERROR (mrb_exc_get(mrb, "FloatDomainError")) + +#define E_KEY_ERROR (mrb_exc_get(mrb, "KeyError")) MRB_API mrb_value mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg); MRB_API mrb_value mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv); @@ -1160,7 +1168,7 @@ MRB_API mrb_value mrb_fiber_yield(mrb_state *mrb, mrb_int argc, const mrb_value * * @mrbgem mruby-fiber */ -#define E_FIBER_ERROR (mrb_class_get(mrb, "FiberError")) +#define E_FIBER_ERROR (mrb_exc_get(mrb, "FiberError")) /* memory pool implementation */ typedef struct mrb_pool mrb_pool; diff --git a/src/class.c b/src/class.c index fed259b5b..cb7bdfddd 100644 --- a/src/class.c +++ b/src/class.c @@ -317,6 +317,20 @@ mrb_class_get(mrb_state *mrb, const char *name) return mrb_class_get_under(mrb, mrb->object_class, name); } +MRB_API struct RClass * +mrb_exc_get(mrb_state *mrb, const char *name) +{ + struct RClass *exc = mrb_class_get_under(mrb, mrb->object_class, name); + struct RClass *e = exc; + + while (e) { + if (e == mrb->eException_class) + return exc; + e = e->super; + } + return mrb->eException_class; +} + MRB_API struct RClass * mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name) { -- cgit v1.2.3 From 06b2e6a76c562b7a83669d0ffe7e4ac43a2636db Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 11 Jan 2017 11:30:52 +0900 Subject: Check if ci->target_class is NULL before dereferencing close #3389 This issue was reported by https://hackerone.com/ston3 --- src/vm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm.c b/src/vm.c index 3023710d4..7b38659a7 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1288,7 +1288,7 @@ RETRY_TRY_BLOCK: int a = GETARG_A(i); int n = GETARG_C(i); - if (mid == 0) { + if (mid == 0 || !mrb->c->ci->target_class) { mrb_value exc; exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method"); -- cgit v1.2.3 From e1ff71029f95e3274136263adbdc51c662ec52de Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 11 Jan 2017 17:51:11 +0900 Subject: String#replace should check replacing string; fix #3374 This issue was reported by https://hackerone.com/tunz --- src/string.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/string.c b/src/string.c index b4746545a..d6bdd6975 100644 --- a/src/string.c +++ b/src/string.c @@ -519,6 +519,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2) long len; check_frozen(mrb, s1); + if (s1 == s2) return mrb_obj_value(s1); len = RSTR_LEN(s2); if (RSTR_SHARED_P(s1)) { str_decref(mrb, s1->as.heap.aux.shared); -- cgit v1.2.3 From db1bd078bedcc33bfd3ca4c45f46bc553786bfd8 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 11 Jan 2017 17:59:56 +0900 Subject: Use temporary variable to avoid potential crash; fix #3387 This issue was original reported by https://hackerone.com/icanthack https://hackerone.com/titanous suggested the solution. `regs` may be reallocated in the function call. --- src/vm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vm.c b/src/vm.c index 7b38659a7..4352b8463 100644 --- a/src/vm.c +++ b/src/vm.c @@ -2411,7 +2411,8 @@ RETRY_TRY_BLOCK: CASE(OP_RANGE) { /* A B C R(A) := range_new(R(B),R(B+1),C) */ int b = GETARG_B(i); - regs[GETARG_A(i)] = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i)); + mrb_value val = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i)); + regs[GETARG_A(i)] = val; ARENA_RESTORE(mrb, ai); NEXT; } -- cgit v1.2.3 From bc4c90de075fd77ecb844daca0a456a06922786b Mon Sep 17 00:00:00 2001 From: Clayton Smith Date: Wed, 11 Jan 2017 09:05:02 -0500 Subject: Use mrb_int for argc. --- src/error.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/error.c b/src/error.c index fda2cd15c..0292910dd 100644 --- a/src/error.c +++ b/src/error.c @@ -44,7 +44,7 @@ static mrb_value exc_initialize(mrb_state *mrb, mrb_value exc) { mrb_value mesg; - int argc; + mrb_int argc; mrb_value *argv; if (mrb_get_args(mrb, "|o*", &mesg, &argv, &argc) >= 1) { -- 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(-) 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 af4f6e8dc6734a40133090df16c10e6099b67abc Mon Sep 17 00:00:00 2001 From: hhc0null Date: Thu, 12 Jan 2017 00:02:17 +0900 Subject: Fix a typo. --- include/mruby/string.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mruby/string.h b/include/mruby/string.h index 9ccf8f187..5a5a6ffd2 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -68,7 +68,7 @@ struct RString { #define mrb_str_ptr(s) ((struct RString*)(mrb_ptr(s))) #define RSTRING(s) mrb_str_ptr(s) #define RSTRING_PTR(s) RSTR_PTR(RSTRING(s)) -#define RSTRING_EMBED_LEN(s) RSTR_ENBED_LEN(RSTRING(s)) +#define RSTRING_EMBED_LEN(s) RSTR_EMBED_LEN(RSTRING(s)) #define RSTRING_LEN(s) RSTR_LEN(RSTRING(s)) #define RSTRING_CAPA(s) RSTR_CAPA(RSTRING(s)) #define RSTRING_END(s) (RSTRING_PTR(s) + RSTRING_LEN(s)) -- cgit v1.2.3 From 38acb9ec36bdd56123e6680885499fbf7f729f21 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 12 Jan 2017 21:43:23 +0900 Subject: Kernel#initialize should not break existing mt; fix #3397 This issue was reported by https://hackerone.com/icanthack The solution is suggested by @clayton-shopify. --- src/class.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/class.c b/src/class.c index cb7bdfddd..45827f5ba 100644 --- a/src/class.c +++ b/src/class.c @@ -915,7 +915,9 @@ boot_defclass(mrb_state *mrb, struct RClass *super) static void boot_initmod(mrb_state *mrb, struct RClass *mod) { - mod->mt = kh_init(mt, mrb); + if (!mod->mt) { + mod->mt = kh_init(mt, mrb); + } } static struct RClass* -- cgit v1.2.3 From a3571240e5fdbdac9210be27e2445e3f82239f44 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 12 Jan 2017 23:08:58 +0900 Subject: Add proper stack size calculation; fix #3398 This issue was reported by https://hackerone.com/ssarong --- src/vm.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/vm.c b/src/vm.c index 4352b8463..9cc29ed5a 100644 --- a/src/vm.c +++ b/src/vm.c @@ -373,7 +373,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc mrb_method_missing(mrb, mid, self, args); } undef = mid; - n++; argc++; + argc++; } ci = cipush(mrb); ci->mid = mid; @@ -389,8 +389,18 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc ci->nregs = argc + 2; stack_extend(mrb, ci->nregs, 0); } + else if (argc >= CALL_MAXARGS) { + mrb_value args = mrb_ary_new_from_values(mrb, argc, argv); + stack_extend(mrb, ci->nregs, 0); + mrb->c->stack[1] = args; + if (undef) { + mrb_ary_unshift(mrb, mrb->c->stack[1], mrb_symbol_value(undef)); + } + ci->argc = -1; + argc = 1; + } else { - ci->nregs = p->body.irep->nregs + n; + ci->nregs = p->body.irep->nregs + argc; stack_extend(mrb, ci->nregs, argc+2); } if (voff >= 0) { @@ -403,7 +413,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc stack_copy(mrb->c->stack+2, argv, argc-1); } } - else if (argc > 0) { + else if (ci->argc > 0) { stack_copy(mrb->c->stack+1, argv, argc); } mrb->c->stack[argc+1] = blk; @@ -2478,7 +2488,12 @@ RETRY_TRY_BLOCK: MRB_API mrb_value mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) { - return mrb_vm_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */ + if (mrb->c->ci->argc < 0) { + return mrb_vm_run(mrb, proc, self, 3); /* receiver, args and block) */ + } + else { + return mrb_vm_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */ + } } MRB_API mrb_value -- cgit v1.2.3 From 8d61f2120c7b3c637ce61df4c13e4b066029a4d5 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 12 Jan 2017 23:14:35 +0900 Subject: Add proper given argument number in the wrong-number-argument error. --- src/vm.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/vm.c b/src/vm.c index 9cc29ed5a..5d2e04383 100644 --- a/src/vm.c +++ b/src/vm.c @@ -717,15 +717,22 @@ argnum_error(mrb_state *mrb, mrb_int num) { mrb_value exc; mrb_value str; + mrb_int argc = mrb->c->ci->argc; + if (argc < 0) { + mrb_value args = mrb->c->stack[1]; + if (mrb_array_p(args)) { + argc = RARRAY_LEN(args); + } + } if (mrb->c->ci->mid) { str = mrb_format(mrb, "'%S': wrong number of arguments (%S for %S)", mrb_sym2str(mrb, mrb->c->ci->mid), - mrb_fixnum_value(mrb->c->ci->argc), mrb_fixnum_value(num)); + mrb_fixnum_value(argc), mrb_fixnum_value(num)); } else { str = mrb_format(mrb, "wrong number of arguments (%S for %S)", - mrb_fixnum_value(mrb->c->ci->argc), mrb_fixnum_value(num)); + mrb_fixnum_value(argc), mrb_fixnum_value(num)); } exc = mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str); mrb_exc_set(mrb, exc); -- cgit v1.2.3 From 6f9cb7406aed5f06dffdb64356d2891aba4a15b1 Mon Sep 17 00:00:00 2001 From: ksss Date: Sat, 14 Jan 2017 10:15:40 +0900 Subject: Implement Kernel.#caller --- mrbgems/mruby-kernel-ext/src/kernel.c | 59 +++++++++++++++++++++++++++++++++ mrbgems/mruby-kernel-ext/test/kernel.rb | 27 +++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/mrbgems/mruby-kernel-ext/src/kernel.c b/mrbgems/mruby-kernel-ext/src/kernel.c index d2153be4a..1aa40260e 100644 --- a/mrbgems/mruby-kernel-ext/src/kernel.c +++ b/mrbgems/mruby-kernel-ext/src/kernel.c @@ -2,6 +2,64 @@ #include #include #include +#include + +static mrb_value +mrb_f_caller(mrb_state *mrb, mrb_value self) +{ + mrb_value bt, v, length; + mrb_int bt_len, argc, lev, n; + + bt = mrb_get_backtrace(mrb); + bt_len = RARRAY_LEN(bt); + argc = mrb_get_args(mrb, "|oo", &v, &length); + + switch (argc) { + case 0: + lev = 1; + n = bt_len - lev; + break; + case 1: + if (mrb_type(v) == MRB_TT_RANGE) { + mrb_int beg, len; + if (mrb_range_beg_len(mrb, v, &beg, &len, bt_len)) { + lev = beg; + n = len; + } + else { + return mrb_nil_value(); + } + } + else { + v = mrb_to_int(mrb, v); + lev = mrb_fixnum(v); + if (lev < 0) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative level (%S)", v); + } + n = bt_len - lev; + } + break; + case 2: + lev = mrb_fixnum(mrb_to_int(mrb, v)); + n = mrb_fixnum(mrb_to_int(mrb, length)); + if (lev < 0) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative level (%S)", v); + } + if (n < 0) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative size (%S)", length); + } + break; + default: + lev = n = 0; + break; + } + + if (n == 0) { + return mrb_ary_new(mrb); + } + + return mrb_funcall(mrb, bt, "[]", 2, mrb_fixnum_value(lev), mrb_fixnum_value(n)); +} /* * call-seq: @@ -170,6 +228,7 @@ mrb_mruby_kernel_ext_gem_init(mrb_state *mrb) struct RClass *krn = mrb->kernel_module; mrb_define_module_function(mrb, krn, "fail", mrb_f_raise, MRB_ARGS_OPT(2)); + mrb_define_module_function(mrb, krn, "caller", mrb_f_caller, MRB_ARGS_NONE()); mrb_define_method(mrb, krn, "__method__", mrb_f_method, MRB_ARGS_NONE()); mrb_define_module_function(mrb, krn, "Integer", mrb_f_integer, MRB_ARGS_ANY()); mrb_define_module_function(mrb, krn, "Float", mrb_f_float, MRB_ARGS_REQ(1)); diff --git a/mrbgems/mruby-kernel-ext/test/kernel.rb b/mrbgems/mruby-kernel-ext/test/kernel.rb index cc6af13a3..ee11dacbf 100644 --- a/mrbgems/mruby-kernel-ext/test/kernel.rb +++ b/mrbgems/mruby-kernel-ext/test/kernel.rb @@ -3,6 +3,33 @@ assert('Kernel.fail, Kernel#fail') do assert_raise(RuntimeError) { Kernel.fail } end +assert('Kernel.caller, Kernel#caller') do + c = Class.new do + def foo(*args) + caller(*args) + end + + def bar(*args) + foo(*args) + end + + def baz(*args) + bar(*args) + end + end + assert_equal "#bar", c.new.baz[0][-4..-1] + assert_equal "#foo", c.new.baz(0)[0][-4..-1] + assert_equal "#bar", c.new.baz(1)[0][-4..-1] + assert_equal "#baz", c.new.baz(2)[0][-4..-1] + assert_equal ["#foo", "#bar"], c.new.baz(0, 2).map { |i| i[-4..-1] } + assert_equal ["#bar", "#baz"], c.new.baz(1..2).map { |i| i[-4..-1] } + assert_nil c.new.baz(10..20) + assert_raise(ArgumentError) { c.new.baz(-1) } + assert_raise(ArgumentError) { c.new.baz(-1, 1) } + assert_raise(ArgumentError) { c.new.baz(1, -1) } + assert_raise(TypeError) { c.new.baz(nil) } +end + assert('Kernel#__method__') do assert_equal(:m, Class.new {def m; __method__; end}.new.m) assert_equal(:m, Class.new {define_method(:m) {__method__}}.new.m) -- cgit v1.2.3 From 59d9f313dfc706789b303ec259fb88ff19207ddc Mon Sep 17 00:00:00 2001 From: ksss Date: Sat, 14 Jan 2017 14:33:47 +0900 Subject: Skip when backtrace doesn't get --- mrbgems/mruby-kernel-ext/test/kernel.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mrbgems/mruby-kernel-ext/test/kernel.rb b/mrbgems/mruby-kernel-ext/test/kernel.rb index ee11dacbf..dd7cea86a 100644 --- a/mrbgems/mruby-kernel-ext/test/kernel.rb +++ b/mrbgems/mruby-kernel-ext/test/kernel.rb @@ -4,6 +4,8 @@ assert('Kernel.fail, Kernel#fail') do end assert('Kernel.caller, Kernel#caller') do + skip "backtrace isn't available" if caller(0).empty? + c = Class.new do def foo(*args) caller(*args) -- cgit v1.2.3 From c83069860a4b5f3aa2c64621e52f7877fe2a453a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 16 Jan 2017 17:20:52 +0900 Subject: Dots is not needed for base 10 negative numbers; fix #3400 --- mrbgems/mruby-sprintf/src/sprintf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index af0ca08ba..616277f5e 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -891,7 +891,7 @@ retry: } else { s = nbuf; - if (v < 0) { + if (base != 10 && v < 0) { dots = 1; } switch (base) { -- cgit v1.2.3 From fe0e45505b0d0fbf627c9a7df0b8df52d0c72321 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 18 Jan 2017 17:53:08 +0900 Subject: Initialize callinfo->acc; ref #3243 --- src/vm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vm.c b/src/vm.c index 5d2e04383..c32fb0c0a 100644 --- a/src/vm.c +++ b/src/vm.c @@ -238,6 +238,7 @@ cipush(mrb_state *mrb) ci->pc = 0; ci->err = 0; ci->proc = 0; + ci->acc = 0; return ci; } -- cgit v1.2.3 From b23fb45f9ce3cb12b33eecc9cab37adc2890f49f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 20 Jan 2017 17:58:29 +0900 Subject: Integral#step without arg should loop forever as CRuby does. --- mrblib/numeric.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mrblib/numeric.rb b/mrblib/numeric.rb index 17155bfd6..975ad973f 100644 --- a/mrblib/numeric.rb +++ b/mrblib/numeric.rb @@ -100,11 +100,18 @@ module Integral # Calls the given block from +self+ to +num+ # incremented by +step+ (default 1). # - def step(num, step = 1, &block) + def step(num=nil, step=1, &block) raise ArgumentError, "step can't be 0" if step == 0 return to_enum(:step, num, step) unless block_given? i = if num.kind_of? Float then self.to_f else self end + if num == nil + while true + block.call(i) + i+=step + end + return self + end if step > 0 while i <= num block.call(i) -- cgit v1.2.3 From 2c0f8f1a23047338a3449b51142b075fb33573f5 Mon Sep 17 00:00:00 2001 From: Clayton Smith Date: Fri, 20 Jan 2017 18:40:18 -0500 Subject: Remove problematic optimization. --- mrbgems/mruby-compiler/core/codegen.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index fc54a0647..89dc20f04 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1675,7 +1675,6 @@ codegen(codegen_scope *s, node *tree, int val) } tree = tree->car; if (tree->car) { /* pre */ - int first = TRUE; t = tree->car; n = 0; while (t) { @@ -1684,10 +1683,7 @@ codegen(codegen_scope *s, node *tree, int val) n++; } else { - if (first) { - genop(s, MKOP_A(OP_LOADNIL, rhs+n)); - first = FALSE; - } + genop(s, MKOP_A(OP_LOADNIL, rhs+n)); gen_assignment(s, t->car, rhs+n, NOVAL); } t = t->cdr; -- cgit v1.2.3 From c48aef0b653ba83452c97b1d1017869de2a846b9 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 21 Jan 2017 17:59:49 +0900 Subject: Stack position may be bigger than stack bottom; fix #3401 This issue was reported by https://hackerone.com/titanous --- src/vm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vm.c b/src/vm.c index c32fb0c0a..77372d937 100644 --- a/src/vm.c +++ b/src/vm.c @@ -137,6 +137,7 @@ stack_extend_alloc(mrb_state *mrb, int room, int keep) size_t size = mrb->c->stend - mrb->c->stbase; size_t off = mrb->c->stack - mrb->c->stbase; + if (off > size) size = off; #ifdef MRB_STACK_EXTEND_DOUBLING if (room <= size) size *= 2; -- cgit v1.2.3 From 797ff625f3ef182ca9ce55d7f8f3bc9ba8adb298 Mon Sep 17 00:00:00 2001 From: Clayton Smith Date: Sat, 21 Jan 2017 09:08:37 -0500 Subject: Fix incorrect parsing of block parameters. --- mrbgems/mruby-compiler/core/parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index ec9b652d7..f8e4eb72f 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -2448,7 +2448,7 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg } | f_arg ',' { - $$ = new_args(p, $1, 0, 1, 0, 0); + $$ = new_args(p, $1, 0, 0, 0, 0); } | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg { -- cgit v1.2.3 From 65c9baae7cea2f67c5cd38b772abe48259f839df Mon Sep 17 00:00:00 2001 From: ksss Date: Sun, 22 Jan 2017 14:06:23 +0900 Subject: Rewrite mrb_ary_splice Referenced to CRuby's array.c(rb_ary_splice) fix #3405 --- src/array.c | 52 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/src/array.c b/src/array.c index 99f9fc8b2..00a716bad 100644 --- a/src/array.c +++ b/src/array.c @@ -589,7 +589,6 @@ MRB_API mrb_value mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_value rpl) { struct RArray *a = mrb_ary_ptr(ary); - mrb_int tail, size; const mrb_value *argv; mrb_int i, argc; @@ -608,7 +607,6 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val if (a->len < len || a->len < head + len) { len = a->len - head; } - tail = head + len; /* size check */ if (mrb_array_p(rpl)) { @@ -623,30 +621,44 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val argc = 1; argv = &rpl; } - size = head + argc; - - if (tail < a->len) size += a->len - tail; - - if (size < 0 || size > ARY_MAX_SIZE) - mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); - - if (size > a->aux.capa) - ary_expand_capa(mrb, a, size); - - if (head > a->len) { + if (head >= a->len) { + if (head > ARY_MAX_SIZE - argc) { + mrb_raisef(mrb, E_INDEX_ERROR, "index %S too big", mrb_fixnum_value(head)); + } + len = head + argc; + if (len > a->aux.capa) { + ary_expand_capa(mrb, a, head + argc); + } ary_fill_with_nil(a->ptr + a->len, head - a->len); + if (argc > 0) { + for (int i = 0; i < argc; i++) { + a->ptr[head + i] = argv[i]; + } + } + a->len = len; } - else if (head < a->len) { - value_move(a->ptr + head + argc, a->ptr + tail, a->len - tail); - } + else { + mrb_int alen; + if (a->len - len > ARY_MAX_SIZE - argc) { + mrb_raisef(mrb, E_INDEX_ERROR, "index %S too big", mrb_fixnum_value(a->len + argc - len)); + } + alen = a->len + argc - len; + if (alen > a->aux.capa) { + ary_expand_capa(mrb, a, alen); + } + + if (len != argc) { + value_move(a->ptr + head + argc, a->ptr + head + len, a->len - (head + len)); + a->len = alen; + } + if (argc > 0) { + value_move(a->ptr + head, argv, argc); + } + } for (i = 0; i < argc; i++) { - *(a->ptr + head + i) = *(argv + i); mrb_field_write_barrier_value(mrb, (struct RBasic*)a, argv[i]); } - - a->len = size; - return ary; } -- cgit v1.2.3 From b49bd70f5967d32a46bce624b87595620664403c Mon Sep 17 00:00:00 2001 From: ksss Date: Sun, 22 Jan 2017 17:50:54 +0900 Subject: Should raise RuntimeError when object frozen --- src/array.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/array.c b/src/array.c index 99f9fc8b2..669e90d02 100644 --- a/src/array.c +++ b/src/array.c @@ -796,6 +796,7 @@ mrb_ary_aset(mrb_state *mrb, mrb_value self) mrb_value v1, v2, v3; mrb_int i, len; + mrb_ary_modify(mrb, mrb_ary_ptr(self)); if (mrb_get_args(mrb, "oo|o", &v1, &v2, &v3) == 2) { switch (mrb_type(v1)) { /* a[n..m] = v */ -- cgit v1.2.3 From fdec607cd06bc12c844fd71bdb75db74f909ff74 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Jan 2017 10:30:14 +0900 Subject: Remove unnecessary inline declaration; ref #3409 --- src/array.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/array.c b/src/array.c index f634070e2..da54b3d6b 100644 --- a/src/array.c +++ b/src/array.c @@ -631,7 +631,7 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val } ary_fill_with_nil(a->ptr + a->len, head - a->len); if (argc > 0) { - for (int i = 0; i < argc; i++) { + for (i = 0; i < argc; i++) { a->ptr[head + i] = argv[i]; } } -- cgit v1.2.3 From 49fd7590df4f510c611f31652235887c0aaaa962 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Jan 2017 10:32:33 +0900 Subject: Use mrb_write_barrier() instead of mrb_field_write_barrier_value() ref #3409 --- src/array.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/array.c b/src/array.c index da54b3d6b..f9155d173 100644 --- a/src/array.c +++ b/src/array.c @@ -656,9 +656,7 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val value_move(a->ptr + head, argv, argc); } } - for (i = 0; i < argc; i++) { - mrb_field_write_barrier_value(mrb, (struct RBasic*)a, argv[i]); - } + mrb_write_barrier(mrb, (struct RBasic*)a); return ary; } -- cgit v1.2.3 From 708088c5fafd469d04a1b428fc49b8b7c27607d2 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Jan 2017 10:52:40 +0900 Subject: Should not make empty strings shared; fix #3407 --- src/string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string.c b/src/string.c index d6bdd6975..02c7ce426 100644 --- a/src/string.c +++ b/src/string.c @@ -423,7 +423,7 @@ byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) mrb_shared_string *shared; orig = mrb_str_ptr(str); - if (RSTR_EMBED_P(orig)) { + if (RSTR_EMBED_P(orig) || RSTR_LEN(orig) == 0) { s = str_new(mrb, orig->as.ary+beg, len); } else { -- cgit v1.2.3 From 5e1d923381072ebcbe002d70bc198a6e95c31f50 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Jan 2017 14:35:26 +0900 Subject: Changed the behavior of mrb_range_beg_len(); close #3411 The new API is: int mrb_range_beg_len(mrb, range, &beg, &len, len, trunc) The new argument `trunc` is a boolean value that specifies whether the function truncates the range. The new return value is an integer instead of a boolean, that is: 0: not a range 1: range with proper edges 2: out of range To get the old behavior, you have to rewrite: mrb_range_beg_len(mrb, range, &beg, &len, len) to: mrn_range_beg_len(mrb, range, &beg, &len, len, TRUE) == 1 [Breaking Change] --- include/mruby/range.h | 2 +- mrbgems/mruby-kernel-ext/src/kernel.c | 2 +- mrbgems/mruby-string-ext/src/string.c | 8 +++++++- src/array.c | 19 ++++++++----------- src/range.c | 20 +++++++------------- src/string.c | 27 +++++++++++++++------------ 6 files changed, 39 insertions(+), 39 deletions(-) diff --git a/include/mruby/range.h b/include/mruby/range.h index fb602b3f3..41e4f1254 100644 --- a/include/mruby/range.h +++ b/include/mruby/range.h @@ -41,7 +41,7 @@ MRB_API struct RRange* mrb_range_ptr(mrb_state *mrb, mrb_value v); */ MRB_API mrb_value mrb_range_new(mrb_state *mrb, mrb_value start, mrb_value end, mrb_bool exclude); -MRB_API mrb_bool mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len); +MRB_API int mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc); mrb_value mrb_get_values_at(mrb_state *mrb, mrb_value obj, mrb_int olen, mrb_int argc, const mrb_value *argv, mrb_value (*func)(mrb_state*, mrb_value, mrb_int)); MRB_END_DECL diff --git a/mrbgems/mruby-kernel-ext/src/kernel.c b/mrbgems/mruby-kernel-ext/src/kernel.c index 1aa40260e..7bb4dea68 100644 --- a/mrbgems/mruby-kernel-ext/src/kernel.c +++ b/mrbgems/mruby-kernel-ext/src/kernel.c @@ -22,7 +22,7 @@ mrb_f_caller(mrb_state *mrb, mrb_value self) case 1: if (mrb_type(v) == MRB_TT_RANGE) { mrb_int beg, len; - if (mrb_range_beg_len(mrb, v, &beg, &len, bt_len)) { + if (mrb_range_beg_len(mrb, v, &beg, &len, bt_len, TRUE) == 1) { lev = beg; n = len; } diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index c6a9e1d0b..7e87b3db4 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -56,8 +56,14 @@ mrb_str_byteslice(mrb_state *mrb, mrb_value str) mrb_int beg; len = RSTRING_LEN(str); - if (mrb_range_beg_len(mrb, a1, &beg, &len, len)) { + switch (mrb_range_beg_len(mrb, a1, &beg, &len, len, TRUE)) { + case 0: /* not range */ + break; + case 1: /* range */ return mrb_str_substr(mrb, str, beg, len); + case 2: /* out of range */ + mrb_raisef(mrb, E_RANGE_ERROR, "%S out of range", a1); + break; } return mrb_nil_value(); } diff --git a/src/array.c b/src/array.c index f9155d173..e41183d68 100644 --- a/src/array.c +++ b/src/array.c @@ -742,7 +742,7 @@ mrb_ary_aget(mrb_state *mrb, mrb_value self) switch (mrb_type(index)) { /* a[n..m] */ case MRB_TT_RANGE: - if (mrb_range_beg_len(mrb, index, &i, &len, a->len)) { + if (mrb_range_beg_len(mrb, index, &i, &len, a->len, TRUE) == 1) { return ary_subseq(mrb, a, i, len); } else { @@ -808,19 +808,16 @@ mrb_ary_aset(mrb_state *mrb, mrb_value self) mrb_ary_modify(mrb, mrb_ary_ptr(self)); if (mrb_get_args(mrb, "oo|o", &v1, &v2, &v3) == 2) { - switch (mrb_type(v1)) { /* a[n..m] = v */ - case MRB_TT_RANGE: - if (mrb_range_beg_len(mrb, v1, &i, &len, RARRAY_LEN(self))) { - mrb_ary_splice(mrb, self, i, len, v2); - } + switch (mrb_range_beg_len(mrb, v1, &i, &len, RARRAY_LEN(self), FALSE)) { + case 0: /* not range */ + mrb_ary_set(mrb, self, aget_index(mrb, v1), v2); break; - /* a[n] = v */ - case MRB_TT_FIXNUM: - mrb_ary_set(mrb, self, mrb_fixnum(v1), v2); + case 1: /* range */ + mrb_ary_splice(mrb, self, i, len, v2); break; - default: - mrb_ary_set(mrb, self, aget_index(mrb, v1), v2); + case 2: /* out of range */ + mrb_raisef(mrb, E_RANGE_ERROR, "%S out of range", v1); break; } return v2; diff --git a/src/range.c b/src/range.c index 73fe7589b..800e64611 100644 --- a/src/range.c +++ b/src/range.c @@ -248,13 +248,13 @@ mrb_range_include(mrb_state *mrb, mrb_value range) return mrb_bool_value(include_p); } -static mrb_bool -range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc) +int +mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc) { mrb_int beg, end; struct RRange *r; - if (mrb_type(range) != MRB_TT_RANGE) return FALSE; + if (mrb_type(range) != MRB_TT_RANGE) return 0; r = mrb_range_ptr(mrb, range); beg = mrb_int(mrb, r->edges->beg); @@ -262,11 +262,11 @@ range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb if (beg < 0) { beg += len; - if (beg < 0) return FALSE; + if (beg < 0) return 2; } if (trunc) { - if (beg > len) return FALSE; + if (beg > len) return 2; if (end > len) end = len; } @@ -278,13 +278,7 @@ range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb *begp = beg; *lenp = len; - return TRUE; -} - -MRB_API mrb_bool -mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len) -{ - return range_beg_len(mrb, range, begp, lenp, len, TRUE); + return 1; } /* 15.2.14.4.12(x) */ @@ -405,7 +399,7 @@ mrb_get_values_at(mrb_state *mrb, mrb_value obj, mrb_int olen, mrb_int argc, con if (mrb_fixnum_p(argv[i])) { mrb_ary_push(mrb, result, func(mrb, obj, mrb_fixnum(argv[i]))); } - else if (range_beg_len(mrb, argv[i], &beg, &len, olen, FALSE)) { + else if (mrb_range_beg_len(mrb, argv[i], &beg, &len, olen, FALSE) == 1) { mrb_int const end = olen < beg + len ? olen : beg + len; for (j = beg; j < end; ++j) { mrb_ary_push(mrb, result, func(mrb, obj, j)); diff --git a/src/string.c b/src/string.c index 02c7ce426..7a75bb63e 100644 --- a/src/string.c +++ b/src/string.c @@ -1091,22 +1091,25 @@ num_index: return mrb_nil_value(); case MRB_TT_RANGE: - /* check if indx is Range */ - { - mrb_int beg, len; + goto range_arg; - len = RSTRING_CHAR_LEN(str); - if (mrb_range_beg_len(mrb, indx, &beg, &len, len)) { - return str_subseq(mrb, str, beg, len); - } - else { - return mrb_nil_value(); - } - } - case MRB_TT_FLOAT: default: indx = mrb_Integer(mrb, indx); if (mrb_nil_p(indx)) { + range_arg: + { + mrb_int beg, len; + + len = RSTRING_CHAR_LEN(str); + switch (mrb_range_beg_len(mrb, indx, &beg, &len, len, TRUE)) { + case 1: + return str_subseq(mrb, str, beg, len); + case 2: + return mrb_nil_value(); + default: + break; + } + } mrb_raise(mrb, E_TYPE_ERROR, "can't convert to Fixnum"); } idx = mrb_fixnum(indx); -- cgit v1.2.3 From 4d38cad31b2107d23fa393561eb5dae5da16c82c Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Jan 2017 15:05:12 +0900 Subject: Add MRB_API to mrb_range_beg_len(); ref #3411 --- src/range.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/range.c b/src/range.c index 800e64611..5553171b9 100644 --- a/src/range.c +++ b/src/range.c @@ -248,7 +248,7 @@ mrb_range_include(mrb_state *mrb, mrb_value range) return mrb_bool_value(include_p); } -int +MRB_API int mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc) { mrb_int beg, end; -- cgit v1.2.3 From 78a395d44607b52a256cd41016210ece1a739538 Mon Sep 17 00:00:00 2001 From: ksss Date: Mon, 23 Jan 2017 15:18:12 +0900 Subject: Refactoring: Use array_copy instead of for loop --- src/array.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/array.c b/src/array.c index e41183d68..9e5b90061 100644 --- a/src/array.c +++ b/src/array.c @@ -590,7 +590,7 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val { struct RArray *a = mrb_ary_ptr(ary); const mrb_value *argv; - mrb_int i, argc; + mrb_int argc; ary_modify(mrb, a); @@ -631,9 +631,7 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val } ary_fill_with_nil(a->ptr + a->len, head - a->len); if (argc > 0) { - for (i = 0; i < argc; i++) { - a->ptr[head + i] = argv[i]; - } + array_copy(a->ptr + head, argv, argc); } a->len = len; } -- cgit v1.2.3 From 28b7b9ec6441d96d63f309b93f7b486074b807e3 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Jan 2017 16:22:55 +0900 Subject: Skip non string values in backtraces; ref #3408 --- src/backtrace.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/backtrace.c b/src/backtrace.c index 285af562f..b499cee5a 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -219,7 +219,9 @@ print_backtrace(mrb_state *mrb, mrb_value backtrace) for (i = 0; i < n; i++) { mrb_value entry = RARRAY_PTR(backtrace)[i]; - fprintf(stream, "\t[%d] %.*s\n", i, (int)RSTRING_LEN(entry), RSTRING_PTR(entry)); + if (mrb_string_p(entry)) { + fprintf(stream, "\t[%d] %.*s\n", i, (int)RSTRING_LEN(entry), RSTRING_PTR(entry)); + } } } -- cgit v1.2.3 From 324887d0d61ce2127dfd839930a88507c1641b75 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Jan 2017 16:23:48 +0900 Subject: Backtrace list must be an array of strings; fix #3408 --- src/error.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/error.c b/src/error.c index 8e456ff1a..a71ee548f 100644 --- a/src/error.c +++ b/src/error.c @@ -208,6 +208,19 @@ exc_set_backtrace(mrb_state *mrb, mrb_value exc) mrb_value backtrace; mrb_get_args(mrb, "o", &backtrace); + if (!mrb_array_p(backtrace)) { + type_err: + mrb_raise(mrb, E_TYPE_ERROR, "backtrace must be Array of String"); + } + else { + const mrb_value *p = RARRAY_PTR(backtrace); + const mrb_value *pend = p + RARRAY_LEN(backtrace); + + while (p < pend) { + if (!mrb_string_p(*p)) goto type_err; + p++; + } + } mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "backtrace"), backtrace); return backtrace; -- cgit v1.2.3 From ffb5e5ab08624c899de03b5347966eb3e070dce5 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Jan 2017 16:44:11 +0900 Subject: The ensure clause should keep its ci after its execution; fix #3406 This issue was reported by https://hackerone.com/ston3 --- src/vm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vm.c b/src/vm.c index 77372d937..8c91ae1e7 100644 --- a/src/vm.c +++ b/src/vm.c @@ -280,12 +280,14 @@ ecall(mrb_state *mrb, int i) mrb_callinfo *ci; mrb_value *self = mrb->c->stack; struct RObject *exc; + int cioff; if (i<0) return; p = mrb->c->ensure[i]; if (!p) return; if (mrb->c->ci->eidx > i) mrb->c->ci->eidx = i; + cioff = mrb->c->ci - mrb->c->cibase; ci = cipush(mrb); ci->stackent = mrb->c->stack; ci->mid = ci[-1].mid; @@ -298,6 +300,7 @@ ecall(mrb_state *mrb, int i) exc = mrb->exc; mrb->exc = 0; mrb_run(mrb, p, *self); mrb->c->ensure[i] = NULL; + mrb->c->ci = mrb->c->cibase + cioff; if (!mrb->exc) mrb->exc = exc; } -- cgit v1.2.3 From 3ce82603a56f2b9480e2bd889dd98f813b868757 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Jan 2017 16:48:18 +0900 Subject: Fix memory leak; ref #3378 The fix was proposed by @titanous --- mrbgems/mruby-compiler/core/codegen.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 89dc20f04..fae12b288 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -93,6 +93,7 @@ codegen_error(codegen_scope *s, const char *message) if (!s) return; while (s->prev) { codegen_scope *tmp = s->prev; + mrb_free(s->mrb, s->iseq); mrb_pool_close(s->mpool); s = tmp; } -- cgit v1.2.3 From f0f095bc135c4d2e6f6d54d6b5683db77708369b Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Jan 2017 16:53:31 +0900 Subject: Fix a double free problem in codegen.c; fix #3378 This issue was first reported by https://hackerone.com/geeknik The fix was proposed by @titanous --- include/mruby/irep.h | 1 + mrbgems/mruby-compiler/core/codegen.c | 4 +--- src/state.c | 5 ++++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/mruby/irep.h b/include/mruby/irep.h index 8922f4b76..35ae2bbaa 100644 --- a/include/mruby/irep.h +++ b/include/mruby/irep.h @@ -39,6 +39,7 @@ typedef struct mrb_irep { struct mrb_locals *lv; /* debug info */ + mrb_bool own_filename; const char *filename; uint16_t *lines; struct mrb_irep_debug_info* debug_info; diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index fae12b288..eae0492ce 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2844,6 +2844,7 @@ scope_finish(codegen_scope *s) memcpy(fname, s->filename, fname_len); fname[fname_len] = '\0'; irep->filename = fname; + irep->own_filename = TRUE; } irep->nlocals = s->nlocals; @@ -2951,9 +2952,6 @@ mrb_generate_code(mrb_state *mrb, parser_state *p) return proc; } MRB_CATCH(&scope->jmp) { - if (scope->filename == scope->irep->filename) { - scope->irep->filename = NULL; - } mrb_irep_decref(mrb, scope->irep); mrb_pool_close(scope->mpool); return NULL; diff --git a/src/state.c b/src/state.c index 1259ac3a0..11b71dd63 100644 --- a/src/state.c +++ b/src/state.c @@ -159,7 +159,9 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep) } mrb_free(mrb, irep->reps); mrb_free(mrb, irep->lv); - mrb_free(mrb, (void *)irep->filename); + if (irep->own_filename) { + mrb_free(mrb, (void *)irep->filename); + } mrb_free(mrb, irep->lines); mrb_debug_info_free(mrb, irep->debug_info); mrb_free(mrb, irep); @@ -261,6 +263,7 @@ mrb_add_irep(mrb_state *mrb) irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep)); *irep = mrb_irep_zero; irep->refcnt = 1; + irep->own_filename = FALSE; return irep; } -- cgit v1.2.3 From 28cf7a549dda15a5f76944d314ad5e20d5362df5 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Jan 2017 22:18:29 +0900 Subject: Change return type of mrb_range_beg_len() from `int` to `mrb_int`. ref #3411 --- include/mruby/range.h | 2 +- src/range.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mruby/range.h b/include/mruby/range.h index 41e4f1254..b166e586b 100644 --- a/include/mruby/range.h +++ b/include/mruby/range.h @@ -41,7 +41,7 @@ MRB_API struct RRange* mrb_range_ptr(mrb_state *mrb, mrb_value v); */ MRB_API mrb_value mrb_range_new(mrb_state *mrb, mrb_value start, mrb_value end, mrb_bool exclude); -MRB_API int mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc); +MRB_API mrb_int mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc); mrb_value mrb_get_values_at(mrb_state *mrb, mrb_value obj, mrb_int olen, mrb_int argc, const mrb_value *argv, mrb_value (*func)(mrb_state*, mrb_value, mrb_int)); MRB_END_DECL diff --git a/src/range.c b/src/range.c index 5553171b9..2cb6f2361 100644 --- a/src/range.c +++ b/src/range.c @@ -248,7 +248,7 @@ mrb_range_include(mrb_state *mrb, mrb_value range) return mrb_bool_value(include_p); } -MRB_API int +MRB_API mrb_int mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc) { mrb_int beg, end; -- cgit v1.2.3 From 72bff2932ba983b4e8aaedda50fa5663dcc5c3ed Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 24 Jan 2017 11:36:27 +0900 Subject: Use size_t to avoid integer overflow in mrb_ary_splice(); fix #3413 --- src/array.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/array.c b/src/array.c index 9e5b90061..c7499ab36 100644 --- a/src/array.c +++ b/src/array.c @@ -591,6 +591,7 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val struct RArray *a = mrb_ary_ptr(ary); const mrb_value *argv; mrb_int argc; + size_t tail; ary_modify(mrb, a); @@ -604,7 +605,8 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val mrb_raise(mrb, E_INDEX_ERROR, "index is out of array"); } } - if (a->len < len || a->len < head + len) { + tail = head + len; + if (a->len < len || (size_t)a->len < tail) { len = a->len - head; } @@ -647,7 +649,8 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val } if (len != argc) { - value_move(a->ptr + head + argc, a->ptr + head + len, a->len - (head + len)); + tail = head + len; + value_move(a->ptr + head + argc, a->ptr + tail, a->len - tail); a->len = alen; } if (argc > 0) { -- cgit v1.2.3 From b3ce364537cf1f745112d6e5acd71f009dcd872f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 24 Jan 2017 17:54:05 +0900 Subject: Outer class may be same as the class; fix #3382 --- src/class.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class.c b/src/class.c index 45827f5ba..81b312fd0 100644 --- a/src/class.c +++ b/src/class.c @@ -1586,7 +1586,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) if (sym == 0) { return mrb_nil_value(); } - else if (outer && outer != mrb->object_class) { + else if (outer && outer != c && outer != mrb->object_class) { mrb_value base = mrb_class_path(mrb, outer); path = mrb_str_buf_new(mrb, 0); if (mrb_nil_p(base)) { -- cgit v1.2.3 From 51d7a69ab04d1e58618c419543744783de0a9670 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 25 Jan 2017 11:07:57 +0900 Subject: Clear (o).w first for MRB_WORD_BOXING; ref #3396 --- include/mruby/boxing_word.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/mruby/boxing_word.h b/include/mruby/boxing_word.h index 30d69842f..6ca491585 100644 --- a/include/mruby/boxing_word.h +++ b/include/mruby/boxing_word.h @@ -95,13 +95,13 @@ mrb_type(mrb_value o) #define mrb_undef_p(o) ((o).w == MRB_Qundef) #define mrb_nil_p(o) ((o).w == MRB_Qnil) -#define BOXWORD_SET_VALUE(o, ttt, attr, v) do {\ +#define BOXWORD_SET_VALUE(o, ttt, attr, v) do { \ switch (ttt) {\ case MRB_TT_FALSE: (o).w = (v) ? MRB_Qfalse : MRB_Qnil; break;\ case MRB_TT_TRUE: (o).w = MRB_Qtrue; break;\ case MRB_TT_UNDEF: (o).w = MRB_Qundef; break;\ - case MRB_TT_FIXNUM: (o).value.i_flag = MRB_FIXNUM_FLAG; (o).attr = (v); break;\ - case MRB_TT_SYMBOL: (o).value.sym_flag = MRB_SYMBOL_FLAG; (o).attr = (v); break;\ + case MRB_TT_FIXNUM: (o).w = 0;(o).value.i_flag = MRB_FIXNUM_FLAG; (o).attr = (v); break;\ + case MRB_TT_SYMBOL: (o).w = 0;(o).value.sym_flag = MRB_SYMBOL_FLAG; (o).attr = (v); break;\ default: (o).w = 0; (o).attr = (v); if ((o).value.bp) (o).value.bp->tt = ttt; break;\ }\ } while (0) -- cgit v1.2.3 From ac88f85a9eb0d03707fc382cbaa442da146d9203 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 25 Jan 2017 11:09:15 +0900 Subject: Copy mrb_float values from pool when MRB_WORD_BOXING; ref #3396 --- src/vm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/vm.c b/src/vm.c index 8c91ae1e7..9684dabfd 100644 --- a/src/vm.c +++ b/src/vm.c @@ -859,7 +859,15 @@ RETRY_TRY_BLOCK: CASE(OP_LOADL) { /* A Bx R(A) := Pool(Bx) */ +#ifdef MRB_WORD_BOXING + mrb_value val = pool[GETARG_Bx(i)]; + if (mrb_float_p(val)) { + val = mrb_float_value(mrb, mrb_float(val)); + } + regs[GETARG_A(i)] = val; +#else regs[GETARG_A(i)] = pool[GETARG_Bx(i)]; +#endif NEXT; } -- cgit v1.2.3 From 6420951463ec9ace9eecb50923dc6a1925a45d31 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 25 Jan 2017 15:38:25 +0900 Subject: Update example lines of mrbgems in build_config.rb; ref #3414 --- build_config.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/build_config.rb b/build_config.rb index bc9e69e42..8293092ab 100644 --- a/build_config.rb +++ b/build_config.rb @@ -16,8 +16,10 @@ MRuby::Build.new do |conf| # g.cc.flags << '-g' # append cflags in this gem # end # conf.gem 'examples/mrbgems/c_and_ruby_extension_example' - # conf.gem :github => 'masuidrive/mrbgems-example', :checksum_hash => '76518e8aecd131d047378448ac8055fa29d974a9' - # conf.gem :git => 'git@github.com:masuidrive/mrbgems-example.git', :branch => 'master', :options => '-v' + # conf.gem :core => 'mruby-eval' + # conf.gem :mgem => 'mruby-io' + # conf.gem :github => 'iij/mruby-io' + # conf.gem :git => 'git@github.com:iij/mruby-io.git', :branch => 'master', :options => '-v' # include the default GEMs conf.gembox 'default' -- cgit v1.2.3 From ab5812d0d8ba79f8a3f56dfef189830d6c12bc3d Mon Sep 17 00:00:00 2001 From: Uchio KONDO Date: Thu, 2 Feb 2017 14:45:32 +0900 Subject: Use standard Module(Class)#to_s --- mrbgems/mruby-bin-mruby/bintest/mruby.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgems/mruby-bin-mruby/bintest/mruby.rb b/mrbgems/mruby-bin-mruby/bintest/mruby.rb index ad8ec3a0f..72ac6586d 100644 --- a/mrbgems/mruby-bin-mruby/bintest/mruby.rb +++ b/mrbgems/mruby-bin-mruby/bintest/mruby.rb @@ -52,7 +52,7 @@ assert('garbage collecting built-in classes') do NilClass = nil GC.start Array.dup -print nil.class.name +print nil.class.to_s RUBY script.flush assert_equal "NilClass", `#{cmd('mruby')} #{script.path}` -- cgit v1.2.3 From a8ccda5692de601d014a942ee1ea2129388ce84c Mon Sep 17 00:00:00 2001 From: Clayton Smith Date: Thu, 2 Feb 2017 16:35:59 -0500 Subject: Fetch arguments earlier to avoid a crash. --- mrbgems/mruby-random/src/random.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index 587e6c01a..f81d38fe6 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -124,6 +124,8 @@ mrb_random_init(mrb_state *mrb, mrb_value self) mrb_value seed; mt_state *t; + seed = get_opt(mrb); + /* avoid memory leaks */ t = (mt_state*)DATA_PTR(self); if (t) { @@ -134,7 +136,6 @@ mrb_random_init(mrb_state *mrb, mrb_value self) t = (mt_state *)mrb_malloc(mrb, sizeof(mt_state)); t->mti = N + 1; - seed = get_opt(mrb); seed = mrb_random_mt_srand(mrb, t, seed); if (mrb_nil_p(seed)) { t->has_seed = FALSE; -- cgit v1.2.3 From 6e0ba0085d22b7751c46b178e841046483f0f6b4 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 4 Feb 2017 12:37:08 +0900 Subject: Jump address should fit in 16 bits range; fix #3426 --- mrbgems/mruby-compiler/core/codegen.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index eae0492ce..1f7c069d4 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -388,6 +388,9 @@ dispatch(codegen_scope *s, int pc) scope_error(s); break; } + if (diff > MAXARG_sBx) { + codegen_error(s, "too distant jump address"); + } s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff); } -- cgit v1.2.3 From 8e0f2313302871ddd713c3e8e6a9d4731426f308 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 4 Feb 2017 12:59:08 +0900 Subject: Mark `mrb->backtrace.exc` as GC root; fix #3388 --- src/gc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gc.c b/src/gc.c index c75a0f9aa..225ca095c 100644 --- a/src/gc.c +++ b/src/gc.c @@ -857,6 +857,7 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc) mrb_gc_mark(mrb, (struct RBasic*)mrb->top_self); /* mark exception */ mrb_gc_mark(mrb, (struct RBasic*)mrb->exc); + mrb_gc_mark(mrb, (struct RBasic*)mrb->backtrace.exc); /* mark pre-allocated exception */ mrb_gc_mark(mrb, (struct RBasic*)mrb->nomem_err); #ifdef MRB_GC_FIXED_ARENA -- cgit v1.2.3 From 8f52b88ee75fb3ca62931a1d3975c9cd78eae2d8 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 4 Feb 2017 13:48:23 +0900 Subject: No need to make env unshared in the finalization; fix #3425 --- src/gc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gc.c b/src/gc.c index 225ca095c..88d157d9c 100644 --- a/src/gc.c +++ b/src/gc.c @@ -367,7 +367,7 @@ mrb_gc_init(mrb_state *mrb, mrb_gc *gc) #endif } -static void obj_free(mrb_state *mrb, struct RBasic *obj); +static void obj_free(mrb_state *mrb, struct RBasic *obj, int end); void free_heap(mrb_state *mrb, mrb_gc *gc) @@ -381,7 +381,7 @@ free_heap(mrb_state *mrb, mrb_gc *gc) page = page->next; for (p = objects(tmp), e=p+MRB_HEAP_PAGE_SIZE; pas.free.tt != MRB_TT_FREE) - obj_free(mrb, &p->as.basic); + obj_free(mrb, &p->as.basic, TRUE); } mrb_free(mrb, tmp); } @@ -699,7 +699,7 @@ mrb_gc_mark(mrb_state *mrb, struct RBasic *obj) } static void -obj_free(mrb_state *mrb, struct RBasic *obj) +obj_free(mrb_state *mrb, struct RBasic *obj, int end) { DEBUG(printf("obj_free(%p,tt=%d)\n",obj,obj->tt)); switch (obj->tt) { @@ -753,7 +753,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj) case MRB_TT_FIBER: { struct mrb_context *c = ((struct RFiber*)obj)->cxt; - if (c && c != mrb->root_c) { + if (!end && c && c != mrb->root_c) { mrb_callinfo *ci = c->ci; mrb_callinfo *ce = c->cibase; @@ -1020,7 +1020,7 @@ incremental_sweep_phase(mrb_state *mrb, mrb_gc *gc, size_t limit) while (pas.basic)) { if (p->as.basic.tt != MRB_TT_FREE) { - obj_free(mrb, &p->as.basic); + obj_free(mrb, &p->as.basic, FALSE); if (p->as.basic.tt == MRB_TT_FREE) { p->as.free.next = page->freelist; page->freelist = (struct RBasic*)p; -- cgit v1.2.3 From bf4e79cc62af809138bc7db7e54ece67080b5fa8 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 4 Feb 2017 14:07:33 +0900 Subject: `argv` may be modified when `mrb_funcall()` is called; fix #3419 Calling `mrb_funcall()` and `mrb_yield()` (and their related functions) are discouraged unless absolutely necessary, because it can cause this kind of issues very easily. --- src/kernel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/kernel.c b/src/kernel.c index 76bd59469..5ca1736c3 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -445,8 +445,11 @@ mrb_obj_extend_m(mrb_state *mrb, mrb_value self) { mrb_value *argv; mrb_int argc; + mrb_value args; mrb_get_args(mrb, "*", &argv, &argc); + args = mrb_ary_new_from_values(mrb, argc, argv); + argv = (mrb_value*)RARRAY_PTR(args); return mrb_obj_extend(mrb, argc, argv, self); } -- cgit v1.2.3 From 48e0bbbfeea8268b09ad0a6bbc840834cc443fe0 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 4 Feb 2017 16:19:31 +0900 Subject: Make `eval` to use trampoline technique; fix #3415 Now `eval()` can call Fiber.yield etc. --- mrbgems/mruby-eval/src/eval.c | 17 +++++++-------- src/vm.c | 49 ++++++++++++++++++++++++------------------- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c index 26dd728ba..81bc80280 100644 --- a/mrbgems/mruby-eval/src/eval.c +++ b/mrbgems/mruby-eval/src/eval.c @@ -5,6 +5,9 @@ #include #include +mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p); +mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self); + static struct mrb_irep * get_closure_irep(mrb_state *mrb, int level) { @@ -209,22 +212,15 @@ f_eval(mrb_state *mrb, mrb_value self) mrb_value binding = mrb_nil_value(); char *file = NULL; mrb_int line = 1; - mrb_value ret; struct RProc *proc; mrb_get_args(mrb, "s|ozi", &s, &len, &binding, &file, &line); proc = create_proc_from_string(mrb, s, len, binding, file, line); - ret = mrb_top_run(mrb, proc, mrb->c->stack[0], 0); - if (mrb->exc) { - mrb_exc_raise(mrb, mrb_obj_value(mrb->exc)); - } - - return ret; + mrb_assert(!MRB_PROC_CFUNC_P(proc)); + return mrb_exec_irep(mrb, self, proc); } -mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self); - #define CI_ACC_SKIP -1 static mrb_value @@ -250,7 +246,8 @@ f_instance_eval(mrb_state *mrb, mrb_value self) c->ci->target_class = mrb_class_ptr(cv); proc = create_proc_from_string(mrb, s, len, mrb_nil_value(), file, line); mrb->c->ci->env = NULL; - return mrb_vm_run(mrb, proc, mrb->c->stack[0], 0); + mrb_assert(!MRB_PROC_CFUNC_P(proc)); + return mrb_exec_irep(mrb, self, proc); } else { mrb_get_args(mrb, "&", &b); diff --git a/src/vm.c b/src/vm.c index 9684dabfd..0c0f5a4bb 100644 --- a/src/vm.c +++ b/src/vm.c @@ -447,6 +447,33 @@ mrb_funcall_argv(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, cons return mrb_funcall_with_block(mrb, self, mid, argc, argv, mrb_nil_value()); } +mrb_value +mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p) +{ + mrb_callinfo *ci = mrb->c->ci; + + ci->proc = p; + if (MRB_PROC_CFUNC_P(p)) { + return p->body.func(mrb, self); + } + if (ci->argc < 0) { + stack_extend(mrb, (p->body.irep->nregs < 3) ? 3 : p->body.irep->nregs, 3); + } + else { + stack_extend(mrb, p->body.irep->nregs, ci->argc+2); + } + + ci->nregs = p->body.irep->nregs; + ci = cipush(mrb); + ci->nregs = 0; + ci->target_class = 0; + ci->pc = p->body.irep->iseq; + ci->stackent = mrb->c->stack; + ci->acc = 0; + + return self; +} + /* 15.3.1.3.4 */ /* 15.3.1.3.44 */ /* @@ -488,7 +515,6 @@ mrb_f_send(mrb_state *mrb, mrb_value self) ci = mrb->c->ci; ci->mid = name; ci->target_class = c; - ci->proc = p; regs = mrb->c->stack+1; /* remove first symbol from arguments */ if (ci->argc >= 0) { @@ -501,26 +527,7 @@ mrb_f_send(mrb_state *mrb, mrb_value self) mrb_ary_shift(mrb, regs[0]); } - if (MRB_PROC_CFUNC_P(p)) { - return p->body.func(mrb, self); - } - - if (ci->argc < 0) { - stack_extend(mrb, (p->body.irep->nregs < 3) ? 3 : p->body.irep->nregs, 3); - } - else { - stack_extend(mrb, p->body.irep->nregs, ci->argc+2); - } - - ci->nregs = p->body.irep->nregs; - ci = cipush(mrb); - ci->nregs = 0; - ci->target_class = 0; - ci->pc = p->body.irep->iseq; - ci->stackent = mrb->c->stack; - ci->acc = 0; - - return self; + return mrb_exec_irep(mrb, self, p); } static mrb_value -- cgit v1.2.3 From f2b18a604c6e4db5875b689ba26b377ad720a3ab Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 6 Feb 2017 09:14:49 +0900 Subject: Check maximum number of formal arguments. http://hkdnet.hatenablog.com/entry/2017/02/06/080000 (Japanese) --- mrbgems/mruby-compiler/core/codegen.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 1f7c069d4..778b6fe0f 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -666,6 +666,9 @@ lambda_body(codegen_scope *s, node *tree, int blk) ka = kd = 0; ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0; + if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) { + codegen_error(s, "too many formal arguments"); + } a = ((mrb_aspec)(ma & 0x1f) << 18) | ((mrb_aspec)(oa & 0x1f) << 13) | ((ra & 1) << 12) -- 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(-) 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 46e4e342f4a1bf216c027838e343919556703547 Mon Sep 17 00:00:00 2001 From: Edgar Boda-Majer Date: Tue, 7 Feb 2017 13:33:53 +0100 Subject: Fix interpolation escaping in String.inspect --- src/string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string.c b/src/string.c index 7a75bb63e..c370e0723 100644 --- a/src/string.c +++ b/src/string.c @@ -2644,7 +2644,7 @@ mrb_str_inspect(mrb_state *mrb, mrb_value str) } #endif c = *p; - if (c == '"'|| c == '\\' || (c == '#' && IS_EVSTR(p, pend))) { + if (c == '"'|| c == '\\' || (c == '#' && IS_EVSTR(p+1, pend))) { buf[0] = '\\'; buf[1] = c; mrb_str_cat(mrb, result, buf, 2); continue; -- cgit v1.2.3 From be550f04e48ee3bfd7ca6967c6042db0599675dc Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 8 Feb 2017 09:45:55 +0900 Subject: codedump.c: OP_POPERR does not have register access. --- src/codedump.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/codedump.c b/src/codedump.c index 4b13d4361..59ba4fdae 100644 --- a/src/codedump.c +++ b/src/codedump.c @@ -416,8 +416,7 @@ codedump(mrb_state *mrb, mrb_irep *irep) print_lv(mrb, irep, c, RA); break; case OP_POPERR: - printf("OP_POPERR\t%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); + printf("OP_POPERR\t%d\t\t\n", GETARG_A(c)); break; case OP_EPOP: printf("OP_EPOP\t%d\n", GETARG_A(c)); -- cgit v1.2.3 From f3d4ff16d39b34585d41c31ffc09a0ffb512ff81 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 8 Feb 2017 16:22:48 +0900 Subject: Fixed a bug in ci address shifting; fix #3423 Dinko Galetic and Denis Kasak reported the issue and the fix. (via https://hackerone.com/dgaletic). --- src/vm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vm.c b/src/vm.c index 0c0f5a4bb..c174c0b43 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1705,9 +1705,10 @@ RETRY_TRY_BLOCK: mrb->jmp = prev_jmp; return v; } - cipop(mrb); + ci = mrb->c->ci; acc = ci->acc; mrb->c->stack = ci->stackent; + cipop(mrb); if (acc == CI_ACC_SKIP) { mrb->jmp = prev_jmp; return v; -- cgit v1.2.3 From b277c58e783f187cfff1b7bb5843d2e95d3c3b0b Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 8 Feb 2017 16:31:37 +0900 Subject: Mark classes referenced from saved backtrace. Maybe related to #3438 --- src/gc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/gc.c b/src/gc.c index 88d157d9c..1608dbcb2 100644 --- a/src/gc.c +++ b/src/gc.c @@ -857,7 +857,12 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc) mrb_gc_mark(mrb, (struct RBasic*)mrb->top_self); /* mark exception */ mrb_gc_mark(mrb, (struct RBasic*)mrb->exc); + /* mark backtrace */ mrb_gc_mark(mrb, (struct RBasic*)mrb->backtrace.exc); + e = (size_t)mrb->backtrace.n; + for (i=0; ibacktrace.entries[i].klass); + } /* mark pre-allocated exception */ mrb_gc_mark(mrb, (struct RBasic*)mrb->nomem_err); #ifdef MRB_GC_FIXED_ARENA -- cgit v1.2.3 From 76135e757f96ad640e3c44b4d46f73e512fbfc50 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 8 Feb 2017 19:01:09 +0900 Subject: Check if m->env is NULL before dereferencing it; fix #3436 --- src/vm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vm.c b/src/vm.c index c174c0b43..287b18518 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1309,7 +1309,9 @@ RETRY_TRY_BLOCK: else { stack_extend(mrb, irep->nregs, ci->argc+2); } - regs[0] = m->env->stack[0]; + if(m->env) { + regs[0] = m->env->stack[0]; + } pc = irep->iseq; JUMP; } -- cgit v1.2.3 From af4d74fc7df9788a1c0013a4dc66e9bbac951b20 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 8 Feb 2017 21:13:22 +0900 Subject: Add MRB_TT_PROC check to OP_SUPER as well; fix #3432 --- src/vm.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/vm.c b/src/vm.c index 287b18518..e734775e2 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1366,11 +1366,22 @@ RETRY_TRY_BLOCK: ci->mid = mid; ci->proc = m; ci->stackent = mrb->c->stack; - if (n == CALL_MAXARGS) { - ci->argc = -1; - } - else { - ci->argc = n; + { + int bidx; + mrb_value blk; + + if (n == CALL_MAXARGS) { + ci->argc = -1; + bidx = a+2; + } + else { + ci->argc = n; + bidx = a+n+1; + } + blk = regs[bidx]; + if (!mrb_nil_p(blk) && mrb_type(blk) != MRB_TT_PROC) { + regs[bidx] = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc"); + } } ci->target_class = c; ci->pc = pc + 1; -- cgit v1.2.3 From 4b32e651a55e8bd55a9e43474823c01e999ba79e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 8 Feb 2017 23:10:25 +0900 Subject: Check if irep is NULL before print_backtrace() According to the valgrind log attached to #3438, proc->body.irep may be NULL in some cases. --- src/backtrace.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/backtrace.c b/src/backtrace.c index b499cee5a..051d5d4e0 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -118,6 +118,7 @@ each_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, each_backtrace_func if (MRB_PROC_CFUNC_P(ci->proc)) continue; irep = ci->proc->body.irep; + if (!irep) continue; if (mrb->c->cibase[i].err) { pc = mrb->c->cibase[i].err; -- cgit v1.2.3 From d0ecf862d9d2e7aed461bc9360686449f56c5d25 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 8 Feb 2017 23:27:17 +0900 Subject: Fixed mixture of signed/unsigned integers in mrbgems/mruby-bin-debugger. --- mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c | 4 ++-- mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c b/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c index 218aeda90..27f27a05a 100644 --- a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c +++ b/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c @@ -43,7 +43,7 @@ check_lineno( mrb_irep_debug_info_file *info_file, uint16_t lineno ) } static int32_t -get_break_index( mrb_debug_context *dbg, int32_t bpno ) +get_break_index( mrb_debug_context *dbg, uint32_t bpno ) { uint32_t i; int32_t index; @@ -296,7 +296,7 @@ mrb_debug_get_break_all( mrb_state *mrb, mrb_debug_context *dbg, uint32_t size, int32_t mrb_debug_get_break( mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno, mrb_debug_breakpoint *bp ) { - uint32_t index; + int32_t index; if((mrb == NULL) || (dbg == NULL) || (bp == NULL)) { return MRB_DEBUG_INVALID_ARGUMENT; diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c b/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c index 1c77d1ef8..33e9575bf 100644 --- a/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c +++ b/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c @@ -71,7 +71,7 @@ dirname(mrb_state *mrb, const char *path) } p = strrchr(path, '/'); - len = p != NULL ? p - path : strlen(path); + len = p != NULL ? (size_t)(p - path) : strlen(path); dir = mrb_malloc(mrb, len + 1); strncpy(dir, path, len); -- cgit v1.2.3 From cd8284fe0b156aaa6e4cb3f9cb934da25d4829be Mon Sep 17 00:00:00 2001 From: ksss Date: Fri, 10 Feb 2017 13:15:49 +0900 Subject: Fix build error when trace mode Rakefile ``` file "a.txt" do system "echo hello > a.txt" end file "b.txt" => "a.txt" do system "cp a.txt b.txt" end task :default => "b.txt" ``` ``` $ touch b.txt $ ruby minirake --trace Invoke default (already=[], needed=[true]) rake aborted! No such file or directory @ rb_file_s_stat - a.txt minirake:241:in `stat' minirake:241:in `timestamp' minirake:233:in `block in needed?' minirake:233:in `collect' minirake:233:in `needed?' minirake:91:in `invoke' minirake:95:in `block in invoke' minirake:95:in `each' minirake:95:in `invoke' minirake:467:in `block in run' minirake:466:in `each' minirake:466:in `run' minirake:484:in `
' ``` --- minirake | 1 + 1 file changed, 1 insertion(+) diff --git a/minirake b/minirake index eb219b934..6e63cbb1e 100755 --- a/minirake +++ b/minirake @@ -237,6 +237,7 @@ module MiniRake # Time stamp for file task. def timestamp + return Time.at(0) unless File.exist?(name) stat = File::stat(name.to_s) stat.directory? ? Time.at(0) : stat.mtime end -- cgit v1.2.3 From 981105b3e6758455646e9834b1c2695bf774a401 Mon Sep 17 00:00:00 2001 From: Tomasz Dabrowski Date: Fri, 10 Feb 2017 12:58:41 +0100 Subject: String#ljust and String#rjust reimplementation (fix #3445) - String#ljust and String#rjust are now C functions to improve performance - infinite loop because of an empty padding argument is now prevented (ArgumentError is raised) - extra tests for ljust/rjust added --- mrbgems/mruby-string-ext/mrblib/string.rb | 46 ---------------- mrbgems/mruby-string-ext/src/string.c | 92 +++++++++++++++++++++++++++++++ mrbgems/mruby-string-ext/test/string.rb | 20 +++++++ 3 files changed, 112 insertions(+), 46 deletions(-) diff --git a/mrbgems/mruby-string-ext/mrblib/string.rb b/mrbgems/mruby-string-ext/mrblib/string.rb index 6e5f3c73d..610a462a7 100644 --- a/mrbgems/mruby-string-ext/mrblib/string.rb +++ b/mrbgems/mruby-string-ext/mrblib/string.rb @@ -263,52 +263,6 @@ class String self end - ## - # call-seq: - # str.ljust(integer, padstr=' ') -> new_str - # - # If integer is greater than the length of str, returns a new - # String of length integer with str left justified - # and padded with padstr; otherwise, returns str. - # - # "hello".ljust(4) #=> "hello" - # "hello".ljust(20) #=> "hello " - # "hello".ljust(20, '1234') #=> "hello123412341234123" - def ljust(idx, padstr = ' ') - if idx <= self.size - return self - end - newstr = self.dup - newstr << padstr - while newstr.size <= idx - newstr << padstr - end - return newstr.slice(0,idx) - end - - ## - # call-seq: - # str.rjust(integer, padstr=' ') -> new_str - # - # If integer is greater than the length of str, returns a new - # String of length integer with str right justified - # and padded with padstr; otherwise, returns str. - # - # "hello".rjust(4) #=> "hello" - # "hello".rjust(20) #=> " hello" - # "hello".rjust(20, '1234') #=> "123412341234123hello" - def rjust(idx, padstr = ' ') - if idx <= self.size - return self - end - padsize = idx - self.size - newstr = padstr.dup - while newstr.size <= padsize - newstr << padstr - end - return newstr.slice(0,padsize) + self - end - # str.upto(other_str, exclusive=false) {|s| block } -> str # str.upto(other_str, exclusive=false) -> an_enumerator # diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index 7e87b3db4..45d406f6f 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -5,6 +5,9 @@ #include #include +#define MAX(a,b) ((a)>(b) ? (a) : (b)) +#define MIN(a,b) ((a)<(b) ? (a) : (b)) + static mrb_value mrb_str_getbyte(mrb_state *mrb, mrb_value str) { @@ -509,6 +512,93 @@ mrb_str_ord(mrb_state* mrb, mrb_value str) } #endif +static mrb_value +mrb_str_just(mrb_state* mrb, mrb_value str, mrb_bool right_just) +{ + mrb_value new_str; + mrb_int idx = 0, i = 0, bytes_to_copy = 0, start_pos = 0, final_pos = 0, + pad_str_length = 0; + mrb_int str_length = RSTRING_LEN(str); + const char *pad_str = NULL; + char *new_str_ptr = NULL; + + mrb_get_args(mrb, "i|s!", &idx, &pad_str, &pad_str_length); + + if (pad_str == NULL) + { + pad_str = " "; + pad_str_length = 1; + } + + if (pad_str_length == 0) + { + mrb_raise(mrb, E_ARGUMENT_ERROR, "zero width padding"); + } + + if (idx <= str_length) + { + return str; + } + + new_str = mrb_str_dup(mrb, str); + mrb_str_resize(mrb, new_str, idx); + + new_str_ptr = RSTRING_PTR(new_str); + + if (right_just) + { + memcpy(new_str_ptr + idx - str_length, RSTRING_PTR(str), str_length); + } + + start_pos = right_just ? 0 : str_length; + final_pos = idx - (right_just ? str_length : 0); + + for (i = start_pos; i < final_pos; i += pad_str_length) + { + bytes_to_copy = idx - i - (right_just ? str_length : 0); + bytes_to_copy = MIN(pad_str_length, bytes_to_copy); + memcpy(new_str_ptr + i, pad_str, bytes_to_copy); + } + + return new_str; +} + +/* + * call-seq: + * str.ljust(integer, padstr=' ') -> new_str + * + * If integer is greater than the length of str, returns a new + * String of length integer with str left justified + * and padded with padstr; otherwise, returns str. + * + * "hello".ljust(4) #=> "hello" + * "hello".ljust(20) #=> "hello " + * "hello".ljust(20, '1234') #=> "hello123412341234123" + */ +static mrb_value +mrb_str_ljust(mrb_state* mrb, mrb_value str) +{ + return mrb_str_just(mrb, str, FALSE); +} + +/* + * call-seq: + * str.rjust(integer, padstr=' ') -> new_str + * + * If integer is greater than the length of str, returns a new + * String of length integer with str right justified + * and padded with padstr; otherwise, returns str. + * + * "hello".rjust(4) #=> "hello" + * "hello".rjust(20) #=> " hello" + * "hello".rjust(20, '1234') #=> "123412341234123hello" + */ +static mrb_value +mrb_str_rjust(mrb_state* mrb, mrb_value str) +{ + return mrb_str_just(mrb, str, TRUE); +} + void mrb_mruby_string_ext_gem_init(mrb_state* mrb) { @@ -530,6 +620,8 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb) mrb_define_method(mrb, s, "lines", mrb_str_lines, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "succ", mrb_str_succ, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "succ!", mrb_str_succ_bang, MRB_ARGS_NONE()); + mrb_define_method(mrb, s, "ljust", mrb_str_ljust, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); + mrb_define_method(mrb, s, "rjust", mrb_str_rjust, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next"), mrb_intern_lit(mrb, "succ")); mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next!"), mrb_intern_lit(mrb, "succ!")); mrb_define_method(mrb, s, "ord", mrb_str_ord, MRB_ARGS_NONE()); diff --git a/mrbgems/mruby-string-ext/test/string.rb b/mrbgems/mruby-string-ext/test/string.rb index 228a236af..2b2c02b8b 100644 --- a/mrbgems/mruby-string-ext/test/string.rb +++ b/mrbgems/mruby-string-ext/test/string.rb @@ -444,6 +444,26 @@ assert('String#rjust') do assert_equal "hello", "hello".rjust(-3) end +assert('String#ljust should not change string') do + a = "hello" + a.ljust(20) + assert_equal "hello", a +end + +assert('String#rjust should not change string') do + a = "hello" + a.rjust(20) + assert_equal "hello", a +end + +assert('String#ljust should raise on zero width padding') do + assert_raise(ArgumentError) { "foo".ljust(10, '') } +end + +assert('String#rjust should raise on zero width padding') do + assert_raise(ArgumentError) { "foo".rjust(10, '') } +end + assert('String#upto') do a = "aa" start = "aa" -- cgit v1.2.3 From 24048cd998777757147b14948e0a149dffcac76d Mon Sep 17 00:00:00 2001 From: Tomasz Dabrowski Date: Fri, 10 Feb 2017 14:44:36 +0100 Subject: Tests for UTF-8 String#ljust and String#rjust --- mrbgems/mruby-string-ext/test/string.rb | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/mrbgems/mruby-string-ext/test/string.rb b/mrbgems/mruby-string-ext/test/string.rb index 2b2c02b8b..996ad2669 100644 --- a/mrbgems/mruby-string-ext/test/string.rb +++ b/mrbgems/mruby-string-ext/test/string.rb @@ -433,6 +433,7 @@ end assert('String#ljust') do assert_equal "hello", "hello".ljust(4) assert_equal "hello ", "hello".ljust(20) + assert_equal 20, "hello".ljust(20).length assert_equal "hello123412341234123", "hello".ljust(20, '1234') assert_equal "hello", "hello".ljust(-3) end @@ -440,10 +441,39 @@ end assert('String#rjust') do assert_equal "hello", "hello".rjust(4) assert_equal " hello", "hello".rjust(20) + assert_equal 20, "hello".rjust(20).length assert_equal "123412341234123hello", "hello".rjust(20, '1234') assert_equal "hello", "hello".rjust(-3) end +if UTF8STRING + assert('String#ljust with UTF8') do + assert_equal "helloん ", "helloん".ljust(20) + assert_equal "helloó ", "helloó".ljust(34) + assert_equal 34, "helloó".ljust(34).length + assert_equal "helloんんんんんんんんんんんんんん", "hello".ljust(19, 'ん') + assert_equal "helloんんんんんんんんんんんんんんん", "hello".ljust(20, 'ん') + end + + assert('String#rjust with UTF8') do + assert_equal " helloん", "helloん".rjust(20) + assert_equal " helloó", "helloó".rjust(34) + # assert_equal 34, "helloó".rjust(34).length + assert_equal "んんんんんんんんんんんんんんhello", "hello".rjust(19, 'ん') + assert_equal "んんんんんんんんんんんんんんんhello", "hello".rjust(20, 'ん') + end + + assert('UTF8 byte counting') do + skip('string length is broken after []=') + + # based on assert_equal 34, "helloó".rjust(34).length + ret = ' ' + ret[-6..-1] = "helloó" + + assert_equal 34, ret.length + end +end + assert('String#ljust should not change string') do a = "hello" a.ljust(20) -- cgit v1.2.3 From ac9d04f4af6e229ad8e0f306c745b07b404978f5 Mon Sep 17 00:00:00 2001 From: Tomasz Dabrowski Date: Fri, 10 Feb 2017 15:17:20 +0100 Subject: String#ljust and String#rjust reimplemented with optimized Ruby --- mrbgems/mruby-string-ext/mrblib/string.rb | 38 +++++++++++++ mrbgems/mruby-string-ext/src/string.c | 92 ------------------------------- 2 files changed, 38 insertions(+), 92 deletions(-) diff --git a/mrbgems/mruby-string-ext/mrblib/string.rb b/mrbgems/mruby-string-ext/mrblib/string.rb index 610a462a7..8895b7ad3 100644 --- a/mrbgems/mruby-string-ext/mrblib/string.rb +++ b/mrbgems/mruby-string-ext/mrblib/string.rb @@ -263,6 +263,44 @@ class String self end + ## + # call-seq: + # str.ljust(integer, padstr=' ') -> new_str + # + # If integer is greater than the length of str, returns a new + # String of length integer with str left justified + # and padded with padstr; otherwise, returns str. + # + # "hello".ljust(4) #=> "hello" + # "hello".ljust(20) #=> "hello " + # "hello".ljust(20, '1234') #=> "hello123412341234123" + def ljust(idx, padstr = ' ') + raise ArgumentError, 'zero width padding' if padstr == '' + return self if idx <= self.size + pad_repetitions = (idx / padstr.length).ceil + padding = (padstr * pad_repetitions)[0...(idx - self.length)] + self + padding + end + + ## + # call-seq: + # str.rjust(integer, padstr=' ') -> new_str + # + # If integer is greater than the length of str, returns a new + # String of length integer with str right justified + # and padded with padstr; otherwise, returns str. + # + # "hello".rjust(4) #=> "hello" + # "hello".rjust(20) #=> " hello" + # "hello".rjust(20, '1234') #=> "123412341234123hello" + def rjust(idx, padstr = ' ') + raise ArgumentError, 'zero width padding' if padstr == '' + return self if idx <= self.size + pad_repetitions = (idx / padstr.length).ceil + padding = (padstr * pad_repetitions)[0...(idx - self.length)] + padding + self + end + # str.upto(other_str, exclusive=false) {|s| block } -> str # str.upto(other_str, exclusive=false) -> an_enumerator # diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index 45d406f6f..7e87b3db4 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -5,9 +5,6 @@ #include #include -#define MAX(a,b) ((a)>(b) ? (a) : (b)) -#define MIN(a,b) ((a)<(b) ? (a) : (b)) - static mrb_value mrb_str_getbyte(mrb_state *mrb, mrb_value str) { @@ -512,93 +509,6 @@ mrb_str_ord(mrb_state* mrb, mrb_value str) } #endif -static mrb_value -mrb_str_just(mrb_state* mrb, mrb_value str, mrb_bool right_just) -{ - mrb_value new_str; - mrb_int idx = 0, i = 0, bytes_to_copy = 0, start_pos = 0, final_pos = 0, - pad_str_length = 0; - mrb_int str_length = RSTRING_LEN(str); - const char *pad_str = NULL; - char *new_str_ptr = NULL; - - mrb_get_args(mrb, "i|s!", &idx, &pad_str, &pad_str_length); - - if (pad_str == NULL) - { - pad_str = " "; - pad_str_length = 1; - } - - if (pad_str_length == 0) - { - mrb_raise(mrb, E_ARGUMENT_ERROR, "zero width padding"); - } - - if (idx <= str_length) - { - return str; - } - - new_str = mrb_str_dup(mrb, str); - mrb_str_resize(mrb, new_str, idx); - - new_str_ptr = RSTRING_PTR(new_str); - - if (right_just) - { - memcpy(new_str_ptr + idx - str_length, RSTRING_PTR(str), str_length); - } - - start_pos = right_just ? 0 : str_length; - final_pos = idx - (right_just ? str_length : 0); - - for (i = start_pos; i < final_pos; i += pad_str_length) - { - bytes_to_copy = idx - i - (right_just ? str_length : 0); - bytes_to_copy = MIN(pad_str_length, bytes_to_copy); - memcpy(new_str_ptr + i, pad_str, bytes_to_copy); - } - - return new_str; -} - -/* - * call-seq: - * str.ljust(integer, padstr=' ') -> new_str - * - * If integer is greater than the length of str, returns a new - * String of length integer with str left justified - * and padded with padstr; otherwise, returns str. - * - * "hello".ljust(4) #=> "hello" - * "hello".ljust(20) #=> "hello " - * "hello".ljust(20, '1234') #=> "hello123412341234123" - */ -static mrb_value -mrb_str_ljust(mrb_state* mrb, mrb_value str) -{ - return mrb_str_just(mrb, str, FALSE); -} - -/* - * call-seq: - * str.rjust(integer, padstr=' ') -> new_str - * - * If integer is greater than the length of str, returns a new - * String of length integer with str right justified - * and padded with padstr; otherwise, returns str. - * - * "hello".rjust(4) #=> "hello" - * "hello".rjust(20) #=> " hello" - * "hello".rjust(20, '1234') #=> "123412341234123hello" - */ -static mrb_value -mrb_str_rjust(mrb_state* mrb, mrb_value str) -{ - return mrb_str_just(mrb, str, TRUE); -} - void mrb_mruby_string_ext_gem_init(mrb_state* mrb) { @@ -620,8 +530,6 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb) mrb_define_method(mrb, s, "lines", mrb_str_lines, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "succ", mrb_str_succ, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "succ!", mrb_str_succ_bang, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "ljust", mrb_str_ljust, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); - mrb_define_method(mrb, s, "rjust", mrb_str_rjust, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next"), mrb_intern_lit(mrb, "succ")); mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next!"), mrb_intern_lit(mrb, "succ!")); mrb_define_method(mrb, s, "ord", mrb_str_ord, MRB_ARGS_NONE()); -- cgit v1.2.3 From d1bc7caecaf337976351934d5910726106601bd9 Mon Sep 17 00:00:00 2001 From: Tomasz Dabrowski Date: Fri, 10 Feb 2017 15:17:42 +0100 Subject: Optimization for String#* for 1-byte strings --- src/string.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/string.c b/src/string.c index c370e0723..2e8ebda32 100644 --- a/src/string.c +++ b/src/string.c @@ -870,7 +870,9 @@ mrb_str_times(mrb_state *mrb, mrb_value self) str2 = str_new(mrb, 0, len); str_with_class(mrb, str2, self); p = RSTR_PTR(str2); - if (len > 0) { + if (len == 1) { + memset(p, RSTRING_PTR(self)[0], len); + } else if (len > 0) { n = RSTRING_LEN(self); memcpy(p, RSTRING_PTR(self), n); while (n <= len/2) { -- cgit v1.2.3 From 6cb7aef56318a345fd7dd9afa3c25e33eb7dd03e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 11 Feb 2017 16:00:26 +0900 Subject: Add type cast to pacify warning --- src/string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string.c b/src/string.c index 2e8ebda32..5e37abee1 100644 --- a/src/string.c +++ b/src/string.c @@ -1773,7 +1773,7 @@ mrb_str_reverse_bang(mrb_state *mrb, mrb_value str) mrb_str_modify(mrb, mrb_str_ptr(str)); len = RSTRING_LEN(str); - buf = mrb_malloc(mrb, (size_t)len); + buf = (char*)mrb_malloc(mrb, (size_t)len); p = buf; e = buf + len; -- cgit v1.2.3 From 8f4a929e1a01c8d6176fb53a9ef5dff6de632959 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 11 Feb 2017 16:27:07 +0900 Subject: String#replace should update s->flags for MRB_STR_NO_UTF. Otherwise String#size may return wrong length; fix #3448 --- src/string.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/string.c b/src/string.c index 5e37abee1..abe8ad865 100644 --- a/src/string.c +++ b/src/string.c @@ -519,6 +519,8 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2) long len; check_frozen(mrb, s1); + s1->flags &= ~MRB_STR_NO_UTF; + s1->flags |= s2->flags&MRB_STR_NO_UTF; if (s1 == s2) return mrb_obj_value(s1); len = RSTR_LEN(s2); if (RSTR_SHARED_P(s1)) { -- cgit v1.2.3 From b130f43298b03f2b1e8e1bf86c236a6f0caadfb3 Mon Sep 17 00:00:00 2001 From: robert Date: Sat, 11 Feb 2017 07:40:55 +0000 Subject: remove skip that shouldn't be necessary anymore. the test should pass after https://github.com/mruby/mruby/commit/8f4a929e1a01c8d6176fb53a9ef5dff6de632959. --- mrbgems/mruby-string-ext/test/string.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mrbgems/mruby-string-ext/test/string.rb b/mrbgems/mruby-string-ext/test/string.rb index 996ad2669..9b7e99647 100644 --- a/mrbgems/mruby-string-ext/test/string.rb +++ b/mrbgems/mruby-string-ext/test/string.rb @@ -464,12 +464,10 @@ if UTF8STRING end assert('UTF8 byte counting') do - skip('string length is broken after []=') - # based on assert_equal 34, "helloó".rjust(34).length + # see https://github.com/mruby/mruby/issues/3448 ret = ' ' ret[-6..-1] = "helloó" - assert_equal 34, ret.length end end -- cgit v1.2.3 From 0b143898c4203ce611dc0d270569fc576f894758 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 11 Feb 2017 16:52:45 +0900 Subject: Remove historical comment; ref #3450 #3448 --- mrbgems/mruby-string-ext/test/string.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/mrbgems/mruby-string-ext/test/string.rb b/mrbgems/mruby-string-ext/test/string.rb index 9b7e99647..24bc859d8 100644 --- a/mrbgems/mruby-string-ext/test/string.rb +++ b/mrbgems/mruby-string-ext/test/string.rb @@ -464,8 +464,6 @@ if UTF8STRING end assert('UTF8 byte counting') do - # based on assert_equal 34, "helloó".rjust(34).length - # see https://github.com/mruby/mruby/issues/3448 ret = ' ' ret[-6..-1] = "helloó" assert_equal 34, ret.length -- cgit v1.2.3 From 642ab8ecdace909b7bd294190e342e58c67ce6c8 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 11 Feb 2017 18:13:39 +0900 Subject: `ecall()` should preserve stack address referenced from ci[1]. OP_RETURN accesses ci[1]->stackent that might be broken; fix #3442 --- src/vm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vm.c b/src/vm.c index e734775e2..276e2ab6d 100644 --- a/src/vm.c +++ b/src/vm.c @@ -281,6 +281,7 @@ ecall(mrb_state *mrb, int i) mrb_value *self = mrb->c->stack; struct RObject *exc; int cioff; + mrb_value *nstk; if (i<0) return; p = mrb->c->ensure[i]; @@ -289,6 +290,7 @@ ecall(mrb_state *mrb, int i) mrb->c->ci->eidx = i; cioff = mrb->c->ci - mrb->c->cibase; ci = cipush(mrb); + nstk = ci->stackent; ci->stackent = mrb->c->stack; ci->mid = ci[-1].mid; ci->acc = CI_ACC_SKIP; @@ -300,6 +302,7 @@ ecall(mrb_state *mrb, int i) exc = mrb->exc; mrb->exc = 0; mrb_run(mrb, p, *self); mrb->c->ensure[i] = NULL; + ci->stackent = nstk; mrb->c->ci = mrb->c->cibase + cioff; if (!mrb->exc) mrb->exc = exc; } -- cgit v1.2.3 From ff03a9a61c62340cff62f8e0fdc1a1e8775b6f17 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 11 Feb 2017 20:35:52 +0900 Subject: Avoid integer overflow in sprintf(); fix #3439 This issue was reported by https://hackerone.com/aerodudrizzt --- mrbgems/mruby-sprintf/src/sprintf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index 616277f5e..d02a2aa4d 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -116,8 +116,9 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base) #define CHECK(l) do {\ /* int cr = ENC_CODERANGE(result);*/\ - while (blen + (l) >= bsiz) {\ + while ((l) >= bsiz - blen) {\ bsiz*=2;\ + if (bsiz < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "too big specifier"); \ }\ mrb_str_resize(mrb, result, bsiz);\ /* ENC_CODERANGE_SET(result, cr);*/\ -- cgit v1.2.3 From 90f262f6426ca2b8c588d0e7083c1a4c97fccee9 Mon Sep 17 00:00:00 2001 From: Tomasz Dabrowski Date: Sat, 11 Feb 2017 13:02:48 +0100 Subject: Revert "Optimization for String#* for 1-byte strings" This reverts commit d1bc7caecaf337976351934d5910726106601bd9. --- src/string.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/string.c b/src/string.c index abe8ad865..acf32167d 100644 --- a/src/string.c +++ b/src/string.c @@ -872,9 +872,7 @@ mrb_str_times(mrb_state *mrb, mrb_value self) str2 = str_new(mrb, 0, len); str_with_class(mrb, str2, self); p = RSTR_PTR(str2); - if (len == 1) { - memset(p, RSTRING_PTR(self)[0], len); - } else if (len > 0) { + if (len > 0) { n = RSTRING_LEN(self); memcpy(p, RSTRING_PTR(self), n); while (n <= len/2) { -- cgit v1.2.3 From 1f2d786e3220ecb6b3ff95e31f538ce338374c54 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 11 Feb 2017 21:21:19 +0900 Subject: Avoid direct return from ecall(); fix #3441 There's incompatibility left for mruby. When you return from `ensure` clause, mruby simply ignores the return value. CRuby returns from the method squashing the exception raised. ``` def f no_such_method() # NoMethodError ensure return 22 end p f() # CRuby prints `22` ``` --- src/vm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm.c b/src/vm.c index 276e2ab6d..70583864e 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1652,7 +1652,7 @@ RETRY_TRY_BLOCK: switch (GETARG_B(i)) { case OP_R_RETURN: /* Fall through to OP_R_NORMAL otherwise */ - if (proc->env && !MRB_PROC_STRICT_P(proc)) { + if (ci->acc >=0 && proc->env && !MRB_PROC_STRICT_P(proc)) { struct REnv *e = top_env(mrb, proc); if (!MRB_ENV_STACK_SHARED_P(e)) { -- cgit v1.2.3 From e4fa59f5ed2eb1631c6f01e48870d49dab9aff37 Mon Sep 17 00:00:00 2001 From: Tomasz Dabrowski Date: Sun, 12 Feb 2017 11:15:20 +0100 Subject: Fixed aspec for Kernel#caller --- mrbgems/mruby-kernel-ext/src/kernel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgems/mruby-kernel-ext/src/kernel.c b/mrbgems/mruby-kernel-ext/src/kernel.c index 7bb4dea68..7e6fa28bd 100644 --- a/mrbgems/mruby-kernel-ext/src/kernel.c +++ b/mrbgems/mruby-kernel-ext/src/kernel.c @@ -228,7 +228,7 @@ mrb_mruby_kernel_ext_gem_init(mrb_state *mrb) struct RClass *krn = mrb->kernel_module; mrb_define_module_function(mrb, krn, "fail", mrb_f_raise, MRB_ARGS_OPT(2)); - mrb_define_module_function(mrb, krn, "caller", mrb_f_caller, MRB_ARGS_NONE()); + mrb_define_module_function(mrb, krn, "caller", mrb_f_caller, MRB_ARGS_OPT(2)); mrb_define_method(mrb, krn, "__method__", mrb_f_method, MRB_ARGS_NONE()); mrb_define_module_function(mrb, krn, "Integer", mrb_f_integer, MRB_ARGS_ANY()); mrb_define_module_function(mrb, krn, "Float", mrb_f_float, MRB_ARGS_REQ(1)); -- cgit v1.2.3 From f198530444f4b5ebfd011c3287114951c8553e5e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 13 Feb 2017 18:18:09 +0900 Subject: Fixed too much value_copy() when block is not given; fix #3440 The issue was reported by https://hackerone.com/titanous --- src/vm.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/vm.c b/src/vm.c index 70583864e..f2af6f950 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1151,12 +1151,14 @@ RETRY_TRY_BLOCK: } if (GET_OPCODE(i) != OP_SENDB) { SET_NIL_VALUE(regs[bidx]); + bidx = 0; } else { mrb_value blk = regs[bidx]; if (!mrb_nil_p(blk) && mrb_type(blk) != MRB_TT_PROC) { regs[bidx] = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc"); } + bidx = 1; } c = mrb_class(mrb, recv); m = mrb_method_search_vm(mrb, &c, mid); @@ -1177,15 +1179,17 @@ RETRY_TRY_BLOCK: mrb_method_missing(mrb, mid, recv, args); } mid = missing; + if (n == CALL_MAXARGS-1) { + regs[a+1] = mrb_ary_new_from_values(mrb, n, regs+a+1); + n++; + } if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], sym); } else { - value_move(regs+a+2, regs+a+1, ++n); + value_move(regs+a+2, regs+a+1, n+bidx); regs[a+1] = sym; - if (n == CALL_MAXARGS) { - regs[a+1] = mrb_ary_new_from_values(mrb, n, regs+a+1); - } + n++; } } @@ -1355,6 +1359,10 @@ RETRY_TRY_BLOCK: mrb_method_missing(mrb, mid, recv, args); } mid = missing; + if (n == CALL_MAXARGS-1) { + regs[a+1] = mrb_ary_new_from_values(mrb, n, regs+a+1); + n++; + } if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid)); } -- cgit v1.2.3 From c2ddcd451724c9399014ab24a6d47815ed1a1c7d Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 13 Feb 2017 18:45:20 +0900 Subject: Should handle `break` from funcall(); fix #3434 This issue was reported by https://hackerone.com/d4nny --- src/vm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm.c b/src/vm.c index f2af6f950..b89b6d0c5 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1733,7 +1733,7 @@ RETRY_TRY_BLOCK: acc = ci->acc; mrb->c->stack = ci->stackent; cipop(mrb); - if (acc == CI_ACC_SKIP) { + if (acc == CI_ACC_SKIP || acc == CI_ACC_DIRECT) { mrb->jmp = prev_jmp; return v; } -- cgit v1.2.3 From ecb6ac8b4aca56582ebed3e955178a0ad6c77d5d Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 13 Feb 2017 19:31:06 +0900 Subject: Fixed codegen error of redo in rescue; fix #3422 The issue (and the fix) was reported by https://hackerone.com/dgaletic --- mrbgems/mruby-compiler/core/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 778b6fe0f..23e036d49 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2038,7 +2038,7 @@ codegen(codegen_scope *s, node *tree, int val) break; case NODE_REDO: - if (!s->loop) { + if (!s->loop || s->loop->type == LOOP_BEGIN || s->loop->type == LOOP_RESCUE) { raise_error(s, "unexpected redo"); } else { -- cgit v1.2.3 From 719f700adf7598d0ad910dcd3a94aad2ef354033 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 14 Feb 2017 00:15:58 +0900 Subject: Extend mruby stack when keep is bigger than room; fix #3421 But #3421 still cause stack overflow error due to infinite recursion. To prevent overflow, we need to add different stack depth check. --- src/vm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vm.c b/src/vm.c index b89b6d0c5..8bb446fa9 100644 --- a/src/vm.c +++ b/src/vm.c @@ -169,6 +169,9 @@ stack_extend_alloc(mrb_state *mrb, int room, int keep) static inline void stack_extend(mrb_state *mrb, int room, int keep) { + if (room < keep) { + room = keep; + } if (mrb->c->stack + room >= mrb->c->stend) { stack_extend_alloc(mrb, room, keep); } -- cgit v1.2.3 From 30aa5218543cd44df7c1d90a5c10cf6f622f5a8a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 14 Feb 2017 00:22:12 +0900 Subject: Do not use mrb_funcall() if Hash#default is not overridden; ref #3421 This change reduces the recursion level, but does not solve the stack overflow issue entirely. --- include/mruby.h | 1 + src/hash.c | 21 ++++++++++++++++++++- src/kernel.c | 14 ++++++++++---- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/include/mruby.h b/include/mruby.h index 99d06146f..6950cf904 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -1147,6 +1147,7 @@ MRB_API mrb_value mrb_attr_get(mrb_state *mrb, mrb_value obj, mrb_sym id); MRB_API mrb_bool mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid); MRB_API mrb_bool mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c); +MRB_API mrb_bool mrb_func_basic_p(mrb_state *mrb, mrb_value obj, mrb_sym mid, mrb_func_t func); /* diff --git a/src/hash.c b/src/hash.c index 98feaceac..b7bd648c0 100644 --- a/src/hash.c +++ b/src/hash.c @@ -159,6 +159,9 @@ mrb_hash_new(mrb_state *mrb) return mrb_hash_new_capa(mrb, 0); } +static mrb_value mrb_hash_default(mrb_state *mrb, mrb_value hash); +static mrb_value hash_default(mrb_state *mrb, mrb_value hash, mrb_value key); + MRB_API mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) { @@ -171,7 +174,9 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) return kh_value(h, k).v; } - /* not found */ + if (mrb_func_basic_p(mrb, hash, mrb_intern_lit(mrb, "default"), mrb_hash_default)) { + return hash_default(mrb, hash, key); + } /* xxx mrb_funcall_tailcall(mrb, hash, "default", 1, key); */ return mrb_funcall(mrb, hash, "default", 1, key); } @@ -366,6 +371,20 @@ mrb_hash_aget(mrb_state *mrb, mrb_value self) return mrb_hash_get(mrb, self, key); } +static mrb_value +hash_default(mrb_state *mrb, mrb_value hash, mrb_value key) +{ + if (MRB_RHASH_DEFAULT_P(hash)) { + if (MRB_RHASH_PROCDEFAULT_P(hash)) { + return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key); + } + else { + return RHASH_IFNONE(hash); + } + } + return mrb_nil_value(); +} + /* 15.2.13.4.5 */ /* * call-seq: diff --git a/src/kernel.c b/src/kernel.c index 8b00d701b..02bb3c99b 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -28,15 +28,21 @@ typedef enum { NOEX_RESPONDS = 0x80 } mrb_method_flag_t; -static mrb_bool -mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj) +MRB_API mrb_bool +mrb_func_basic_p(mrb_state *mrb, mrb_value obj, mrb_sym mid, mrb_func_t func) { - struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern_lit(mrb, "to_s")); - if (MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s)) + struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mid); + if (MRB_PROC_CFUNC_P(me) && (me->body.func == func)) return TRUE; return FALSE; } +static mrb_bool +mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj) +{ + return mrb_func_basic_p(mrb, obj, mrb_intern_lit(mrb, "to_s"), mrb_any_to_s); +} + /* 15.3.1.3.17 */ /* * call-seq: -- cgit v1.2.3 From 131566753dc497fa2b4d7159eeed61bb9e2a1885 Mon Sep 17 00:00:00 2001 From: palkan Date: Mon, 13 Feb 2017 20:57:29 +0300 Subject: Separate compilers setup from config setup Fixes #3418. --- tasks/mrbgem_spec.rake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tasks/mrbgem_spec.rake b/tasks/mrbgem_spec.rake index 3053c3d49..1f7cde529 100644 --- a/tasks/mrbgem_spec.rake +++ b/tasks/mrbgem_spec.rake @@ -90,7 +90,9 @@ module MRuby build.libmruby << @objs instance_eval(&@build_config_initializer) if @build_config_initializer + end + def setup_compilers compilers.each do |compiler| compiler.define_rules build_dir, "#{dir}" compiler.defines << %Q[MRBGEM_#{funcname.upcase}_VERSION=#{version}] @@ -419,6 +421,8 @@ module MRuby @ary = tsort_dependencies gem_table.keys, gem_table, true + each(&:setup_compilers) + each do |g| import_include_paths(g) end -- cgit v1.2.3 From 83a3da4456a6bd7405abbbf5c9d2aec6c8f180cb Mon Sep 17 00:00:00 2001 From: crimsonwoods Date: Wed, 15 Feb 2017 00:36:02 +0900 Subject: Set default linker 'flags' and 'flags_before_libraries'. --- tasks/toolchains/android.rake | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/tasks/toolchains/android.rake b/tasks/toolchains/android.rake index 0cc60a7a3..0800055c8 100644 --- a/tasks/toolchains/android.rake +++ b/tasks/toolchains/android.rake @@ -232,6 +232,34 @@ Set ANDROID_PLATFORM environment variable or set :platform parameter flags end + def ldflags + flags = [] + + flags += %W(--sysroot="#{sysroot}") + + flags + end + + def ldflags_before_libraries + flags = [] + + case toolchain + when :clang + flags += %W(-gcc-toolchain "#{gcc_toolchain_path.to_s}") + case arch + when /armeabi-v7a/ then flags += %W(-target armv7-none-linux-androideabi) + when /armeabi/ then flags += %W(-target armv5te-none-linux-androideabi) + when /arm64-v8a/ then flags += %W(-target aarch64-none-linux-android) + when /x86_64/ then flags += %W(-target x86_64-none-linux-android) + when /x86/ then flags += %W(-target i686-none-linux-android) + when /mips64/ then flags += %W(-target mips64el-none-linux-android) + when /mips/ then flags += %W(-target mipsel-none-linux-android) + end + end + flags += %W(-no-canonical-prefixes) + + flags + end end MRuby::Toolchain.new(:android) do |conf, params| @@ -246,5 +274,6 @@ MRuby::Toolchain.new(:android) do |conf, params| conf.archiver.command = android.ar conf.linker.command = android.cc - conf.linker.flags = [] + conf.linker.flags = android.ldflags + conf.linker.flags_before_libraries = android.ldflags_before_libraries end -- cgit v1.2.3 From 838fa69aa318bba76542cea9abcdb9738c6f202f Mon Sep 17 00:00:00 2001 From: crimsonwoods Date: Wed, 15 Feb 2017 00:51:10 +0900 Subject: Add '-Wl,--fix-cortex-a8' linker option for 'armeabi-v7a' architecture. --- tasks/toolchains/android.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/toolchains/android.rake b/tasks/toolchains/android.rake index 0800055c8..eb6c7c2ce 100644 --- a/tasks/toolchains/android.rake +++ b/tasks/toolchains/android.rake @@ -247,7 +247,7 @@ Set ANDROID_PLATFORM environment variable or set :platform parameter when :clang flags += %W(-gcc-toolchain "#{gcc_toolchain_path.to_s}") case arch - when /armeabi-v7a/ then flags += %W(-target armv7-none-linux-androideabi) + when /armeabi-v7a/ then flags += %W(-target armv7-none-linux-androideabi -Wl,--fix-cortex-a8) when /armeabi/ then flags += %W(-target armv5te-none-linux-androideabi) when /arm64-v8a/ then flags += %W(-target aarch64-none-linux-android) when /x86_64/ then flags += %W(-target x86_64-none-linux-android) -- cgit v1.2.3 From a6b1e964a3cb4cc0e09d4ecc89e4fee682f8446c Mon Sep 17 00:00:00 2001 From: crimsonwoods Date: Wed, 15 Feb 2017 02:36:37 +0900 Subject: Modify default cflags. --- tasks/toolchains/android.rake | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/tasks/toolchains/android.rake b/tasks/toolchains/android.rake index eb6c7c2ce..7759a3f9c 100644 --- a/tasks/toolchains/android.rake +++ b/tasks/toolchains/android.rake @@ -203,31 +203,33 @@ Set ANDROID_PLATFORM environment variable or set :platform parameter def cflags flags = [] - flags += %W(-D__android__ --sysroot="#{sysroot}") + flags += %W(-MMD -MP) + flags += %W(-D__android__ -DANDROID --sysroot="#{sysroot}") case toolchain when :gcc - flags += %W(-mandroid) case arch - when /armeabi-v7a/ then flags += %W(-march=armv7-a) - when /armeabi/ then flags += %W(-march=armv5te) - when /arm64-v8a/ then flags += %W(-march=armv8-a) + when /armeabi-v7a/ then flags += %W(-march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp -fpic) + when /armeabi/ then flags += %W(-march=armv5te -mtune=xscale -msoft-float -fpic) + when /arm64-v8a/ then flags += %W(-march=armv8-a -fpic) when /x86_64/ then flags += %W(-march=x86-64) when /x86/ then flags += %W(-march=i686) - when /mips64/ then flags += %W(-march=mips64) - when /mips/ then flags += %W(-march=mips32) + when /mips64/ then flags += %W(-march=mips64r6 -fmessage-length=0 -fpic) + when /mips/ then flags += %W(-march=mips32 -fmessage-length=0 -fpic) end when :clang flags += %W(-gcc-toolchain "#{gcc_toolchain_path.to_s}") case arch - when /armeabi-v7a/ then flags += %W(-target armv7-none-linux-androideabi) - when /armeabi/ then flags += %W(-target armv5te-none-linux-androideabi) - when /arm64-v8a/ then flags += %W(-target aarch64-none-linux-android) - when /x86_64/ then flags += %W(-target x86_64-none-linux-android) - when /x86/ then flags += %W(-target i686-none-linux-android) - when /mips64/ then flags += %W(-target mips64el-none-linux-android) - when /mips/ then flags += %W(-target mipsel-none-linux-android) + when /armeabi-v7a/ then flags += %W(-target armv7-none-linux-androideabi -fpic) + when /armeabi/ then flags += %W(-target armv5te-none-linux-androideabi -fpic) + when /arm64-v8a/ then flags += %W(-target aarch64-none-linux-android -fpic) + when /x86_64/ then flags += %W(-target x86_64-none-linux-android -fPIC) + when /x86/ then flags += %W(-target i686-none-linux-android -fPIC) + when /mips64/ then flags += %W(-target mips64el-none-linux-android -fmessage-length=0 -fpic) + when /mips/ then flags += %W(-target mipsel-none-linux-android -fmessage-length=0 -fpic) end + flags += %W(-Wno-invalid-command-line-argument -Wno-unused-command-line-argument) end + flags += %W(-ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes) flags end -- cgit v1.2.3 From 5395dbfb3a1f424c6adc37b7d73d9def37e9e227 Mon Sep 17 00:00:00 2001 From: crimsonwoods Date: Wed, 15 Feb 2017 03:10:16 +0900 Subject: Add new two build config files. --- examples/targets/build_config_android_arm64-v8a.rb | 26 ++++++++++++++++++++++ examples/targets/build_config_android_armeabi.rb | 26 ++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 examples/targets/build_config_android_arm64-v8a.rb create mode 100644 examples/targets/build_config_android_armeabi.rb diff --git a/examples/targets/build_config_android_arm64-v8a.rb b/examples/targets/build_config_android_arm64-v8a.rb new file mode 100644 index 000000000..6188c13ec --- /dev/null +++ b/examples/targets/build_config_android_arm64-v8a.rb @@ -0,0 +1,26 @@ +MRuby::Build.new do |conf| + + # Gets set by the VS command prompts. + if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] + toolchain :visualcpp + else + toolchain :gcc + end + + enable_debug + + # include the default GEMs + conf.gembox 'default' +end + +# Requires Android NDK r13 or later. +MRuby::CrossBuild.new('android-arm64-v8a') do |conf| + params = { + :arch => 'arm64-v8a', + :platform => 'android-24', + :toolchain => :clang, + } + toolchain :android, params + + conf.gembox 'default' +end diff --git a/examples/targets/build_config_android_armeabi.rb b/examples/targets/build_config_android_armeabi.rb new file mode 100644 index 000000000..b7eb33a92 --- /dev/null +++ b/examples/targets/build_config_android_armeabi.rb @@ -0,0 +1,26 @@ +MRuby::Build.new do |conf| + + # Gets set by the VS command prompts. + if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] + toolchain :visualcpp + else + toolchain :gcc + end + + enable_debug + + # include the default GEMs + conf.gembox 'default' +end + +# Requires Android NDK r13 or later. +MRuby::CrossBuild.new('android-armeabi') do |conf| + params = { + :arch => 'armeabi', + :platform => 'android-24', + :toolchain => :clang, + } + toolchain :android, params + + conf.gembox 'default' +end -- cgit v1.2.3 From 04296925ac81537e029af46ed7622471d8374ce8 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 09:24:35 +0900 Subject: Use mrb_funcall_argv() instead of mrb_funcall() --- src/hash.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/hash.c b/src/hash.c index b7bd648c0..d15faa206 100644 --- a/src/hash.c +++ b/src/hash.c @@ -167,6 +167,7 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) { khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; + mrb_sym mid; if (h) { k = kh_get(ht, mrb, h, key); @@ -174,11 +175,12 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) return kh_value(h, k).v; } - if (mrb_func_basic_p(mrb, hash, mrb_intern_lit(mrb, "default"), mrb_hash_default)) { + mid = mrb_intern_lit(mrb, "default"); + if (mrb_func_basic_p(mrb, hash, mid, mrb_hash_default)) { return hash_default(mrb, hash, key); } /* xxx mrb_funcall_tailcall(mrb, hash, "default", 1, key); */ - return mrb_funcall(mrb, hash, "default", 1, key); + return mrb_funcall_argv(mrb, hash, mid, 1, &key); } MRB_API mrb_value -- cgit v1.2.3 From dd24f9f5cc6cc878ae00cf96ce08ae1486d8c0cb Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 09:25:09 +0900 Subject: Avoid calling hook methods if they are not overridden. --- src/class.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/class.c b/src/class.c index 81b312fd0..84cc08a10 100644 --- a/src/class.c +++ b/src/class.c @@ -240,12 +240,22 @@ mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super) return mrb_define_class_id(mrb, mrb_intern_cstr(mrb, name), super); } +static mrb_value mrb_bob_init(mrb_state *mrb, mrb_value cv); + static void mrb_class_inherited(mrb_state *mrb, struct RClass *super, struct RClass *klass) { + mrb_value s; + mrb_sym mid; + if (!super) super = mrb->object_class; - mrb_funcall(mrb, mrb_obj_value(super), "inherited", 1, mrb_obj_value(klass)); + s = mrb_obj_value(super); + mid = mrb_intern_lit(mrb, "inherited"); + if (!mrb_func_basic_p(mrb, s, mid, mrb_bob_init)) { + mrb_value c = mrb_obj_value(klass); + mrb_funcall_argv(mrb, mrb_obj_value(super), mid, 1, &c); + } } MRB_API struct RClass* @@ -1407,10 +1417,13 @@ MRB_API mrb_value mrb_obj_new(mrb_state *mrb, struct RClass *c, mrb_int argc, const mrb_value *argv) { mrb_value obj; + mrb_sym mid; obj = mrb_instance_alloc(mrb, mrb_obj_value(c)); - mrb_funcall_argv(mrb, obj, mrb_intern_lit(mrb, "initialize"), argc, argv); - + mid = mrb_intern_lit(mrb, "initialize"); + if (!mrb_func_basic_p(mrb, obj, mid, mrb_bob_init)) { + mrb_funcall_argv(mrb, obj, mid, argc, argv); + } return obj; } @@ -1432,13 +1445,17 @@ mrb_class_new_class(mrb_state *mrb, mrb_value cv) mrb_int n; mrb_value super, blk; mrb_value new_class; + mrb_sym mid; n = mrb_get_args(mrb, "|C&", &super, &blk); if (n == 0) { super = mrb_obj_value(mrb->object_class); } new_class = mrb_obj_value(mrb_class_new(mrb, mrb_class_ptr(super))); - mrb_funcall_with_block(mrb, new_class, mrb_intern_lit(mrb, "initialize"), n, &super, blk); + mid = mrb_intern_lit(mrb, "initialize"); + if (!mrb_func_basic_p(mrb, new_class, mid, mrb_bob_init)) { + mrb_funcall_with_block(mrb, new_class, mid, n, &super, blk); + } mrb_class_inherited(mrb, mrb_class_ptr(super), mrb_class_ptr(new_class)); return new_class; } -- cgit v1.2.3 From 8efa7b00df2842eaff31cdabc95651a856e40549 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 11:59:47 +0900 Subject: Preallocate SystemStackError; ref #3421 --- include/mruby.h | 2 +- src/backtrace.c | 2 +- src/error.c | 5 +++-- src/gc.c | 1 + src/vm.c | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/mruby.h b/include/mruby.h index 6950cf904..8adce289b 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -221,6 +221,7 @@ typedef struct mrb_state { struct RClass *eException_class; struct RClass *eStandardError_class; struct RObject *nomem_err; /* pre-allocated NoMemoryError */ + struct RObject *stack_err; /* pre-allocated SysStackError */ #ifdef MRB_GC_FIXED_ARENA struct RObject *arena_err; /* pre-allocated arena overfow error */ #endif @@ -1110,7 +1111,6 @@ MRB_API void mrb_print_error(mrb_state *mrb); #define E_SYNTAX_ERROR (mrb_exc_get(mrb, "SyntaxError")) #define E_LOCALJUMP_ERROR (mrb_exc_get(mrb, "LocalJumpError")) #define E_REGEXP_ERROR (mrb_exc_get(mrb, "RegexpError")) -#define E_SYSSTACK_ERROR (mrb_exc_get(mrb, "SystemStackError")) #define E_NOTIMP_ERROR (mrb_exc_get(mrb, "NotImplementedError")) #define E_FLOATDOMAIN_ERROR (mrb_exc_get(mrb, "FloatDomainError")) diff --git a/src/backtrace.c b/src/backtrace.c index 051d5d4e0..529b0b1c9 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -263,7 +263,7 @@ mrb_print_backtrace(mrb_state *mrb) { mrb_value backtrace; - if (!mrb->exc || mrb_obj_is_kind_of(mrb, mrb_obj_value(mrb->exc), E_SYSSTACK_ERROR)) { + if (!mrb->exc) { return; } diff --git a/src/error.c b/src/error.c index a71ee548f..7916ca65b 100644 --- a/src/error.c +++ b/src/error.c @@ -532,7 +532,7 @@ mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, char const* fmt, void mrb_init_exception(mrb_state *mrb) { - struct RClass *exception, *runtime_error, *script_error; + struct RClass *exception, *runtime_error, *script_error, *stack_error; mrb->eException_class = exception = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */ MRB_SET_INSTANCE_TT(exception, MRB_TT_EXCEPTION); @@ -553,5 +553,6 @@ mrb_init_exception(mrb_state *mrb) #endif script_error = mrb_define_class(mrb, "ScriptError", mrb->eException_class); /* 15.2.37 */ mrb_define_class(mrb, "SyntaxError", script_error); /* 15.2.38 */ - mrb_define_class(mrb, "SystemStackError", exception); + stack_error = mrb_define_class(mrb, "SystemStackError", exception); + mrb->stack_err = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, stack_error, "stack level too deep")); } diff --git a/src/gc.c b/src/gc.c index 1608dbcb2..63eab8e00 100644 --- a/src/gc.c +++ b/src/gc.c @@ -865,6 +865,7 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc) } /* mark pre-allocated exception */ mrb_gc_mark(mrb, (struct RBasic*)mrb->nomem_err); + mrb_gc_mark(mrb, (struct RBasic*)mrb->stack_err); #ifdef MRB_GC_FIXED_ARENA mrb_gc_mark(mrb, (struct RBasic*)mrb->arena_err); #endif diff --git a/src/vm.c b/src/vm.c index 8bb446fa9..91612a0da 100644 --- a/src/vm.c +++ b/src/vm.c @@ -162,7 +162,7 @@ stack_extend_alloc(mrb_state *mrb, int room, int keep) to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */ if (size > MRB_STACK_MAX) { init_new_stack_space(mrb, room, keep); - mrb_raise(mrb, E_SYSSTACK_ERROR, "stack level too deep. (limit=" MRB_STRINGIZE(MRB_STACK_MAX) ")"); + mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err)); } } -- cgit v1.2.3 From 1e57fefbcf1ab327113699eebf2b08d9ec450dfe Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 12:01:52 +0900 Subject: Do not funcall() Exception#set_backtrace from runtime. This change reduce flexibility but makes mruby simpler and faster. --- src/error.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/error.c b/src/error.c index 7916ca65b..3fa18fcb3 100644 --- a/src/error.c +++ b/src/error.c @@ -202,12 +202,9 @@ exc_get_backtrace(mrb_state *mrb, mrb_value exc) return backtrace; } -static mrb_value -exc_set_backtrace(mrb_state *mrb, mrb_value exc) +static void +set_backtrace(mrb_state *mrb, mrb_value exc, mrb_value backtrace) { - mrb_value backtrace; - - mrb_get_args(mrb, "o", &backtrace); if (!mrb_array_p(backtrace)) { type_err: mrb_raise(mrb, E_TYPE_ERROR, "backtrace must be Array of String"); @@ -222,7 +219,15 @@ exc_set_backtrace(mrb_state *mrb, mrb_value exc) } } mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "backtrace"), backtrace); +} +static mrb_value +exc_set_backtrace(mrb_state *mrb, mrb_value exc) +{ + mrb_value backtrace; + + mrb_get_args(mrb, "o", &backtrace); + set_backtrace(mrb, exc, backtrace); return backtrace; } @@ -253,12 +258,6 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc) } } -static void -set_backtrace(mrb_state *mrb, mrb_value info, mrb_value bt) -{ - mrb_funcall(mrb, info, "set_backtrace", 1, bt); -} - static mrb_bool have_backtrace(mrb_state *mrb, struct RObject *exc) { -- cgit v1.2.3 From 1e5b5b14d7468ca4fedaa9ba1c9dba0ff67d7ea8 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 12:06:32 +0900 Subject: Prohibit too deep `mrb_funcall()` recursion; ref #3421 `mrb_funcall()` recursion can cause stack overflow easily, so recursion depth is now limited to MRB_FUNCALL_DEPTH_MAX, which default value is 512. --- src/vm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/vm.c b/src/vm.c index 91612a0da..96a9966a2 100644 --- a/src/vm.c +++ b/src/vm.c @@ -40,6 +40,11 @@ void abort(void); #define MRB_STACK_GROWTH 128 #endif +/* Maximum mrb_funcall() depth. Should be set lower on memory constrained systems. */ +#ifndef MRB_FUNCALL_DEPTH_MAX +#define MRB_FUNCALL_DEPTH_MAX 512 +#endif + /* Maximum stack depth. Should be set lower on memory constrained systems. The value below allows about 60000 recursive calls in the simplest case. */ #ifndef MRB_STACK_MAX @@ -386,6 +391,9 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc undef = mid; argc++; } + if (mrb->c->ci - mrb->c->cibase > MRB_FUNCALL_DEPTH_MAX) { + mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err)); + } ci = cipush(mrb); ci->mid = mid; ci->proc = p; -- 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(-) 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 From 8b4bd3158b365cd1baddc4e9f9e5f770717022cf Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 13:07:53 +0900 Subject: Move #== and #!= to BasicObject; ref #3417 --- src/class.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/kernel.c | 52 +--------------------------------------------------- 2 files changed, 52 insertions(+), 51 deletions(-) diff --git a/src/class.c b/src/class.c index 0b7521e61..21a4d3f20 100644 --- a/src/class.c +++ b/src/class.c @@ -1486,6 +1486,55 @@ mrb_bob_not(mrb_state *mrb, mrb_value cv) return mrb_bool_value(!mrb_test(cv)); } +/* 15.3.1.3.1 */ +/* 15.3.1.3.10 */ +/* 15.3.1.3.11 */ +/* + * call-seq: + * obj == other -> true or false + * obj.equal?(other) -> true or false + * obj.eql?(other) -> true or false + * + * Equality---At the Object level, == returns + * true only if obj and other are the + * same object. Typically, this method is overridden in descendant + * classes to provide class-specific meaning. + * + * Unlike ==, the equal? method should never be + * overridden by subclasses: it is used to determine object identity + * (that is, a.equal?(b) iff a is the same + * object as b). + * + * The eql? method returns true if + * obj and anObject have the same value. Used by + * Hash to test members for equality. For objects of + * class Object, eql? is synonymous with + * ==. Subclasses normally continue this tradition, but + * there are exceptions. Numeric types, for example, + * perform type conversion across ==, but not across + * eql?, so: + * + * 1 == 1.0 #=> true + * 1.eql? 1.0 #=> false + */ +mrb_value +mrb_obj_equal_m(mrb_state *mrb, mrb_value self) +{ + mrb_value arg; + + mrb_get_args(mrb, "o", &arg); + return mrb_bool_value(mrb_obj_equal(mrb, self, arg)); +} + +static mrb_value +mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self) +{ + mrb_value arg; + + mrb_get_args(mrb, "o", &arg); + return mrb_bool_value(!mrb_equal(mrb, self, arg)); +} + MRB_API mrb_bool mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid) { @@ -2235,6 +2284,8 @@ 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, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */ + mrb_define_method(mrb, bob, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(1)); 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 fd00d0484..e21a99352 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -66,55 +66,6 @@ mrb_obj_inspect(mrb_state *mrb, mrb_value obj) return mrb_any_to_s(mrb, obj); } -/* 15.3.1.3.1 */ -/* 15.3.1.3.10 */ -/* 15.3.1.3.11 */ -/* - * call-seq: - * obj == other -> true or false - * obj.equal?(other) -> true or false - * obj.eql?(other) -> true or false - * - * Equality---At the Object level, == returns - * true only if obj and other are the - * same object. Typically, this method is overridden in descendant - * classes to provide class-specific meaning. - * - * Unlike ==, the equal? method should never be - * overridden by subclasses: it is used to determine object identity - * (that is, a.equal?(b) iff a is the same - * object as b). - * - * The eql? method returns true if - * obj and anObject have the same value. Used by - * Hash to test members for equality. For objects of - * class Object, eql? is synonymous with - * ==. Subclasses normally continue this tradition, but - * there are exceptions. Numeric types, for example, - * perform type conversion across ==, but not across - * eql?, so: - * - * 1 == 1.0 #=> true - * 1.eql? 1.0 #=> false - */ -static mrb_value -mrb_obj_equal_m(mrb_state *mrb, mrb_value self) -{ - mrb_value arg; - - mrb_get_args(mrb, "o", &arg); - return mrb_bool_value(mrb_obj_equal(mrb, self, arg)); -} - -static mrb_value -mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self) -{ - mrb_value arg; - - mrb_get_args(mrb, "o", &arg); - return mrb_bool_value(!mrb_equal(mrb, self, arg)); -} - /* 15.3.1.3.2 */ /* * call-seq: @@ -1227,6 +1178,7 @@ mrb_local_variables(mrb_state *mrb, mrb_value self) return mrb_hash_keys(mrb, vars); } +mrb_value mrb_obj_equal_m(mrb_state *mrb, mrb_value); void mrb_init_kernel(mrb_state *mrb) { @@ -1242,8 +1194,6 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "singleton_class", mrb_singleton_class, MRB_ARGS_NONE()); - mrb_define_method(mrb, krn, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */ - mrb_define_method(mrb, krn, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(1)); mrb_define_method(mrb, krn, "===", mrb_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.2 */ mrb_define_method(mrb, krn, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.3 */ mrb_define_method(mrb, krn, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.4 */ -- cgit v1.2.3 From 3dbda9178834a4e55d884c97677ed2ecf46c2289 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 13:12:05 +0900 Subject: Move #__send__ to BasicObject; ref #3417 --- src/class.c | 1 + src/kernel.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class.c b/src/class.c index 21a4d3f20..086833eaf 100644 --- a/src/class.c +++ b/src/class.c @@ -2286,6 +2286,7 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, bob, "!", mrb_bob_not, MRB_ARGS_NONE()); mrb_define_method(mrb, bob, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */ mrb_define_method(mrb, bob, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, bob, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.4 */ 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 e21a99352..95ebcfbd8 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -1196,7 +1196,6 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "===", mrb_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.2 */ mrb_define_method(mrb, krn, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.3 */ - mrb_define_method(mrb, krn, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.4 */ mrb_define_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.6 */ mrb_define_method(mrb, krn, "class", mrb_obj_class_m, MRB_ARGS_NONE()); /* 15.3.1.3.7 */ mrb_define_method(mrb, krn, "clone", mrb_obj_clone, MRB_ARGS_NONE()); /* 15.3.1.3.8 */ -- cgit v1.2.3 From 612d636b77edd7c0969e8850583aefd895638284 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 13:15:58 +0900 Subject: Move #instance_eval to BasicObject; ref #3417 --- src/class.c | 4 ++++ src/kernel.c | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/class.c b/src/class.c index 086833eaf..f3146ca15 100644 --- a/src/class.c +++ b/src/class.c @@ -2245,6 +2245,9 @@ mrb_mod_module_function(mrb_state *mrb, mrb_value mod) return mod; } +/* implementation of instance_eval */ +mrb_value mrb_obj_instance_eval(mrb_state*, mrb_value); + void mrb_init_class(mrb_state *mrb) { @@ -2287,6 +2290,7 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, bob, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */ mrb_define_method(mrb, bob, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(1)); mrb_define_method(mrb, bob, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.4 */ + mrb_define_method(mrb, bob, "instance_eval", mrb_obj_instance_eval, MRB_ARGS_ANY()); /* 15.3.1.3.18 */ 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 95ebcfbd8..04bcbe6c2 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -489,9 +489,6 @@ mrb_obj_init_copy(mrb_state *mrb, mrb_value self) } -/* implementation of instance_eval */ -mrb_value mrb_obj_instance_eval(mrb_state*, mrb_value); - MRB_API mrb_bool mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c) { @@ -1209,7 +1206,6 @@ mrb_init_kernel(mrb_state *mrb) 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 */ mrb_define_method(mrb, krn, "inspect", mrb_obj_inspect, MRB_ARGS_NONE()); /* 15.3.1.3.17 */ - mrb_define_method(mrb, krn, "instance_eval", mrb_obj_instance_eval, MRB_ARGS_ANY()); /* 15.3.1.3.18 */ mrb_define_method(mrb, krn, "instance_of?", obj_is_instance_of, MRB_ARGS_REQ(1)); /* 15.3.1.3.19 */ mrb_define_method(mrb, krn, "instance_variable_defined?", mrb_obj_ivar_defined, MRB_ARGS_REQ(1)); /* 15.3.1.3.20 */ mrb_define_method(mrb, krn, "instance_variable_get", mrb_obj_ivar_get, MRB_ARGS_REQ(1)); /* 15.3.1.3.21 */ -- cgit v1.2.3 From 517e9313bf6e6d4697095a9257598915ac857ff3 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 13:19:21 +0900 Subject: Move #__id__ to BasicObject; ref #3417 --- src/class.c | 3 +++ src/kernel.c | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/class.c b/src/class.c index f3146ca15..0922b3cff 100644 --- a/src/class.c +++ b/src/class.c @@ -2245,6 +2245,8 @@ mrb_mod_module_function(mrb_state *mrb, mrb_value mod) return mod; } +/* implementation of __id__ */ +mrb_value mrb_obj_id_m(mrb_state *mrb, mrb_value self); /* implementation of instance_eval */ mrb_value mrb_obj_instance_eval(mrb_state*, mrb_value); @@ -2289,6 +2291,7 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, bob, "!", mrb_bob_not, MRB_ARGS_NONE()); mrb_define_method(mrb, bob, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */ mrb_define_method(mrb, bob, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, bob, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.3 */ mrb_define_method(mrb, bob, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.4 */ mrb_define_method(mrb, bob, "instance_eval", mrb_obj_instance_eval, MRB_ARGS_ANY()); /* 15.3.1.3.18 */ diff --git a/src/kernel.c b/src/kernel.c index 04bcbe6c2..6cb2e3ad5 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -101,7 +101,7 @@ mrb_equal_m(mrb_state *mrb, mrb_value self) * :name notation, which returns the symbol id of * name. Replaces the deprecated Object#id. */ -static mrb_value +mrb_value mrb_obj_id_m(mrb_state *mrb, mrb_value self) { return mrb_fixnum_value(mrb_obj_id(self)); @@ -1192,7 +1192,6 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "singleton_class", mrb_singleton_class, MRB_ARGS_NONE()); mrb_define_method(mrb, krn, "===", mrb_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.2 */ - mrb_define_method(mrb, krn, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.3 */ mrb_define_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.6 */ mrb_define_method(mrb, krn, "class", mrb_obj_class_m, MRB_ARGS_NONE()); /* 15.3.1.3.7 */ mrb_define_method(mrb, krn, "clone", mrb_obj_clone, MRB_ARGS_NONE()); /* 15.3.1.3.8 */ -- cgit v1.2.3 From b165708c8deba00685f9a27926c554aaa7f3b0fb Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 13:24:03 +0900 Subject: Move #instance_exec to Kernel module CRuby defines #instance_exec in BasicObject, but we don't. It's a small incompatibility that isn't worth accomplish at the price of implementation complexity. --- mrbgems/mruby-object-ext/src/object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgems/mruby-object-ext/src/object.c b/mrbgems/mruby-object-ext/src/object.c index 3eba95633..e4fe328e9 100644 --- a/mrbgems/mruby-object-ext/src/object.c +++ b/mrbgems/mruby-object-ext/src/object.c @@ -96,7 +96,7 @@ mrb_mruby_object_ext_gem_init(mrb_state* mrb) mrb_define_method(mrb, n, "to_f", nil_to_f, MRB_ARGS_NONE()); mrb_define_method(mrb, n, "to_i", nil_to_i, MRB_ARGS_NONE()); - mrb_define_method(mrb, mrb->object_class, "instance_exec", mrb_obj_instance_exec, MRB_ARGS_ANY() | MRB_ARGS_BLOCK()); + mrb_define_method(mrb, mrb->kernel_module, "instance_exec", mrb_obj_instance_exec, MRB_ARGS_ANY() | MRB_ARGS_BLOCK()); } void -- cgit v1.2.3