From 76d7e7d54c16cd4cc151fdb7d0de43c8f6c13770 Mon Sep 17 00:00:00 2001 From: nobu Date: Fri, 11 Apr 2003 06:37:48 +0000 Subject: * numeric.c (coerce_rescue): prevent inspected String from GC. * numeric.c (flo_eq, rb_dbl_cmp, flo_gt, flo_ge, flo_lt, flo_le, flo_eql): correct NaN comparison. (ruby-bugs:PR#744) git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3671 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- numeric.c | 56 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 20 deletions(-) (limited to 'numeric.c') diff --git a/numeric.c b/numeric.c index fe4b0308f3..3e804bc56f 100644 --- a/numeric.c +++ b/numeric.c @@ -93,9 +93,11 @@ static VALUE coerce_rescue(x) VALUE *x; { + volatile VALUE v; + rb_raise(rb_eTypeError, "%s can't be coerced into %s", rb_special_const_p(x[1])? - RSTRING(rb_inspect(x[1]))->ptr: + RSTRING(v = rb_inspect(x[1]))->ptr: rb_obj_classname(x[1]), rb_obj_classname(x[0])); return Qnil; /* dummy */ @@ -506,17 +508,24 @@ static VALUE flo_eq(x, y) VALUE x, y; { + double a, b; + switch (TYPE(y)) { case T_FIXNUM: - if (RFLOAT(x)->value == FIX2LONG(y)) return Qtrue; - return Qfalse; + b = FIX2LONG(y); + break; case T_BIGNUM: - return (RFLOAT(x)->value == rb_big2dbl(y))?Qtrue:Qfalse; + b = rb_big2dbl(y); + break; case T_FLOAT: - return (RFLOAT(x)->value == RFLOAT(y)->value)?Qtrue:Qfalse; + b = RFLOAT(y)->value; + break; default: return num_equal(x, y); } + a = RFLOAT(x)->value; + if (isnan(a) || isnan(b)) return Qfalse; + return (a == b)?Qtrue:Qfalse; } static VALUE @@ -541,6 +550,7 @@ VALUE rb_dbl_cmp(a, b) double a, b; { + if (isnan(a) || isnan(b)) return Qnil; if (a == b) return INT2FIX(0); if (a > b) return INT2FIX(1); if (a < b) return INT2FIX(-1); @@ -596,6 +606,7 @@ flo_gt(x, y) default: return rb_num_coerce_cmp(x, y); } + if (isnan(a) || isnan(b)) return Qfalse; return (a > b)?Qtrue:Qfalse; } @@ -622,6 +633,7 @@ flo_ge(x, y) default: return rb_num_coerce_cmp(x, y); } + if (isnan(a) || isnan(b)) return Qfalse; return (a >= b)?Qtrue:Qfalse; } @@ -648,6 +660,7 @@ flo_lt(x, y) default: return rb_num_coerce_cmp(x, y); } + if (isnan(a) || isnan(b)) return Qfalse; return (a < b)?Qtrue:Qfalse; } @@ -674,6 +687,7 @@ flo_le(x, y) default: return rb_num_coerce_cmp(x, y); } + if (isnan(a) || isnan(b)) return Qfalse; return (a <= b)?Qtrue:Qfalse; } @@ -681,8 +695,12 @@ static VALUE flo_eql(x, y) VALUE x, y; { - if (TYPE(y) == T_FLOAT && RFLOAT(x)->value == RFLOAT(y)->value) { - return Qtrue; + if (TYPE(y) == T_FLOAT) { + double a = RFLOAT(x)->value; + double b = RFLOAT(y)->value; + + if (isnan(a) || isnan(b)) return Qfalse; + if (a == b) return Qtrue; } return Qfalse; } @@ -716,38 +734,36 @@ static VALUE flo_is_nan_p(num) VALUE num; { + double value = RFLOAT(num)->value; - double value = RFLOAT(num)->value; - - return isnan(value) ? Qtrue : Qfalse; + return isnan(value) ? Qtrue : Qfalse; } static VALUE flo_is_infinite_p(num) VALUE num; { - double value = RFLOAT(num)->value; + double value = RFLOAT(num)->value; - if (isinf(value)) { - return INT2FIX( value < 0 ? -1 : 1 ); - } + if (isinf(value)) { + return INT2FIX( value < 0 ? -1 : 1 ); + } - return Qnil; + return Qnil; } static VALUE flo_is_finite_p(num) VALUE num; { - double value = RFLOAT(num)->value; + double value = RFLOAT(num)->value; - if (isinf(value) || isnan(value)) - return Qfalse; + if (isinf(value) || isnan(value)) + return Qfalse; - return Qtrue; + return Qtrue; } - static VALUE flo_floor(num) VALUE num; -- cgit v1.2.3