[前][次][番号順一覧][スレッド一覧]

ruby-changes:53535

From: shyouhei <ko1@a...>
Date: Fri, 16 Nov 2018 10:52:44 +0900 (JST)
Subject: [ruby-changes:53535] shyouhei:r65751 (trunk): avoid division by zero

shyouhei	2018-11-16 10:52:39 +0900 (Fri, 16 Nov 2018)

  New Revision: 65751

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=65751

  Log:
    avoid division by zero
    
    * cvt(): use signbit() instead of 1/d < 0
    * w_float(): ditto
    * ruby_float_step_size(): unit==0 check shall be prior to divisions
    * arith_seq_float_step_size(): ditto
    * rb_big_divide(): same as r65642
    * fix_divide(): ditto
    * rb_big_fdiv_double(): ditto
    * fix_fdiv_double(): ditto

  Modified files:
    trunk/bignum.c
    trunk/enumerator.c
    trunk/marshal.c
    trunk/numeric.c
    trunk/vsnprintf.c
Index: enumerator.c
===================================================================
--- enumerator.c	(revision 65750)
+++ enumerator.c	(revision 65751)
@@ -2790,15 +2790,16 @@ static double https://github.com/ruby/ruby/blob/trunk/enumerator.c#L2790
 arith_seq_float_step_size(double beg, double end, double step, int excl)
 {
     double const epsilon = DBL_EPSILON;
-    double n = (end - beg) / step;
-    double err = (fabs(beg) + fabs(end) + fabs(end - beg)) / fabs(step) * epsilon;
+    double n, err;
 
-    if (isinf(step)) {
-        return step > 0 ? beg <= end : beg >= end;
-    }
     if (step == 0) {
         return HUGE_VAL;
     }
+    n = (end - beg) / step;
+    err = (fabs(beg) + fabs(end) + fabs(end - beg)) / fabs(step) * epsilon;
+    if (isinf(step)) {
+        return step > 0 ? beg <= end : beg >= end;
+    }
     if (err > 0.5) err = 0.5;
     if (excl) {
         if (n <= 0) return 0;
Index: marshal.c
===================================================================
--- marshal.c	(revision 65750)
+++ marshal.c	(revision 65751)
@@ -401,8 +401,8 @@ w_float(double d, struct dump_arg *arg) https://github.com/ruby/ruby/blob/trunk/marshal.c#L401
 	w_cstr("nan", arg);
     }
     else if (d == 0.0) {
-	if (1.0/d < 0) w_cstr("-0", arg);
-	else           w_cstr("0", arg);
+        if (signbit(d)) w_cstr("-0", arg);
+        else            w_cstr("0", arg);
     }
     else {
 	int decpt, sign, digs, len = 0;
Index: bignum.c
===================================================================
--- bignum.c	(revision 65750)
+++ bignum.c	(revision 65751)
@@ -6041,12 +6041,15 @@ rb_big_divide(VALUE x, VALUE y, ID op) https://github.com/ruby/ruby/blob/trunk/bignum.c#L6041
     }
     else if (RB_FLOAT_TYPE_P(y)) {
 	if (op == '/') {
-	    return DBL2NUM(rb_big2dbl(x) / RFLOAT_VALUE(y));
+            double dx = rb_big2dbl(x);
+            return rb_flo_div_flo(DBL2NUM(dx), y);
 	}
 	else {
+            VALUE v;
 	    double dy = RFLOAT_VALUE(y);
 	    if (dy == 0.0) rb_num_zerodiv();
-	    return rb_dbl2big(rb_big2dbl(x) / dy);
+            v = rb_big_divide(x, y, '/');
+            return rb_dbl2big(RFLOAT_VALUE(v));
 	}
     }
     else {
@@ -6179,6 +6182,7 @@ double https://github.com/ruby/ruby/blob/trunk/bignum.c#L6182
 rb_big_fdiv_double(VALUE x, VALUE y)
 {
     double dx, dy;
+    VALUE v;
 
     dx = big2dbl(x);
     if (FIXNUM_P(y)) {
@@ -6199,7 +6203,8 @@ rb_big_fdiv_double(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/bignum.c#L6203
     else {
 	return NUM2DBL(rb_num_coerce_bin(x, y, rb_intern("fdiv")));
     }
-    return dx / dy;
+    v = rb_flo_div_flo(DBL2NUM(dx), DBL2NUM(dy));
+    return NUM2DBL(v);
 }
 
 VALUE
Index: vsnprintf.c
===================================================================
--- vsnprintf.c	(revision 65750)
+++ vsnprintf.c	(revision 65751)
@@ -1250,7 +1250,7 @@ cvt(double value, int ndigits, int flags https://github.com/ruby/ruby/blob/trunk/vsnprintf.c#L1250
 	if (value < 0) {
 		value = -value;
 		*sign = '-';
-	} else if (value == 0.0 && 1.0/value < 0) {
+	} else if (value == 0.0 && signbit(value)) {
 	    *sign = '-';
 	} else {
 	    *sign = '\000';
Index: numeric.c
===================================================================
--- numeric.c	(revision 65750)
+++ numeric.c	(revision 65751)
@@ -2485,15 +2485,16 @@ static double https://github.com/ruby/ruby/blob/trunk/numeric.c#L2485
 ruby_float_step_size(double beg, double end, double unit, int excl)
 {
     const double epsilon = DBL_EPSILON;
-    double n = (end - beg)/unit;
-    double err = (fabs(beg) + fabs(end) + fabs(end-beg)) / fabs(unit) * epsilon;
+    double n, err;
 
+    if (unit == 0) {
+        return HUGE_VAL;
+    }
+    n= (end - beg)/unit;
+    err = (fabs(beg) + fabs(end) + fabs(end-beg)) / fabs(unit) * epsilon;
     if (isinf(unit)) {
 	return unit > 0 ? beg <= end : beg >= end;
     }
-    if (unit == 0) {
-	return HUGE_VAL;
-    }
     if (err>0.5) err=0.5;
     if (excl) {
 	if (n<=0) return 0;
@@ -3707,7 +3708,7 @@ fix_fdiv_double(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/numeric.c#L3708
         return rb_big_fdiv_double(rb_int2big(FIX2LONG(x)), y);
     }
     else if (RB_TYPE_P(y, T_FLOAT)) {
-        return (double)FIX2LONG(x) / RFLOAT_VALUE(y);
+        return double_div_double(FIX2LONG(x), RFLOAT_VALUE(y));
     }
     else {
         return NUM2DBL(rb_num_coerce_bin(x, y, rb_intern("fdiv")));
@@ -3777,19 +3778,16 @@ fix_divide(VALUE x, VALUE y, ID op) https://github.com/ruby/ruby/blob/trunk/numeric.c#L3778
 	return rb_big_div(x, y);
     }
     else if (RB_TYPE_P(y, T_FLOAT)) {
-	{
-	    double div;
-
 	    if (op == '/') {
-		div = (double)FIX2LONG(x) / RFLOAT_VALUE(y);
-		return DBL2NUM(div);
+                double d = FIX2LONG(x);
+                return rb_flo_div_flo(DBL2NUM(d), y);
 	    }
 	    else {
+                VALUE v;
 		if (RFLOAT_VALUE(y) == 0) rb_num_zerodiv();
-		div = (double)FIX2LONG(x) / RFLOAT_VALUE(y);
-		return rb_dbl2big(floor(div));
+                v = fix_divide(x, y, '/');
+                return flo_floor(0, 0, v);
 	    }
-	}
     }
     else {
 	if (RB_TYPE_P(y, T_RATIONAL) &&

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]