From c09d250ca148c0efc0167d55885bd20da87b43f7 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 19 Sep 2018 20:53:32 +0900 Subject: Remove implicit conversion using `to_int` method. The ISO standard does not include implicit type conversion using `to_int`. This implicit conversion often causes vulnerability. There will be no more attacks like #4120. In addition, we have added internal convenience method `__to_int` which does type check and conversion (from floats). --- mrbgems/mruby-kernel-ext/src/kernel.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'mrbgems/mruby-kernel-ext/src') diff --git a/mrbgems/mruby-kernel-ext/src/kernel.c b/mrbgems/mruby-kernel-ext/src/kernel.c index 32d86376a..a60e9a210 100644 --- a/mrbgems/mruby-kernel-ext/src/kernel.c +++ b/mrbgems/mruby-kernel-ext/src/kernel.c @@ -93,9 +93,8 @@ mrb_f_method(mrb_state *mrb, mrb_value self) * (0, 0b, and 0x) are honored. * In any case, strings should be strictly conformed to numeric * representation. This behavior is different from that of - * String#to_i. Non string values will be converted using - * to_int, and to_i. Passing nil - * raises a TypeError. + * String#to_i. Non string values will be treated as integers. + * Passing nil raises a TypeError. * * Integer(123.999) #=> 123 * Integer("0x1a") #=> 26 -- cgit v1.2.3 From e207d5af43e9d6e09679e9aee9bf00a843528e0e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 19 Sep 2018 21:51:53 +0900 Subject: Remove implicit conversion using `to_str` method. We have added internal convenience method `__to_str` which does string type check. --- include/mruby.h | 5 +--- mrbgems/mruby-io/src/file.c | 2 +- mrbgems/mruby-kernel-ext/src/kernel.c | 8 ++----- mrbgems/mruby-string-ext/mrblib/string.rb | 6 ++--- mrbgems/mruby-string-ext/test/string.rb | 11 --------- mrblib/string.rb | 11 ++++----- src/class.c | 9 ++++++- src/kernel.c | 39 +++++-------------------------- src/object.c | 27 +++++++++++++++++++++ src/string.c | 32 ++----------------------- test/t/string.rb | 13 ----------- 11 files changed, 55 insertions(+), 108 deletions(-) (limited to 'mrbgems/mruby-kernel-ext/src') diff --git a/include/mruby.h b/include/mruby.h index ee004c111..ab5d5b167 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -854,10 +854,6 @@ typedef const char *mrb_args_format; /** * Retrieve arguments from mrb_state. * - * When applicable, implicit conversions (such as `to_str`, `to_ary`, `to_hash`) are - * applied to received arguments. - * Used inside a function of mrb_func_t type. - * * @param mrb The current MRuby state. * @param format [mrb_args_format] is a list of format specifiers * @param ... The passing variadic arguments must be a pointer of retrieving type. @@ -1187,6 +1183,7 @@ MRB_API void mrb_gc_unregister(mrb_state *mrb, mrb_value obj); MRB_API mrb_value mrb_to_int(mrb_state *mrb, mrb_value val); #define mrb_int(mrb, val) mrb_fixnum(mrb_to_int(mrb, val)) +MRB_API mrb_value mrb_to_str(mrb_state *mrb, mrb_value val); MRB_API void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t); typedef enum call_type { diff --git a/mrbgems/mruby-io/src/file.c b/mrbgems/mruby-io/src/file.c index e65741061..960f4a4e2 100644 --- a/mrbgems/mruby-io/src/file.c +++ b/mrbgems/mruby-io/src/file.c @@ -115,7 +115,7 @@ mrb_file_s_unlink(mrb_state *mrb, mrb_value obj) mrb_get_args(mrb, "*", &argv, &argc); for (i = 0; i < argc; i++) { const char *utf8_path; - pathv = mrb_convert_type(mrb, argv[i], MRB_TT_STRING, "String", "to_str"); + pathv = mrb_string_type(mrb, argv[i]); utf8_path = mrb_string_value_cstr(mrb, &pathv); path = mrb_locale_from_utf8(utf8_path, -1); if (UNLINK(path) < 0) { diff --git a/mrbgems/mruby-kernel-ext/src/kernel.c b/mrbgems/mruby-kernel-ext/src/kernel.c index a60e9a210..bc2656399 100644 --- a/mrbgems/mruby-kernel-ext/src/kernel.c +++ b/mrbgems/mruby-kernel-ext/src/kernel.c @@ -141,8 +141,7 @@ mrb_f_float(mrb_state *mrb, mrb_value self) * String(arg) -> string * * Returns arg as an String. - * - * First tries to call its to_str method, then its to_s method. + * converted using to_s method. * * String(self) #=> "main" * String(self.class) #=> "Object" @@ -154,10 +153,7 @@ mrb_f_string(mrb_state *mrb, mrb_value self) mrb_value arg, tmp; mrb_get_args(mrb, "o", &arg); - tmp = mrb_check_convert_type(mrb, arg, MRB_TT_STRING, "String", "to_str"); - if (mrb_nil_p(tmp)) { - tmp = mrb_check_convert_type(mrb, arg, MRB_TT_STRING, "String", "to_s"); - } + tmp = mrb_convert_type(mrb, arg, MRB_TT_STRING, "String", "to_s"); return tmp; } diff --git a/mrbgems/mruby-string-ext/mrblib/string.rb b/mrbgems/mruby-string-ext/mrblib/string.rb index 27ca30610..9212d83a5 100644 --- a/mrbgems/mruby-string-ext/mrblib/string.rb +++ b/mrbgems/mruby-string-ext/mrblib/string.rb @@ -12,8 +12,8 @@ class String # String.try_convert(/re/) #=> nil # def self.try_convert(obj) - if obj.respond_to?(:to_str) - obj.to_str + if self === obj + obj else nil end @@ -142,7 +142,7 @@ class String # "abcdef".casecmp("ABCDEF") #=> 0 # def casecmp(str) - self.downcase <=> str.to_str.downcase + self.downcase <=> str.__to_str.downcase rescue NoMethodError nil end diff --git a/mrbgems/mruby-string-ext/test/string.rb b/mrbgems/mruby-string-ext/test/string.rb index 757b5c50a..024b2cd4b 100644 --- a/mrbgems/mruby-string-ext/test/string.rb +++ b/mrbgems/mruby-string-ext/test/string.rb @@ -114,12 +114,6 @@ assert('String#concat') do assert_equal "Hello World!", "Hello " << "World" << 33 assert_equal "Hello World!", "Hello ".concat("World").concat(33) - o = Object.new - def o.to_str - "to_str" - end - assert_equal "hi to_str", "hi " << o - assert_raise(TypeError) { "".concat(Object.new) } end @@ -128,11 +122,6 @@ assert('String#casecmp') do assert_equal 0, "aBcDeF".casecmp("abcdef") assert_equal(-1, "abcdef".casecmp("abcdefg")) assert_equal 0, "abcdef".casecmp("ABCDEF") - o = Object.new - def o.to_str - "ABCDEF" - end - assert_equal 0, "abcdef".casecmp(o) end assert('String#start_with?') do diff --git a/mrblib/string.rb b/mrblib/string.rb index 07b80b340..397603e9d 100644 --- a/mrblib/string.rb +++ b/mrblib/string.rb @@ -12,7 +12,7 @@ class String def each_line(rs = "\n", &block) return to_enum(:each_line, rs, &block) unless block return block.call(self) if rs.nil? - rs = rs.to_str + rs = rs.__to_str offset = 0 rs_len = rs.length this = dup @@ -67,7 +67,7 @@ class String block = nil end if !replace.nil? || !block - replace = replace.to_str + replace = replace.__to_str end offset = 0 result = [] @@ -129,12 +129,12 @@ class String end pattern, replace = *args - pattern = pattern.to_str + pattern = pattern.__to_str if args.length == 2 && block block = nil end unless block - replace = replace.to_str + replace = replace.__to_str end result = [] this = dup @@ -245,14 +245,13 @@ class String ## # ISO 15.2.10.5.3 def =~(re) - raise TypeError, "type mismatch: String given" if re.respond_to? :to_str re =~ self end ## # ISO 15.2.10.5.27 def match(re, &block) - if re.respond_to? :to_str + if String === re if Object.const_defined?(:Regexp) r = Regexp.new(re) r.match(self, &block) diff --git a/src/class.c b/src/class.c index 76c699881..7d7e6216c 100644 --- a/src/class.c +++ b/src/class.c @@ -504,10 +504,17 @@ check_type(mrb_state *mrb, mrb_value val, enum mrb_vtype t, const char *c, const return tmp; } +#define CHECK_TYPE(mrb, val, t, c) do { \ + if (mrb_type(val) != (t)) {\ + mrb_raisef(mrb, E_TYPE_ERROR, "expected %S", mrb_str_new_lit(mrb, c));\ + }\ +} while (0) + static mrb_value to_str(mrb_state *mrb, mrb_value val) { - return check_type(mrb, val, MRB_TT_STRING, "String", "to_str"); + CHECK_TYPE(mrb, val, MRB_TT_STRING, "String"); + return val; } static mrb_value diff --git a/src/kernel.c b/src/kernel.c index 195594d6b..ce9cd1d44 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -746,6 +746,7 @@ basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub) { return mrb_respond_to(mrb, obj, id); } + /* 15.3.1.3.43 */ /* * call-seq: @@ -765,45 +766,16 @@ basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub) static mrb_value obj_respond_to(mrb_state *mrb, mrb_value self) { - mrb_value mid; mrb_sym id, rtm_id; - mrb_bool priv = FALSE, respond_to_p = TRUE; - - mrb_get_args(mrb, "o|b", &mid, &priv); - - if (mrb_symbol_p(mid)) { - id = mrb_symbol(mid); - } - else { - mrb_value tmp; - if (mrb_string_p(mid)) { - tmp = mrb_check_intern_str(mrb, mid); - } - else { - tmp = mrb_check_string_type(mrb, mid); - if (mrb_nil_p(tmp)) { - tmp = mrb_inspect(mrb, mid); - mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", tmp); - } - tmp = mrb_check_intern_str(mrb, tmp); - } - if (mrb_nil_p(tmp)) { - respond_to_p = FALSE; - } - else { - id = mrb_symbol(tmp); - } - } - - if (respond_to_p) { - respond_to_p = basic_obj_respond_to(mrb, self, id, !priv); - } + mrb_bool priv = FALSE, respond_to_p; + mrb_get_args(mrb, "n|b", &id, &priv); + respond_to_p = basic_obj_respond_to(mrb, self, id, !priv); if (!respond_to_p) { rtm_id = mrb_intern_lit(mrb, "respond_to_missing?"); if (basic_obj_respond_to(mrb, self, rtm_id, !priv)) { mrb_value args[2], v; - args[0] = mid; + args[0] = mrb_symbol_value(id); args[1] = mrb_bool_value(priv); v = mrb_funcall_argv(mrb, self, rtm_id, 2, args); return mrb_bool_value(mrb_bool(v)); @@ -873,6 +845,7 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, MRB_ARGS_NONE()); /* 15.3.1.3.46 */ mrb_define_method(mrb, krn, "__case_eqq", mrb_obj_ceqq, MRB_ARGS_REQ(1)); /* internal */ mrb_define_method(mrb, krn, "__to_int", mrb_to_int, MRB_ARGS_NONE()); /* internal */ + mrb_define_method(mrb, krn, "__to_str", mrb_to_str, MRB_ARGS_NONE()); /* internal */ mrb_define_method(mrb, krn, "class_defined?", mrb_krn_class_defined, MRB_ARGS_REQ(1)); diff --git a/src/object.c b/src/object.c index ba6fa3947..c69866498 100644 --- a/src/object.c +++ b/src/object.c @@ -579,6 +579,33 @@ mrb_Float(mrb_state *mrb, mrb_value val) } #endif +MRB_API mrb_value +mrb_to_str(mrb_state *mrb, mrb_value val) +{ + if (!mrb_string_p(val)) { + mrb_value type = inspect_type(mrb, val); + mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to String", type); + } + return val; +} + +MRB_API mrb_value +mrb_string_type(mrb_state *mrb, mrb_value str) +{ + if (!mrb_string_p(str)) { + mrb_raisef(mrb, E_TYPE_ERROR, "%S cannot be converted to String", + inspect_type(mrb, str)); + } + return str; +} + +MRB_API mrb_value +mrb_check_string_type(mrb_state *mrb, mrb_value str) +{ + if (!mrb_string_p(str)) return mrb_nil_value(); + return str; +} + MRB_API mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj) { diff --git a/src/string.c b/src/string.c index b7abfb762..b6d4ecef0 100644 --- a/src/string.c +++ b/src/string.c @@ -956,15 +956,7 @@ str_eql(mrb_state *mrb, const mrb_value str1, const mrb_value str2) MRB_API mrb_bool mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2) { - if (mrb_immediate_p(str2)) return FALSE; - if (!mrb_string_p(str2)) { - if (mrb_nil_p(str2)) return FALSE; - if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "to_str"))) { - return FALSE; - } - str2 = mrb_funcall(mrb, str2, "to_str", 0); - return mrb_equal(mrb, str2, str1); - } + if (!mrb_string_p(str2)) return FALSE; return str_eql(mrb, str1, str2); } @@ -992,14 +984,8 @@ mrb_str_equal_m(mrb_state *mrb, mrb_value str1) MRB_API mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str) { - mrb_value s; - if (!mrb_string_p(str)) { - s = mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str"); - if (mrb_nil_p(s)) { - s = mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_s"); - } - return s; + return mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_s"); } return str; } @@ -1714,18 +1700,6 @@ mrb_ptr_to_str(mrb_state *mrb, void *p) return mrb_obj_value(p_str); } -MRB_API mrb_value -mrb_string_type(mrb_state *mrb, mrb_value str) -{ - return mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str"); -} - -MRB_API mrb_value -mrb_check_string_type(mrb_state *mrb, mrb_value str) -{ - return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str"); -} - /* 15.2.10.5.30 */ /* * call-seq: @@ -2379,7 +2353,6 @@ mrb_str_to_f(mrb_state *mrb, mrb_value self) /* * call-seq: * str.to_s => str - * str.to_str => str * * Returns the receiver. */ @@ -2783,7 +2756,6 @@ mrb_init_string(mrb_state *mrb) #endif mrb_define_method(mrb, s, "to_i", mrb_str_to_i, MRB_ARGS_ANY()); /* 15.2.10.5.39 */ mrb_define_method(mrb, s, "to_s", mrb_str_to_s, MRB_ARGS_NONE()); /* 15.2.10.5.40 */ - mrb_define_method(mrb, s, "to_str", mrb_str_to_s, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "to_sym", mrb_str_intern, MRB_ARGS_NONE()); /* 15.2.10.5.41 */ mrb_define_method(mrb, s, "upcase", mrb_str_upcase, MRB_ARGS_NONE()); /* 15.2.10.5.42 */ mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.43 */ diff --git a/test/t/string.rb b/test/t/string.rb index e91b915fe..3a1eced16 100644 --- a/test/t/string.rb +++ b/test/t/string.rb @@ -253,19 +253,6 @@ assert('String#chomp!', '15.2.10.5.10') do assert_equal 'abc', e end -assert('String#chomp! uses the correct length') do - class A - def to_str - $s.replace("AA") - "A" - end - end - - $s = "AAA" - $s.chomp!(A.new) - assert_equal $s, "A" -end - assert('String#chop', '15.2.10.5.11') do a = ''.chop b = 'abc'.chop -- cgit v1.2.3 From 747059a718b9c6538891a21df69bad9998c51ad0 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 19 Sep 2018 22:19:55 +0900 Subject: Removed `to_ary` conversion method. --- include/mruby/array.h | 1 + mrbgems/mruby-array-ext/mrblib/array.rb | 11 +---------- mrbgems/mruby-array-ext/test/array.rb | 16 ---------------- mrbgems/mruby-enumerator/mrblib/enumerator.rb | 4 +--- mrbgems/mruby-kernel-ext/src/kernel.c | 9 ++------- src/array.c | 27 +++++---------------------- src/class.c | 3 ++- src/object.c | 17 +++++++++++++++++ 8 files changed, 29 insertions(+), 59 deletions(-) (limited to 'mrbgems/mruby-kernel-ext/src') diff --git a/include/mruby/array.h b/include/mruby/array.h index 6fffe4512..dd280cbc0 100644 --- a/include/mruby/array.h +++ b/include/mruby/array.h @@ -199,6 +199,7 @@ MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val * @param other The array to replace it with. */ MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other); +MRB_API mrb_value mrb_array_type(mrb_state *mrb, mrb_value self); MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self); /* diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb index 7e8e792d4..f94d08765 100644 --- a/mrbgems/mruby-array-ext/mrblib/array.rb +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -1,3 +1,4 @@ +# coding: cp932 class Array ## # call-seq: @@ -757,16 +758,6 @@ class Array nil end - ## - # call-seq: - # ary.to_ary -> ary - # - # Returns +self+. - # - def to_ary - self - end - ## # call-seq: # ary.dig(idx, ...) -> object diff --git a/mrbgems/mruby-array-ext/test/array.rb b/mrbgems/mruby-array-ext/test/array.rb index 2d2d181f8..d0b5bec6d 100644 --- a/mrbgems/mruby-array-ext/test/array.rb +++ b/mrbgems/mruby-array-ext/test/array.rb @@ -323,27 +323,11 @@ 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 } end -assert("Array#to_ary") do - assert_equal [], [].to_ary - assert_equal [1,2,3], [1,2,3].to_ary -end - assert("Array#dig") do h = [[[1]], 0] assert_equal(1, h.dig(0, 0, 0)) diff --git a/mrbgems/mruby-enumerator/mrblib/enumerator.rb b/mrbgems/mruby-enumerator/mrblib/enumerator.rb index 22856a91b..ae692dd12 100644 --- a/mrbgems/mruby-enumerator/mrblib/enumerator.rb +++ b/mrbgems/mruby-enumerator/mrblib/enumerator.rb @@ -621,9 +621,7 @@ module Enumerable # use Enumerator to use infinite sequence def zip(*args, &block) args = args.map do |a| - if a.respond_to?(:to_ary) - a.to_ary.to_enum(:each) - elsif a.respond_to?(:each) + if a.respond_to?(:each) a.to_enum(:each) else raise TypeError, "wrong argument type #{a.class} (must respond to :each)" diff --git a/mrbgems/mruby-kernel-ext/src/kernel.c b/mrbgems/mruby-kernel-ext/src/kernel.c index bc2656399..324753f6e 100644 --- a/mrbgems/mruby-kernel-ext/src/kernel.c +++ b/mrbgems/mruby-kernel-ext/src/kernel.c @@ -161,9 +161,7 @@ mrb_f_string(mrb_state *mrb, mrb_value self) * call-seq: * Array(arg) -> array * - * Returns +arg+ as an Array. - * - * First tries to call Array#to_ary on +arg+, then Array#to_a. + * Returns +arg+ as an Array using to_a method. * * Array(1..5) #=> [1, 2, 3, 4, 5] * @@ -174,10 +172,7 @@ mrb_f_array(mrb_state *mrb, mrb_value self) mrb_value arg, tmp; mrb_get_args(mrb, "o", &arg); - tmp = mrb_check_convert_type(mrb, arg, MRB_TT_ARRAY, "Array", "to_ary"); - if (mrb_nil_p(tmp)) { - tmp = mrb_check_convert_type(mrb, arg, MRB_TT_ARRAY, "Array", "to_a"); - } + tmp = mrb_check_convert_type(mrb, arg, MRB_TT_ARRAY, "Array", "to_a"); if (mrb_nil_p(tmp)) { return mrb_ary_new_from_values(mrb, 1, &arg); } diff --git a/src/array.c b/src/array.c index 0b039a6ec..c218162bc 100644 --- a/src/array.c +++ b/src/array.c @@ -1058,7 +1058,7 @@ mrb_ary_rindex_m(mrb_state *mrb, mrb_value self) MRB_API mrb_value mrb_ary_splat(mrb_state *mrb, mrb_value v) { - mrb_value a, recv_class; + mrb_value a; if (mrb_array_p(v)) { return v; @@ -1069,22 +1069,11 @@ mrb_ary_splat(mrb_state *mrb, mrb_value v) } a = mrb_funcall(mrb, v, "to_a", 0); - if (mrb_array_p(a)) { - return a; - } - else if (mrb_nil_p(a)) { + if (mrb_nil_p(a)) { return mrb_ary_new_from_values(mrb, 1, &v); } - else { - recv_class = mrb_obj_value(mrb_obj_class(mrb, v)); - mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Array (%S#to_a gives %S)", - recv_class, - recv_class, - mrb_obj_value(mrb_obj_class(mrb, a)) - ); - /* not reached */ - return mrb_undef_value(); - } + mrb_array_type(mrb, a); + return a; } static mrb_value @@ -1121,12 +1110,6 @@ mrb_ary_empty_p(mrb_state *mrb, mrb_value self) return mrb_bool_value(ARY_LEN(a) == 0); } -MRB_API mrb_value -mrb_check_array_type(mrb_state *mrb, mrb_value ary) -{ - return mrb_check_convert_type(mrb, ary, MRB_TT_ARRAY, "Array", "to_ary"); -} - MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset) { @@ -1180,7 +1163,7 @@ join_ary(mrb_state *mrb, mrb_value ary, mrb_value sep, mrb_value list) val = tmp; goto str_join; } - tmp = mrb_check_convert_type(mrb, val, MRB_TT_ARRAY, "Array", "to_ary"); + tmp = mrb_check_array_type(mrb, val); if (!mrb_nil_p(tmp)) { val = tmp; goto ary_join; diff --git a/src/class.c b/src/class.c index 7d7e6216c..6eccd7905 100644 --- a/src/class.c +++ b/src/class.c @@ -520,7 +520,8 @@ to_str(mrb_state *mrb, mrb_value val) static mrb_value to_ary(mrb_state *mrb, mrb_value val) { - return check_type(mrb, val, MRB_TT_ARRAY, "Array", "to_ary"); + CHECK_TYPE(mrb, val, MRB_TT_ARRAY, "Array"); + return val; } static mrb_value diff --git a/src/object.c b/src/object.c index c69866498..6e86f162e 100644 --- a/src/object.c +++ b/src/object.c @@ -606,6 +606,23 @@ mrb_check_string_type(mrb_state *mrb, mrb_value str) return str; } +MRB_API mrb_value +mrb_array_type(mrb_state *mrb, mrb_value ary) +{ + if (!mrb_array_p(ary)) { + mrb_raisef(mrb, E_TYPE_ERROR, "%S cannot be converted to Array", + inspect_type(mrb, ary)); + } + return ary; +} + +MRB_API mrb_value +mrb_check_array_type(mrb_state *mrb, mrb_value ary) +{ + if (!mrb_array_p(ary)) return mrb_nil_value(); + return ary; +} + MRB_API mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj) { -- cgit v1.2.3 From cb85fa6787ea9467f81be41570a36b475b7ef061 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 19 Sep 2018 22:53:48 +0900 Subject: Removed `to_hash` conversion method. --- mrbgems/mruby-hash-ext/mrblib/hash.rb | 30 +++++++----------------------- mrbgems/mruby-kernel-ext/src/kernel.c | 20 ++++++-------------- mrbgems/mruby-sprintf/src/sprintf.c | 2 +- mrblib/hash.rb | 14 ++++---------- src/class.c | 15 ++------------- src/hash.c | 28 ---------------------------- src/object.c | 17 +++++++++++++++++ 7 files changed, 37 insertions(+), 89 deletions(-) (limited to 'mrbgems/mruby-kernel-ext/src') diff --git a/mrbgems/mruby-hash-ext/mrblib/hash.rb b/mrbgems/mruby-hash-ext/mrblib/hash.rb index a839ff4a6..604780c46 100644 --- a/mrbgems/mruby-hash-ext/mrblib/hash.rb +++ b/mrbgems/mruby-hash-ext/mrblib/hash.rb @@ -27,9 +27,9 @@ class Hash length = object.length if length == 1 o = object[0] - if o.respond_to?(:to_hash) + if Hash === o h = self.new - object[0].to_hash.each { |k, v| h[k] = v } + o.each { |k, v| h[k] = v } return h elsif o.respond_to?(:to_a) h = self.new @@ -82,7 +82,7 @@ class Hash # def merge!(other, &block) - raise TypeError, "can't convert argument into Hash" unless other.respond_to?(:to_hash) + raise TypeError, "Hash required (#{other.class} given)" unless Hash === other if block other.each_key{|k| self[k] = (self.has_key?(k))? block.call(k, self[k], other[k]): other[k] @@ -310,11 +310,7 @@ class Hash # h1 < h1 #=> false # def <(hash) - begin - hash = hash.to_hash - rescue NoMethodError - raise TypeError, "can't convert #{hash.class} to Hash" - end + raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash size < hash.size and all? {|key, val| hash.key?(key) and hash[key] == val } @@ -334,11 +330,7 @@ class Hash # h1 <= h1 #=> true # def <=(hash) - begin - hash = hash.to_hash - rescue NoMethodError - raise TypeError, "can't convert #{hash.class} to Hash" - end + raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash size <= hash.size and all? {|key, val| hash.key?(key) and hash[key] == val } @@ -358,11 +350,7 @@ class Hash # h1 > h1 #=> false # def >(hash) - begin - hash = hash.to_hash - rescue NoMethodError - raise TypeError, "can't convert #{hash.class} to Hash" - end + raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash size > hash.size and hash.all? {|key, val| key?(key) and self[key] == val } @@ -382,11 +370,7 @@ class Hash # h1 >= h1 #=> true # def >=(hash) - begin - hash = hash.to_hash - rescue NoMethodError - raise TypeError, "can't convert #{hash.class} to Hash" - end + raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash size >= hash.size and hash.all? {|key, val| key?(key) and self[key] == val } diff --git a/mrbgems/mruby-kernel-ext/src/kernel.c b/mrbgems/mruby-kernel-ext/src/kernel.c index 324753f6e..99affbfa4 100644 --- a/mrbgems/mruby-kernel-ext/src/kernel.c +++ b/mrbgems/mruby-kernel-ext/src/kernel.c @@ -184,9 +184,9 @@ mrb_f_array(mrb_state *mrb, mrb_value self) * call-seq: * Hash(arg) -> hash * - * Converts arg to a Hash by calling - * arg.to_hash. Returns an empty Hash when - * arg is nil or []. + * Returns a Hash if arg is a Hash. + * Returns an empty Hash when arg is nil + * or []. * * Hash([]) #=> {} * Hash(nil) #=> {} @@ -197,21 +197,13 @@ mrb_f_array(mrb_state *mrb, mrb_value self) static mrb_value mrb_f_hash(mrb_state *mrb, mrb_value self) { - mrb_value arg, tmp; + mrb_value arg; mrb_get_args(mrb, "o", &arg); - if (mrb_nil_p(arg)) { + if (mrb_nil_p(arg) || (mrb_array_p(arg) && RARRAY_LEN(arg) == 0)) { return mrb_hash_new(mrb); } - tmp = mrb_check_convert_type(mrb, arg, MRB_TT_HASH, "Hash", "to_hash"); - if (mrb_nil_p(tmp)) { - if (mrb_array_p(arg) && RARRAY_LEN(arg) == 0) { - return mrb_hash_new(mrb); - } - mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into Hash", - mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, arg))); - } - return tmp; + return mrb_ensure_hash_type(mrb, arg); } /* diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index 15d7b5464..5a4a7899e 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -233,7 +233,7 @@ get_hash(mrb_state *mrb, mrb_value *hash, mrb_int argc, const mrb_value *argv) if (argc != 2) { mrb_raise(mrb, E_ARGUMENT_ERROR, "one hash required"); } - tmp = mrb_check_convert_type(mrb, argv[1], MRB_TT_HASH, "Hash", "to_hash"); + tmp = mrb_check_hash_type(mrb, argv[1]); if (mrb_nil_p(tmp)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "one hash required"); } diff --git a/mrblib/hash.rb b/mrblib/hash.rb index 96029a230..1cd039c45 100644 --- a/mrblib/hash.rb +++ b/mrblib/hash.rb @@ -12,9 +12,7 @@ class Hash # ISO 15.2.13.4.1 def ==(hash) return true if self.equal?(hash) - begin - hash = hash.to_hash - rescue NoMethodError + unless Hash === hash return false end return false if self.size != hash.size @@ -32,9 +30,7 @@ class Hash # ISO 15.2.13.4.32 (x) def eql?(hash) return true if self.equal?(hash) - begin - hash = hash.to_hash - rescue NoMethodError + unless Hash === hash return false end return false if self.size != hash.size @@ -154,9 +150,8 @@ class Hash # # ISO 15.2.13.4.23 def replace(hash) - raise TypeError, "can't convert argument into Hash" unless hash.respond_to?(:to_hash) + raise TypeError, "Hash required (#{hash.class} given)" unless Hash === hash self.clear - hash = hash.to_hash hash.each_key{|k| self[k] = hash[k] } @@ -179,8 +174,7 @@ class Hash # # ISO 15.2.13.4.22 def merge(other, &block) - raise TypeError, "can't convert argument into Hash" unless other.respond_to?(:to_hash) - other = other.to_hash + raise TypeError, "Hash required (#{other.class} given)" unless Hash === other h = self.dup if block other.each_key{|k| diff --git a/src/class.c b/src/class.c index 6187d5420..b5a492d8f 100644 --- a/src/class.c +++ b/src/class.c @@ -492,18 +492,6 @@ mrb_notimplement_m(mrb_state *mrb, mrb_value self) return mrb_nil_value(); } -static mrb_value -check_type(mrb_state *mrb, mrb_value val, enum mrb_vtype t, const char *c, const char *m) -{ - mrb_value tmp; - - tmp = mrb_check_convert_type(mrb, val, t, c, m); - if (mrb_nil_p(tmp)) { - mrb_raisef(mrb, E_TYPE_ERROR, "expected %S", mrb_str_new_cstr(mrb, c)); - } - return tmp; -} - #define CHECK_TYPE(mrb, val, t, c) do { \ if (mrb_type(val) != (t)) {\ mrb_raisef(mrb, E_TYPE_ERROR, "expected %S", mrb_str_new_lit(mrb, c));\ @@ -527,7 +515,8 @@ to_ary(mrb_state *mrb, mrb_value val) static mrb_value to_hash(mrb_state *mrb, mrb_value val) { - return check_type(mrb, val, MRB_TT_HASH, "Hash", "to_hash"); + CHECK_TYPE(mrb, val, MRB_TT_HASH, "Hash"); + return val; } #define to_sym(mrb, ss) mrb_obj_to_sym(mrb, ss) diff --git a/src/hash.c b/src/hash.c index f6b61f4e1..734f6d9bd 100644 --- a/src/hash.c +++ b/src/hash.c @@ -320,18 +320,6 @@ mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val) return; } -MRB_API mrb_value -mrb_ensure_hash_type(mrb_state *mrb, mrb_value hash) -{ - return mrb_convert_type(mrb, hash, MRB_TT_HASH, "Hash", "to_hash"); -} - -MRB_API mrb_value -mrb_check_hash_type(mrb_state *mrb, mrb_value hash) -{ - return mrb_check_convert_type(mrb, hash, MRB_TT_HASH, "Hash", "to_hash"); -} - MRB_API khash_t(ht)* mrb_hash_tbl(mrb_state *mrb, mrb_value hash) { @@ -787,20 +775,6 @@ mrb_hash_empty_m(mrb_state *mrb, mrb_value self) return mrb_false_value(); } -/* 15.2.13.4.29 (x)*/ -/* - * call-seq: - * hsh.to_hash => hsh - * - * Returns +self+. - */ - -static mrb_value -mrb_hash_to_hash(mrb_state *mrb, mrb_value hash) -{ - return hash; -} - /* 15.2.13.4.19 */ /* * call-seq: @@ -1022,6 +996,4 @@ mrb_init_hash(mrb_state *mrb) mrb_define_method(mrb, h, "store", mrb_hash_aset, MRB_ARGS_REQ(2)); /* 15.2.13.4.26 */ mrb_define_method(mrb, h, "value?", mrb_hash_has_value, MRB_ARGS_REQ(1)); /* 15.2.13.4.27 */ mrb_define_method(mrb, h, "values", mrb_hash_values, MRB_ARGS_NONE()); /* 15.2.13.4.28 */ - - mrb_define_method(mrb, h, "to_hash", mrb_hash_to_hash, MRB_ARGS_NONE()); /* 15.2.13.4.29 (x)*/ } diff --git a/src/object.c b/src/object.c index a105c62f0..66dfa0f97 100644 --- a/src/object.c +++ b/src/object.c @@ -623,6 +623,23 @@ mrb_check_array_type(mrb_state *mrb, mrb_value ary) return ary; } +MRB_API mrb_value +mrb_ensure_hash_type(mrb_state *mrb, mrb_value hash) +{ + if (!mrb_hash_p(hash)) { + mrb_raisef(mrb, E_TYPE_ERROR, "%S cannot be converted to Hash", + inspect_type(mrb, hash)); + } + return hash; +} + +MRB_API mrb_value +mrb_check_hash_type(mrb_state *mrb, mrb_value hash) +{ + if (!mrb_hash_p(hash)) return mrb_nil_value(); + return hash; +} + MRB_API mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj) { -- cgit v1.2.3