ruby-changes:24803
From: nobu <ko1@a...>
Date: Thu, 30 Aug 2012 16:18:19 +0900 (JST)
Subject: [ruby-changes:24803] nobu:r36854 (trunk): bigdecimal.c: check underflow
nobu 2012-08-30 16:17:56 +0900 (Thu, 30 Aug 2012) New Revision: 36854 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=36854 Log: bigdecimal.c: check underflow * ext/bigdecimal/bigdecimal.c (BigDecimal_to_f): check underflow since strtod() sets errno to ERANGE at underflow too. [ruby-core:47342] [Bug #6944] Modified files: trunk/ChangeLog trunk/ext/bigdecimal/bigdecimal.c trunk/test/bigdecimal/test_bigdecimal.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 36853) +++ ChangeLog (revision 36854) @@ -1,3 +1,9 @@ +Thu Aug 30 16:17:52 2012 Nobuyoshi Nakada <nobu@r...> + + * ext/bigdecimal/bigdecimal.c (BigDecimal_to_f): check underflow since + strtod() sets errno to ERANGE at underflow too. [ruby-core:47342] + [Bug #6944] + Thu Aug 30 12:44:43 2012 Akinori MUSHA <knu@i...> * lib/set.rb (Set#{<,>,<=,>=}): Define comparison operators as Index: ext/bigdecimal/bigdecimal.c =================================================================== --- ext/bigdecimal/bigdecimal.c (revision 36853) +++ ext/bigdecimal/bigdecimal.c (revision 36854) @@ -696,8 +696,10 @@ VpToString(p, buf, 0, 0); errno = 0; d = strtod(buf, 0); - if (errno == ERANGE) - goto overflow; + if (errno == ERANGE) { + if (d == 0.0) goto underflow; + if (fabs(d) >= HUGE_VAL) goto overflow; + } return rb_float_new(d); overflow: Index: test/bigdecimal/test_bigdecimal.rb =================================================================== --- test/bigdecimal/test_bigdecimal.rb (revision 36853) +++ test/bigdecimal/test_bigdecimal.rb (revision 36854) @@ -540,15 +540,35 @@ assert_kind_of(Float, x .to_f) assert_kind_of(Float, (-x).to_f) + bug6944 = '[ruby-core:47342]' + BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, true) - assert_raise(FloatDomainError) { - BigDecimal("1e#{Float::MIN_10_EXP - 2*Float::DIG}").to_f } - assert_raise(FloatDomainError) { - BigDecimal("-1e#{Float::MIN_10_EXP - 2*Float::DIG}").to_f } + x = "1e#{Float::MIN_10_EXP - 2*Float::DIG}" + assert_raise(FloatDomainError, x) {BigDecimal(x).to_f} + x = "-#{x}" + assert_raise(FloatDomainError, x) {BigDecimal(x).to_f} + x = "1e#{Float::MIN_10_EXP - Float::DIG}" + assert_nothing_raised(FloatDomainError, x) { + assert_in_delta(0.0, BigDecimal(x).to_f, 10**Float::MIN_10_EXP, bug6944) + } + x = "-#{x}" + assert_nothing_raised(FloatDomainError, x) { + assert_in_delta(0.0, BigDecimal(x).to_f, 10**Float::MIN_10_EXP, bug6944) + } BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, false) - assert_equal( 0.0, BigDecimal("1e#{Float::MIN_10_EXP - 2*Float::DIG}").to_f) - assert_equal(-0.0, BigDecimal("-1e#{Float::MIN_10_EXP - 2*Float::DIG}").to_f) + x = "1e#{Float::MIN_10_EXP - 2*Float::DIG}" + assert_equal( 0.0, BigDecimal(x).to_f, x) + x = "-#{x}" + assert_equal(-0.0, BigDecimal(x).to_f, x) + x = "1e#{Float::MIN_10_EXP - Float::DIG}" + assert_nothing_raised(FloatDomainError, x) { + assert_in_delta(0.0, BigDecimal(x).to_f, 10**Float::MIN_10_EXP, bug6944) + } + x = "-#{x}" + assert_nothing_raised(FloatDomainError, x) { + assert_in_delta(0.0, BigDecimal(x).to_f, 10**Float::MIN_10_EXP, bug6944) + } end def test_coerce -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/