range.c: fix fixnum loop condition

* range.c (range_step): FIXABLE + FIXABLE never overflow, but may
  not be FIXABLE.  [Feature #12912]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63207 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2018-04-20 00:10:46 +00:00
Родитель 5a5c9a706c
Коммит ad5a6aa790
2 изменённых файлов: 9 добавлений и 4 удалений

Просмотреть файл

@ -402,11 +402,10 @@ range_step(int argc, VALUE *argv, VALUE range)
if (FIXNUM_P(b) && NIL_P(e) && FIXNUM_P(step)) {
long i = FIX2LONG(b), unit = FIX2LONG(step);
while (1) {
do {
rb_yield(LONG2FIX(i));
if (i + unit < i) break;
i += unit;
}
i += unit; /* FIXABLE+FIXABLE never overflow */
} while (FIXABLE(i));
b = LONG2NUM(i);
for (;; b = rb_funcallv(b, id_succ, 0, 0))

Просмотреть файл

@ -3,6 +3,7 @@ require 'test/unit'
require 'delegate'
require 'timeout'
require 'bigdecimal'
require 'rbconfig/sizeof'
class TestRange < Test::Unit::TestCase
def test_new
@ -244,6 +245,11 @@ class TestRange < Test::Unit::TestCase
(2**32-1 .. ).step(2) {|x| a << x; break if a.size == 2 }
assert_equal([4294967295, 4294967297], a)
a = []
max = RbConfig::LIMITS["FIXNUM_MAX"]
(max..).step {|x| a << x; break if a.size == 2 }
assert_equal([max, max+1], a)
o1 = Object.new
o2 = Object.new
def o1.<=>(x); -1; end