From fee9ec61bb9808b5235a78b923a2b8baeebbea8c Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 13 Aug 2018 15:07:10 +0900 Subject: Make `Array.new` to accept both integers and floats. This time we used `Integral` module which is mruby specific. --- mrblib/array.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrblib/array.rb') diff --git a/mrblib/array.rb b/mrblib/array.rb index 334f4e984..13c5d646c 100644 --- a/mrblib/array.rb +++ b/mrblib/array.rb @@ -66,7 +66,7 @@ class Array # # ISO 15.2.12.5.15 def initialize(size=0, obj=nil, &block) - raise TypeError, "expected Integer for 1st argument" unless size.kind_of? Integer + raise TypeError, "expected Integer for 1st argument" unless size.kind_of? Integral raise ArgumentError, "negative array size" if size < 0 self.clear -- cgit v1.2.3 From 91444c47476f8f62723d0bee2684a0817b99e448 Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Thu, 18 Oct 2018 13:07:47 +0900 Subject: replace quicksort with mergesort. --- mrbgems/mruby-enum-ext/mrblib/enum.rb | 4 +- mrblib/array.rb | 84 +++++++++++++++++++++-------------- test/t/array.rb | 6 +++ 3 files changed, 58 insertions(+), 36 deletions(-) (limited to 'mrblib/array.rb') diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb index 6cbacdf9e..ba92decee 100644 --- a/mrbgems/mruby-enum-ext/mrblib/enum.rb +++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb @@ -201,9 +201,7 @@ module Enumerable ary.push([block.call(e), i]) } if ary.size > 1 - ary.__sort_sub__(0, ary.size - 1) do |a,b| - a <=> b - end + ary.sort! end ary.collect{|e,i| orig[i]} end diff --git a/mrblib/array.rb b/mrblib/array.rb index 13c5d646c..ae0868410 100644 --- a/mrblib/array.rb +++ b/mrblib/array.rb @@ -193,43 +193,61 @@ class Array include Enumerable ## - # Quick sort - # left : the beginning of sort region - # right : the end of sort region - def __sort_sub__(left, right, &block) - stack = [ [left, right] ] + # Sort all elements and replace +self+ with these + # elements. + def sort!(&block) + stack = [ [ 0, self.size - 1 ] ] until stack.empty? - left, right = stack.pop - if left < right - i = left - j = right - pivot = self[i + (j - i) / 2] - while true - while ((block)? block.call(self[i], pivot): (self[i] <=> pivot)) < 0 - i += 1 - end - while ((block)? block.call(pivot, self[j]): (pivot <=> self[j])) < 0 - j -= 1 + left, mid, right = stack.pop + if right == nil + right = mid + # sort self[left..right] + if left < right + if left + 1 == right + lval = self[left] + rval = self[right] + if (block&.call(lval, rval) || (lval <=> rval)) > 0 + self[left] = rval + self[right] = lval + end + else + mid = ((left + right + 1) / 2).floor + stack.push [ left, mid, right ] + stack.push [ mid, right ] + stack.push [ left, (mid - 1) ] if left < mid - 1 end - break if (i >= j) - tmp = self[i]; self[i] = self[j]; self[j] = tmp; - i += 1 - j -= 1 end - stack.push [left, i-1] - stack.push [j+1, right] - end - end - end - # private :__sort_sub__ + else + lary = self[left, mid - left] + lsize = lary.size - ## - # Sort all elements and replace +self+ with these - # elements. - def sort!(&block) - size = self.size - if size > 1 - __sort_sub__(0, size - 1, &block) + # The entity sharing between lary and self may cause a large memory + # copy operation in the merge loop below. This harmless operation + # cancels the sharing and provides a huge performance gain. + lary[0] = lary[0] + + # merge + lidx = 0 + ridx = mid + (left..right).each { |i| + if lidx >= lsize + break + elsif ridx > right + self[i, lsize - lidx] = lary[lidx, lsize - lidx] + break + else + lval = lary[lidx] + rval = self[ridx] + if (block&.call(lval, rval) || (lval <=> rval)) <= 0 + self[i] = lval + lidx += 1 + else + self[i] = rval + ridx += 1 + end + end + } + end end self end diff --git a/test/t/array.rb b/test/t/array.rb index ecec39363..53fbdcf1a 100644 --- a/test/t/array.rb +++ b/test/t/array.rb @@ -386,6 +386,12 @@ assert("Array#rindex") do assert_equal 0, $a.rindex(1) end +assert('Array#sort!') do + a = [3, 2, 1] + assert_equal a, a.sort! # sort! returns self. + assert_equal [1, 2, 3], a # it is sorted. +end + assert('Array#freeze') do a = [].freeze assert_raise(RuntimeError) do -- cgit v1.2.3 From 34872e90d44bdde64e18b7774cf09495ec043e24 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 29 Oct 2018 11:55:49 +0900 Subject: Re-implement `Array#_inspect` and `Hash#_inspect` without blocks. To reduce the env object allocation; ref #4143 --- mrblib/array.rb | 11 +++++++++-- mrblib/hash.rb | 13 ++++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'mrblib/array.rb') diff --git a/mrblib/array.rb b/mrblib/array.rb index ae0868410..53d880660 100644 --- a/mrblib/array.rb +++ b/mrblib/array.rb @@ -84,8 +84,15 @@ class Array end def _inspect - return "[]" if self.size == 0 - "["+self.map{|x|x.inspect}.join(", ")+"]" + size = self.size + return "[]" if size == 0 + ary=[] + i=0 + while i" + v._inspect - }.join(", ")+"}" + ary=[] + keys=self.keys + size=keys.size + i=0 + while i" + self[k]._inspect) + i+=1 + end + "{"+ary.join(", ")+"}" end ## # Return the contents of this hash as a string. -- cgit v1.2.3 From afca99a40b8a3415b3a9a0e8fc41c93ddcbb11d8 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). --- include/mruby.h | 1 - mrbgems/mruby-enum-ext/mrblib/enum.rb | 27 +++++-------- mrbgems/mruby-enumerator/mrblib/enumerator.rb | 8 ++-- mrbgems/mruby-enumerator/test/enumerator.rb | 6 --- mrbgems/mruby-kernel-ext/src/kernel.c | 5 +-- mrbgems/mruby-numeric-ext/src/numeric_ext.c | 17 ++++---- mrbgems/mruby-pack/src/pack.c | 6 ++- mrbgems/mruby-random/src/random.c | 12 +++--- mrbgems/mruby-random/test/random.rb | 12 ------ mrbgems/mruby-range-ext/mrblib/range.rb | 5 +-- mrbgems/mruby-string-ext/test/string.rb | 12 ------ mrblib/array.rb | 2 +- src/kernel.c | 2 + src/numeric.c | 4 -- src/object.c | 57 ++++++++------------------- 15 files changed, 51 insertions(+), 125 deletions(-) (limited to 'mrblib/array.rb') diff --git a/include/mruby.h b/include/mruby.h index 8eff31746..33597101a 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -716,7 +716,6 @@ MRB_API mrb_value mrb_notimplement_m(mrb_state*, mrb_value); * @return [mrb_value] The newly duplicated object. */ MRB_API mrb_value mrb_obj_dup(mrb_state *mrb, mrb_value obj); -MRB_API mrb_value mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method); /** * Returns true if obj responds to the given method. If the method was defined for that diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb index ba92decee..fedf8b1ae 100644 --- a/mrbgems/mruby-enum-ext/mrblib/enum.rb +++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb @@ -13,10 +13,9 @@ module Enumerable # a.drop(3) #=> [4, 5, 0] def drop(n) - raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) + n = n.__to_int raise ArgumentError, "attempt to drop negative size" if n < 0 - n = n.to_int ary = [] self.each {|*val| n == 0 ? ary << val.__svalue : n -= 1 } ary @@ -57,8 +56,8 @@ module Enumerable # a.take(3) #=> [1, 2, 3] def take(n) - raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) - i = n.to_int + n = n.__to_int + i = n.to_i raise ArgumentError, "attempt to take negative size" if i < 0 ary = [] return ary if i == 0 @@ -113,12 +112,12 @@ module Enumerable # [8, 9, 10] def each_cons(n, &block) - raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) + n = n.__to_int raise ArgumentError, "invalid size" if n <= 0 return to_enum(:each_cons,n) unless block ary = [] - n = n.to_int + n = n.to_i self.each do |*val| ary.shift if ary.size == n ary << val.__svalue @@ -141,12 +140,12 @@ module Enumerable # [10] def each_slice(n, &block) - raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) + n = n.__to_int raise ArgumentError, "invalid slice size" if n <= 0 return to_enum(:each_slice,n) unless block ary = [] - n = n.to_int + n = n.to_i self.each do |*val| ary << val.__svalue if ary.size == n @@ -223,9 +222,7 @@ module Enumerable end return nil 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 + i = args[0].__to_int raise ArgumentError, "attempt to take negative size" if i < 0 ary = [] return ary if i == 0 @@ -673,13 +670,7 @@ module Enumerable if nv.nil? n = -1 else - unless nv.respond_to?(:to_int) - raise TypeError, "no implicit conversion of #{nv.class} into Integer" - end - n = nv.to_int - unless n.kind_of?(Integer) - raise TypeError, "no implicit conversion of #{nv.class} into Integer" - end + n = nv.__to_int return nil if n <= 0 end diff --git a/mrbgems/mruby-enumerator/mrblib/enumerator.rb b/mrbgems/mruby-enumerator/mrblib/enumerator.rb index dbc7d3004..6dd971f3a 100644 --- a/mrbgems/mruby-enumerator/mrblib/enumerator.rb +++ b/mrbgems/mruby-enumerator/mrblib/enumerator.rb @@ -157,12 +157,10 @@ class Enumerator def with_index(offset=0, &block) return to_enum :with_index, offset unless block - offset = if offset.nil? - 0 - elsif offset.respond_to?(:to_int) - offset.to_int + if offset.nil? + offset = 0 else - raise TypeError, "no implicit conversion of #{offset.class} into Integer" + offset = offset.__to_int end n = offset - 1 diff --git a/mrbgems/mruby-enumerator/test/enumerator.rb b/mrbgems/mruby-enumerator/test/enumerator.rb index ef4970883..f3bd1bdba 100644 --- a/mrbgems/mruby-enumerator/test/enumerator.rb +++ b/mrbgems/mruby-enumerator/test/enumerator.rb @@ -54,12 +54,6 @@ assert 'Enumerator#with_index' do assert_equal [[[1, 10], 20], [[2, 11], 21], [[3, 12], 22]], a end -assert 'Enumerator#with_index nonnum offset' do - s = Object.new - def s.to_int; 1 end - assert_equal([[1,1],[2,2],[3,3]], @obj.to_enum(:foo, 1, 2, 3).with_index(s).to_a) -end - assert 'Enumerator#with_index string offset' do assert_raise(TypeError){ @obj.to_enum(:foo, 1, 2, 3).with_index('1').to_a } end 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 diff --git a/mrbgems/mruby-numeric-ext/src/numeric_ext.c b/mrbgems/mruby-numeric-ext/src/numeric_ext.c index 1d6a07769..cd8bbf187 100644 --- a/mrbgems/mruby-numeric-ext/src/numeric_ext.c +++ b/mrbgems/mruby-numeric-ext/src/numeric_ext.c @@ -2,13 +2,10 @@ #include static inline mrb_int -to_int(mrb_value x) +to_int(mrb_state *mrb, mrb_value x) { - double f; - - if (mrb_fixnum_p(x)) return mrb_fixnum(x); - f = mrb_float(x); - return (mrb_int)f; + x = mrb_to_int(mrb, x); + return mrb_fixnum(x); } /* @@ -28,7 +25,7 @@ mrb_int_chr(mrb_state *mrb, mrb_value x) mrb_int chr; char c; - chr = to_int(x); + chr = to_int(mrb, x); if (chr >= (1 << CHAR_BIT)) { mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", x); } @@ -48,8 +45,8 @@ mrb_int_allbits(mrb_state *mrb, mrb_value self) { mrb_int n, m; - n = to_int(self); mrb_get_args(mrb, "i", &m); + n = to_int(mrb, self); return mrb_bool_value((n & m) == m); } @@ -64,8 +61,8 @@ mrb_int_anybits(mrb_state *mrb, mrb_value self) { mrb_int n, m; - n = to_int(self); mrb_get_args(mrb, "i", &m); + n = to_int(mrb, self); return mrb_bool_value((n & m) != 0); } @@ -80,8 +77,8 @@ mrb_int_nobits(mrb_state *mrb, mrb_value self) { mrb_int n, m; - n = to_int(self); mrb_get_args(mrb, "i", &m); + n = to_int(mrb, self); return mrb_bool_value((n & m) == 0); } diff --git a/mrbgems/mruby-pack/src/pack.c b/mrbgems/mruby-pack/src/pack.c index 796ba4d34..5caf7b62b 100644 --- a/mrbgems/mruby-pack/src/pack.c +++ b/mrbgems/mruby-pack/src/pack.c @@ -1124,14 +1124,16 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary) o = mrb_ary_ref(mrb, ary, aidx); if (type == PACK_TYPE_INTEGER) { o = mrb_to_int(mrb, o); + } #ifndef MRB_WITHOUT_FLOAT - } else if (type == PACK_TYPE_FLOAT) { + else if (type == PACK_TYPE_FLOAT) { if (!mrb_float_p(o)) { mrb_float f = mrb_to_flo(mrb, o); o = mrb_float_value(mrb, f); } + } #endif - } else if (type == PACK_TYPE_STRING) { + else if (type == PACK_TYPE_STRING) { if (!mrb_string_p(o)) { mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into String", mrb_class_path(mrb, mrb_obj_class(mrb, o))); } diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index 5b926a228..68209840a 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -79,12 +79,12 @@ get_opt(mrb_state* mrb) mrb_get_args(mrb, "|o", &arg); if (!mrb_nil_p(arg)) { - arg = mrb_check_convert_type(mrb, arg, MRB_TT_FIXNUM, "Fixnum", "to_int"); - if (mrb_nil_p(arg)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument type"); - } - if (mrb_fixnum(arg) < 0) { - arg = mrb_fixnum_value(0 - mrb_fixnum(arg)); + mrb_int i; + + arg = mrb_to_int(mrb, arg); + i = mrb_fixnum(arg); + if (i < 0) { + arg = mrb_fixnum_value(0 - i); } } return arg; diff --git a/mrbgems/mruby-random/test/random.rb b/mrbgems/mruby-random/test/random.rb index 1c59be3a6..1653ae4a6 100644 --- a/mrbgems/mruby-random/test/random.rb +++ b/mrbgems/mruby-random/test/random.rb @@ -74,15 +74,3 @@ 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 diff --git a/mrbgems/mruby-range-ext/mrblib/range.rb b/mrbgems/mruby-range-ext/mrblib/range.rb index e5d1fb079..de7925ba7 100644 --- a/mrbgems/mruby-range-ext/mrblib/range.rb +++ b/mrbgems/mruby-range-ext/mrblib/range.rb @@ -15,10 +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" 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) + n = nv.__to_int raise ArgumentError, "negative array size (or size too big)" unless 0 <= n ary = [] each do |i| diff --git a/mrbgems/mruby-string-ext/test/string.rb b/mrbgems/mruby-string-ext/test/string.rb index f0f8be6b3..781506949 100644 --- a/mrbgems/mruby-string-ext/test/string.rb +++ b/mrbgems/mruby-string-ext/test/string.rb @@ -31,18 +31,6 @@ 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)) diff --git a/mrblib/array.rb b/mrblib/array.rb index 53d880660..a677b2a1f 100644 --- a/mrblib/array.rb +++ b/mrblib/array.rb @@ -66,7 +66,7 @@ class Array # # ISO 15.2.12.5.15 def initialize(size=0, obj=nil, &block) - raise TypeError, "expected Integer for 1st argument" unless size.kind_of? Integral + size = size.__to_int raise ArgumentError, "negative array size" if size < 0 self.clear diff --git a/src/kernel.c b/src/kernel.c index db681d510..195594d6b 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -830,6 +830,7 @@ mrb_obj_ceqq(mrb_state *mrb, mrb_value self) } mrb_value mrb_obj_equal_m(mrb_state *mrb, mrb_value); + void mrb_init_kernel(mrb_state *mrb) { @@ -871,6 +872,7 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "respond_to?", obj_respond_to, MRB_ARGS_ANY()); /* 15.3.1.3.43 */ 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, "class_defined?", mrb_krn_class_defined, MRB_ARGS_REQ(1)); diff --git a/src/numeric.c b/src/numeric.c index f7f0318e8..3624831cc 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -674,7 +674,6 @@ flo_round(mrb_state *mrb, mrb_value num) /* * call-seq: * flt.to_i -> integer - * flt.to_int -> integer * flt.truncate -> integer * * Returns flt truncated to an Integer. @@ -714,7 +713,6 @@ flo_nan_p(mrb_state *mrb, mrb_value num) /* * call-seq: * int.to_i -> integer - * int.to_int -> integer * * As int is already an Integer, all these * methods simply return the receiver. @@ -1513,7 +1511,6 @@ mrb_init_numeric(mrb_state *mrb) MRB_SET_INSTANCE_TT(integer, MRB_TT_FIXNUM); mrb_undef_class_method(mrb, integer, "new"); mrb_define_method(mrb, integer, "to_i", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.24 */ - mrb_define_method(mrb, integer, "to_int", int_to_i, MRB_ARGS_NONE()); #ifndef MRB_WITHOUT_FLOAT mrb_define_method(mrb, integer, "ceil", int_to_i, MRB_ARGS_REQ(1)); /* 15.2.8.3.8 (x) */ mrb_define_method(mrb, integer, "floor", int_to_i, MRB_ARGS_REQ(1)); /* 15.2.8.3.10 (x) */ @@ -1565,7 +1562,6 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, fl, "round", flo_round, MRB_ARGS_OPT(1)); /* 15.2.9.3.12 */ mrb_define_method(mrb, fl, "to_f", flo_to_f, MRB_ARGS_NONE()); /* 15.2.9.3.13 */ mrb_define_method(mrb, fl, "to_i", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.14 */ - mrb_define_method(mrb, fl, "to_int", flo_truncate, MRB_ARGS_NONE()); mrb_define_method(mrb, fl, "truncate", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.15 */ mrb_define_method(mrb, fl, "divmod", flo_divmod, MRB_ARGS_REQ(1)); mrb_define_method(mrb, fl, "eql?", flo_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */ diff --git a/src/object.c b/src/object.c index 8724c5416..ba6fa3947 100644 --- a/src/object.c +++ b/src/object.c @@ -322,19 +322,6 @@ convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *metho return mrb_funcall_argv(mrb, val, m, 0, 0); } -MRB_API mrb_value -mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method) -{ - mrb_value v; - - if (mrb_fixnum_p(val)) return val; - v = convert_type(mrb, val, "Integer", method, FALSE); - if (mrb_nil_p(v) || !mrb_fixnum_p(v)) { - return mrb_nil_value(); - } - return v; -} - MRB_API mrb_value mrb_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method) { @@ -505,25 +492,22 @@ mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c) return FALSE; } -static mrb_value -mrb_to_integer(mrb_state *mrb, mrb_value val, const char *method) -{ - mrb_value v; - - if (mrb_fixnum_p(val)) return val; - v = convert_type(mrb, val, "Integer", method, TRUE); - if (!mrb_obj_is_kind_of(mrb, v, mrb->fixnum_class)) { - mrb_value type = inspect_type(mrb, val); - mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Integer (%S#%S gives %S)", - type, type, mrb_str_new_cstr(mrb, method), inspect_type(mrb, v)); - } - return v; -} - MRB_API mrb_value mrb_to_int(mrb_state *mrb, mrb_value val) { - return mrb_to_integer(mrb, val, "to_int"); + + if (!mrb_fixnum_p(val)) { + mrb_value type; + +#ifndef MRB_WITHOUT_FLOAT + if (mrb_float_p(val)) { + return mrb_flo_to_fixnum(mrb, val); + } +#endif + type = inspect_type(mrb, val); + mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Integer", type); + } + return val; } MRB_API mrb_value @@ -533,18 +517,12 @@ mrb_convert_to_integer(mrb_state *mrb, mrb_value val, mrb_int base) if (mrb_nil_p(val)) { if (base != 0) goto arg_error; - mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Integer"); + mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Integer"); } switch (mrb_type(val)) { #ifndef MRB_WITHOUT_FLOAT case MRB_TT_FLOAT: if (base != 0) goto arg_error; - else { - mrb_float f = mrb_float(val); - if (FIXABLE_FLOAT(f)) { - break; - } - } return mrb_flo_to_fixnum(mrb, val); #endif @@ -568,11 +546,8 @@ mrb_convert_to_integer(mrb_state *mrb, mrb_value val, mrb_int base) arg_error: mrb_raise(mrb, E_ARGUMENT_ERROR, "base specified for non string value"); } - tmp = convert_type(mrb, val, "Integer", "to_int", FALSE); - if (mrb_nil_p(tmp) || !mrb_fixnum_p(tmp)) { - tmp = mrb_to_integer(mrb, val, "to_i"); - } - return tmp; + /* to raise TypeError */ + return mrb_to_int(mrb, val); } MRB_API mrb_value -- cgit v1.2.3 From af51119d3a4d56cead0e6b4da69efc78667314d2 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 2 Mar 2019 15:46:50 +0900 Subject: Raise error on failed comparison in `sort`; ref #4307 --- mrblib/array.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'mrblib/array.rb') diff --git a/mrblib/array.rb b/mrblib/array.rb index a677b2a1f..d598efc77 100644 --- a/mrblib/array.rb +++ b/mrblib/array.rb @@ -213,7 +213,11 @@ class Array if left + 1 == right lval = self[left] rval = self[right] - if (block&.call(lval, rval) || (lval <=> rval)) > 0 + cmp = if block then block.call(lval,rval) else lval <=> rval end + if cmp.nil? + raise ArgumentError, "comparison of #{lval.inspect} and #{rval.inspect} failed" + end + if cmp > 0 self[left] = rval self[right] = lval end @@ -245,7 +249,11 @@ class Array else lval = lary[lidx] rval = self[ridx] - if (block&.call(lval, rval) || (lval <=> rval)) <= 0 + cmp = if block then block.call(lval,rval) else lval <=> rval end + if cmp.nil? + raise ArgumentError, "comparison of #{lval.inspect} and #{rval.inspect} failed" + end + if cmp <= 0 self[i] = lval lidx += 1 else -- cgit v1.2.3