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/