From ffa31d235badfb5544ddb2de151ccfc66c8a20e6 Mon Sep 17 00:00:00 2001 From: gifnksm Date: Mon, 29 Apr 2013 11:53:01 +0900 Subject: libstd: modify wrong shift width. borrow = *elem << (uint::bits - n_bits); The code above contains a bug that the value of the right operand of the shift operator exceeds the size of the left operand, because sizeof(*elem) == 32, and 0 <= n_bits < 32 in 64bit architecture. If `--opt-level` option is not given to rustc, the code above runs as if the right operand is `(uint::bits - n_bits) % 32`, but if --opt-level is given, `borrow` is always zero. I wonder why this bug is not catched in the libstd's testsuite (I try the `rustc --test --opt-level=2 bigint.rs` before fixing the bug, but the unittest passes normally.) --- src/libstd/num/bigint.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/libstd/num') diff --git a/src/libstd/num/bigint.rs b/src/libstd/num/bigint.rs index 74e5b00d896..526272883b7 100644 --- a/src/libstd/num/bigint.rs +++ b/src/libstd/num/bigint.rs @@ -623,7 +623,7 @@ impl BigUint { let mut shifted = ~[]; for self.data.each_reverse |elem| { shifted = ~[(*elem >> n_bits) | borrow] + shifted; - borrow = *elem << (uint::bits - n_bits); + borrow = *elem << (BigDigit::bits - n_bits); } return BigUint::new(shifted); } @@ -1213,6 +1213,7 @@ mod biguint_tests { check(~[1 << 2], 2, ~[1]); check(~[1, 2], 3, ~[1 << (BigDigit::bits - 2)]); check(~[1, 1, 2], 3 + BigDigit::bits, ~[1 << (BigDigit::bits - 2)]); + check(~[0, 1], 1, ~[0x80000000]); test_shr_bits(); #[cfg(target_arch = "x86_64")] -- cgit 1.4.1-3-g733a5