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

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/

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