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(-) (limited to 'mrbgems') 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(+) (limited to 'mrbgems') 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(+) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 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 (limited to 'mrbgems') 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 (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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 (limited to 'mrbgems') 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 (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(+) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(+) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 a8b8abbd826b60b6313baef5635acd41e6d8f716 Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Thu, 24 Nov 2016 12:48:41 +0100 Subject: Fixed float tolerance in tests when MRB_USE_FLOAT is set --- mrbgems/mruby-test/driver.c | 6 ++++++ test/assert.rb | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 73e4f069becaf69707b990d658b34155f8973508 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Fri, 18 Nov 2016 16:17:40 -0500 Subject: Fix nested empty heredoc causing segfault As reported by https://hackerone.com/jpenalbae --- mrbgems/mruby-compiler/core/codegen.c | 6 +++++- mrbgems/mruby-compiler/core/parse.y | 2 +- test/t/codegen.rb | 10 ++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 test/t/codegen.rb (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 (limited to 'mrbgems') 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 12539825773ddb13fac38091d13341b816ac23fa Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 14 Nov 2016 15:07:07 -0500 Subject: Fix codegen issue causing misaligned register Reported by https://hackerone.com/haquaman --- mrbgems/mruby-compiler/core/codegen.c | 2 ++ test/t/codegen.rb | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 test/t/codegen.rb (limited to 'mrbgems') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 0c84dd558..75adbefdd 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2024,6 +2024,7 @@ codegen(codegen_scope *s, node *tree, int val) } genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc)); } + if (val) push(); break; case NODE_RETRY: @@ -2058,6 +2059,7 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc)); } } + if (val) push(); } break; diff --git a/test/t/codegen.rb b/test/t/codegen.rb new file mode 100644 index 000000000..89ad94bae --- /dev/null +++ b/test/t/codegen.rb @@ -0,0 +1,20 @@ +## +# Codegen tests + +assert('codegen absorbs arguments to redo and retry if they are the argument of a call') do + assert_nothing_raised do + a=*"1", case nil + when 1 + redo | + 1 + end + end + + assert_nothing_raised do + a=*"1", case nil + when 1 + retry | + 1 + end + end +end -- cgit v1.2.3 From 71641bbf732ab8cbadf8a07e20b2a939b0e3b82b Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 14 Nov 2016 17:28:18 -0500 Subject: Fix segfault caused by empty condition in ternary Reported by https://hackerone.com/jpenalbae --- mrbgems/mruby-compiler/core/codegen.c | 4 ++++ test/t/codegen.rb | 6 ++++++ 2 files changed, 10 insertions(+) create mode 100644 test/t/codegen.rb (limited to 'mrbgems') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 0c84dd558..71b1dcc6f 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1362,6 +1362,10 @@ codegen(codegen_scope *s, node *tree, int val) int pos1, pos2; node *e = tree->cdr->cdr->car; + if (!tree->car) { + codegen(s, e, val); + return; + } switch ((intptr_t)tree->car->car) { case NODE_TRUE: case NODE_INT: diff --git a/test/t/codegen.rb b/test/t/codegen.rb new file mode 100644 index 000000000..99d6dbe66 --- /dev/null +++ b/test/t/codegen.rb @@ -0,0 +1,6 @@ +## +# Codegen tests + +assert('empty condition in ternary expression parses correctly') do + assert_equal () ? 1 : 2, 2 +end -- cgit v1.2.3 From 1ec5994377b45b0299a9c4e6e7ab275792d81bc9 Mon Sep 17 00:00:00 2001 From: Francois Chagnon Date: Mon, 14 Nov 2016 16:49:45 -0500 Subject: Fix calling .arity on Proc with undefined `initialize` Reported by @bouk --- mrbgems/mruby-proc-ext/src/proc.c | 3 +++ mrbgems/mruby-proc-ext/test/proc.rb | 11 +++++++++++ src/proc.c | 15 ++++++++------- test/t/proc.rb | 11 +++++++++++ 4 files changed, 33 insertions(+), 7 deletions(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 (limited to 'mrbgems') 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 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(+) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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(+) (limited to 'mrbgems') 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 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(+) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 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(+) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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(+) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 fe362c1f2649c9c502d9a5998ef8c4c94893f3ea Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Thu, 24 Nov 2016 13:31:47 -0500 Subject: Fix segfault when using result of rest assignment Reported by https://hackerone.com/haquaman --- mrbgems/mruby-compiler/core/codegen.c | 4 +++- test/t/codegen.rb | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(+) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 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(+) (limited to 'mrbgems') 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(+) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 c8da3c4df4f8cb6f6d00c70e75606c59f9888509 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Wed, 7 Dec 2016 11:22:30 -0500 Subject: Fix segfault when undef is called with exactly 127 arguments The issue is that when there are more than 126 arguments an array needs to be created to pass the arguments on with. Reported by https://hackerone.com/revskills --- mrbgems/mruby-compiler/core/codegen.c | 22 ++++++++++++++++++++-- test/t/codegen.rb | 10 ++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index b2cd12225..3cfd99d41 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2560,13 +2560,31 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_A(OP_TCLASS, cursp())); push(); while (t) { - int symbol = new_msym(s, sym(t->car)); + int symbol; + if (num >= CALL_MAXARGS - 1) { + pop_n(num); + genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), num)); + while (t) { + symbol = new_msym(s, sym(t->car)); + push(); + genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol)); + pop(); + genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1)); + t = t->cdr; + } + num = CALL_MAXARGS; + break; + } + symbol = new_msym(s, sym(t->car)); genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol)); push(); t = t->cdr; num++; } - pop_n(num + 1); + pop(); + if (num < CALL_MAXARGS) { + pop_n(num); + } genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num)); if (val) { push(); diff --git a/test/t/codegen.rb b/test/t/codegen.rb index bb0f5c306..3058a7fbc 100644 --- a/test/t/codegen.rb +++ b/test/t/codegen.rb @@ -63,3 +63,13 @@ assert('splat in case splat') do assert_equal [1], a end + +assert('undef with 127 or more arguments') do + assert_raise NameError do + undef + a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, + a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, + a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, + a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a + end +end -- cgit v1.2.3 From 1264219832aeff2630f47d4abb9bee6d013c3e75 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Tue, 15 Nov 2016 11:13:38 -0500 Subject: Fix segfault in gen_values with NOVAL and more than 127 args --- mrbgems/mruby-compiler/core/codegen.c | 2 -- test/t/codegen.rb | 8 ++++++++ 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'mrbgems') 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(+) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 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(+) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 3cba13c249457cfb318c9d7d4456d99003442139 Mon Sep 17 00:00:00 2001 From: ksss Date: Wed, 21 Dec 2016 15:17:05 +0900 Subject: Proc shouldn't have `initialize` method Fix #3356 --- mrbgems/mruby-proc-ext/test/proc.rb | 11 ----------- src/proc.c | 12 ++++++------ test/t/proc.rb | 27 --------------------------- 3 files changed, 6 insertions(+), 44 deletions(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 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(+) (limited to 'mrbgems') 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 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(+) (limited to 'mrbgems') 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(+) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(+) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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(+) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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(+) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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(+) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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 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(-) (limited to 'mrbgems') 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