diff --git a/ChangeLog b/ChangeLog index 9740541e62..e6f0bc0f6b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Thu Feb 27 12:10:09 2014 Nobuyoshi Nakada + + * numeric.c (ruby_num_interval_step_size): check signs and get rid + of implementation dependent behavior of negative division. + [ruby-core:61106] [Bug #9570] + Thu Feb 27 03:55:45 2014 Zachary Scott * thread.c: [DOC] Typo in comment for _FORTIFY_SOURCE [Fixes GH-548] diff --git a/numeric.c b/numeric.c index 838ec43c29..99a1c7d60e 100644 --- a/numeric.c +++ b/numeric.c @@ -1808,10 +1808,21 @@ ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl) long delta, diff, result; diff = FIX2LONG(step); + if (!diff) rb_num_zerodiv(); delta = FIX2LONG(to) - FIX2LONG(from); if (excl) { delta += (diff > 0 ? -1 : +1); } + if (delta) { + if (diff < 0) { + if (delta > 0) return INT2FIX(0); + diff = -diff; + delta = -delta; + } + else { + if (delta < 0) return INT2FIX(0); + } + } result = delta / diff; return LONG2FIX(result >= 0 ? result + 1 : 0); } diff --git a/test/ruby/test_numeric.rb b/test/ruby/test_numeric.rb index 44c12ede9c..25351163b7 100644 --- a/test/ruby/test_numeric.rb +++ b/test/ruby/test_numeric.rb @@ -279,6 +279,8 @@ class TestNumeric < Test::Unit::TestCase assert_step [1], [1, 10, 2**32] assert_step [1], [1, to: 10, by: 2**32] + assert_step [], [2, 1, 3] + assert_step [], [-2, -1, -3] assert_step [3, 3, 3, 3], [3, by: 0], inf: true assert_step [10], [10, 1, -(2**32)]