aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-08-30 07:17:56 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-08-30 07:17:56 +0000
commitd7ca01a73ad5287f9d063bbdf5b35f472affda9d (patch)
treec79b2018ac56d826f7c0a716df096e5ceb9ef19d
parentaa7dc0f305c11c2ef9e67f6d48acbd1264022024 (diff)
downloadruby-d7ca01a73ad5287f9d063bbdf5b35f472affda9d.tar.gz
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] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36854 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog6
-rw-r--r--ext/bigdecimal/bigdecimal.c6
-rw-r--r--test/bigdecimal/test_bigdecimal.rb32
3 files changed, 36 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index 55b791bf66..1d396d38f6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Thu Aug 30 16:17:52 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * 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@iDaemons.org>
* lib/set.rb (Set#{<,>,<=,>=}): Define comparison operators as
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 866ce345fc..e8ba40a531 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -696,8 +696,10 @@ BigDecimal_to_f(VALUE self)
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:
diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb
index d440e4cedb..6694697e0e 100644
--- a/test/bigdecimal/test_bigdecimal.rb
+++ b/test/bigdecimal/test_bigdecimal.rb
@@ -540,15 +540,35 @@ class TestBigDecimal < Test::Unit::TestCase
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