Skip to content

Commit 9da7706

Browse files
committed
Auto merge of #28248 - PeterReid:master, r=alexcrichton
Overflows in integer pow() computations would be missed if they preceded a 0 bit of the exponent being processed. This made calls such as 2i32.pow(1024) not trigger an overflow. Fixes #28012
2 parents 2d4ae52 + a593a21 commit 9da7706

File tree

2 files changed

+27
-15
lines changed

2 files changed

+27
-15
lines changed

src/libcore/num/mod.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -537,25 +537,21 @@ macro_rules! int_impl {
537537
let mut base = self;
538538
let mut acc = Self::one();
539539

540-
let mut prev_base = self;
541-
let mut base_oflo = false;
542-
while exp > 0 {
540+
while exp > 1 {
543541
if (exp & 1) == 1 {
544-
if base_oflo {
545-
// ensure overflow occurs in the same manner it
546-
// would have otherwise (i.e. signal any exception
547-
// it would have otherwise).
548-
acc = acc * (prev_base * prev_base);
549-
} else {
550-
acc = acc * base;
551-
}
542+
acc = acc * base;
552543
}
553-
prev_base = base;
554-
let (new_base, new_base_oflo) = base.overflowing_mul(base);
555-
base = new_base;
556-
base_oflo = new_base_oflo;
557544
exp /= 2;
545+
base = base * base;
546+
}
547+
548+
// Deal with the final bit of the exponent separately, since
549+
// squaring the base afterwards is not necessary and may cause a
550+
// needless overflow.
551+
if exp == 1 {
552+
acc = acc * base;
558553
}
554+
559555
acc
560556
}
561557

src/test/run-fail/overflowing-pow.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// error-pattern:thread '<main>' panicked at 'arithmetic operation overflowed'
12+
// compile-flags: -C debug-assertions
13+
14+
fn main() {
15+
let _x = 2i32.pow(1024);
16+
}

0 commit comments

Comments
 (0)