mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
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).
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -93,9 +93,8 @@ mrb_f_method(mrb_state *mrb, mrb_value self)
|
||||
* (<code>0</code>, <code>0b</code>, and <code>0x</code>) are honored.
|
||||
* In any case, strings should be strictly conformed to numeric
|
||||
* representation. This behavior is different from that of
|
||||
* <code>String#to_i</code>. Non string values will be converted using
|
||||
* <code>to_int</code>, and <code>to_i</code>. Passing <code>nil</code>
|
||||
* raises a TypeError.
|
||||
* <code>String#to_i</code>. Non string values will be treated as integers.
|
||||
* Passing <code>nil</code> raises a TypeError.
|
||||
*
|
||||
* Integer(123.999) #=> 123
|
||||
* Integer("0x1a") #=> 26
|
||||
|
||||
@@ -2,13 +2,10 @@
|
||||
#include <mruby.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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|
|
||||
|
||||
@@ -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))
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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 <i>flt</i> truncated to an <code>Integer</code>.
|
||||
@@ -714,7 +713,6 @@ flo_nan_p(mrb_state *mrb, mrb_value num)
|
||||
/*
|
||||
* call-seq:
|
||||
* int.to_i -> integer
|
||||
* int.to_int -> integer
|
||||
*
|
||||
* As <i>int</i> is already an <code>Integer</code>, 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 */
|
||||
|
||||
+16
-41
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user