From 00b8b11858785439785c0f6805ea4b6910070020 Mon Sep 17 00:00:00 2001 From: shyouhei Date: Mon, 12 Nov 2018 03:26:39 +0000 Subject: vm_insnhelper.c: avoid division by zero same as r65642. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65678 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- internal.h | 1 + numeric.c | 65 +++++++++++++++++++++++++++------------------------------ vm_insnhelper.c | 4 ++-- 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/internal.h b/internal.h index 1a030566d3..d36723b273 100644 --- a/internal.h +++ b/internal.h @@ -1755,6 +1755,7 @@ rb_num_negative_int_p(VALUE num) VALUE rb_float_abs(VALUE flt); VALUE rb_float_equal(VALUE x, VALUE y); VALUE rb_float_eql(VALUE x, VALUE y); +VALUE rb_flo_div_flo(VALUE x, VALUE y); #if USE_FLONUM #define RUBY_BIT_ROTL(v, n) (((v) << (n)) | ((v) >> ((sizeof(v) * 8) - n))) diff --git a/numeric.c b/numeric.c index 47dbf722f1..6d098368df 100644 --- a/numeric.c +++ b/numeric.c @@ -1089,6 +1089,30 @@ flo_iszero(VALUE f) return RFLOAT_VALUE(f) == 0.0; } +static double +double_div_double(double x, double y) +{ + if (LIKELY(y != 0.0)) { + return x / y; + } + else if (x == 0.0) { + return nan(""); + } + else { + double z = signbit(y) ? -1.0 : 1.0; + return x * z * HUGE_VAL; + } +} + +VALUE +rb_flo_div_flo(VALUE x, VALUE y) +{ + double num = RFLOAT_VALUE(x); + double den = RFLOAT_VALUE(y); + double ret = double_div_double(x, y); + return DBL2NUM(ret); +} + /* * call-seq: * float / other -> float @@ -1099,52 +1123,25 @@ flo_iszero(VALUE f) static VALUE flo_div(VALUE x, VALUE y) { - double den; double num = RFLOAT_VALUE(x); - double sign = 1.0; + double den; + double ret; if (RB_TYPE_P(y, T_FIXNUM)) { - if (FIXNUM_ZERO_P(y)) { - goto zerodiv; - } - else { - den = FIX2LONG(y); - goto nonzero; - } + den = FIX2LONG(y); } else if (RB_TYPE_P(y, T_BIGNUM)) { - if (rb_bigzero_p(y)) { - goto zerodiv; - } - else { - den = rb_big2dbl(y); - goto nonzero; - } + den = rb_big2dbl(y); } else if (RB_TYPE_P(y, T_FLOAT)) { - if (flo_iszero(y)) { - sign = signbit(RFLOAT_VALUE(y)) ? -1.0 : 1.0; - goto zerodiv; - } - else { - den = RFLOAT_VALUE(y); - goto nonzero; - } + den = RFLOAT_VALUE(y); } else { return rb_num_coerce_bin(x, y, '/'); } -nonzero: - return DBL2NUM(num / den); - -zerodiv: - if (num == 0.0) { - return DBL2NUM(nan("")); - } - else { - return DBL2NUM(num * sign * HUGE_VAL); - } + ret = double_div_double(num, den); + return DBL2NUM(ret); } /* diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 84ed11662e..05a5289487 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -3450,7 +3450,7 @@ vm_opt_div(VALUE recv, VALUE obj) } else if (FLONUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) { - return DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj)); + return rb_flo_div_flo(recv, obj); } else if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) { return Qundef; @@ -3458,7 +3458,7 @@ vm_opt_div(VALUE recv, VALUE obj) else if (RBASIC_CLASS(recv) == rb_cFloat && RBASIC_CLASS(obj) == rb_cFloat && BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) { - return DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj)); + return rb_flo_div_flo(recv, obj); } else { return Qundef; -- cgit v1.2.3