bignum.c (estimate_initial_sqrt): prevent integer overflow

`Integer.sqrt(0xffff_ffff_ffff_ffff ** 2)` caused assertion failure
because of integer overflow.  [ruby-core:95453] [Bug #16269]
This commit is contained in:
Yusuke Endoh 2019-10-21 21:22:53 +09:00
Родитель c8f97d1620
Коммит f364564e66
2 изменённых файлов: 12 добавлений и 1 удалений

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

@ -6888,8 +6888,16 @@ estimate_initial_sqrt(VALUE *xp, const size_t xn, const BDIGIT *nds, size_t len)
rshift /= 2;
rshift += (2-(len&1))*BITSPERDIG/2;
if (rshift >= 0) {
if (nlz((BDIGIT)d) + rshift >= BITSPERDIG) {
/* (d << rshift) does cause overflow.
* example: Integer.sqrt(0xffff_ffff_ffff_ffff ** 2)
*/
d = ~(BDIGIT_DBL)0;
}
else {
d <<= rshift;
}
}
BDIGITS_ZERO(xds, xn-2);
bdigitdbl2bary(&xds[xn-2], 2, d);

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

@ -640,6 +640,9 @@ class TestInteger < Test::Unit::TestCase
failures << n unless root*root <= n && (root+1)*(root+1) > n
end
assert_empty(failures, bug13440)
x = 0xffff_ffff_ffff_ffff
assert_equal(x, Integer.sqrt(x ** 2), "[ruby-core:95453]")
end
def test_fdiv