diff options
| author | bors <bors@rust-lang.org> | 2013-04-09 07:52:04 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-04-09 07:52:04 -0700 |
| commit | 412a07055c211f2dec4fb87f25b87d2d71fb13de (patch) | |
| tree | de1953e40e10262584cb436135d1bc6e203c3d36 /src | |
| parent | e56a17879aaa88787326e0bf3f7742980fed270e (diff) | |
| parent | 89676d6a5960aa51ee1e6975c423e979819a407c (diff) | |
| download | rust-412a07055c211f2dec4fb87f25b87d2d71fb13de.tar.gz rust-412a07055c211f2dec4fb87f25b87d2d71fb13de.zip | |
auto merge of #5769 : gifnksm/rust/range_step, r=bstrie
`uint::range_step` or `int::range_step` causes overflow or underflow as following.
code:
```rust
fn main() {
for uint::range_step(3, 0, -2) |n| {
println(fmt!("%u", n));
}
}
```
output:
```
3
1
18446744073709551615
18446744073709551613
...
```
This commit fixes this behavior as follows.
```
3
1
```
Diffstat (limited to 'src')
| -rw-r--r-- | src/libcore/num/int-template.rs | 28 | ||||
| -rw-r--r-- | src/libcore/num/uint-template.rs | 31 |
2 files changed, 49 insertions, 10 deletions
diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index db90ec79465..4af903908f1 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -107,11 +107,15 @@ pub fn range_step(start: T, stop: T, step: T, it: &fn(T) -> bool) { } else if step > 0 { // ascending while i < stop { if !it(i) { break } + // avoiding overflow. break if i + step > max_value + if i > max_value - step { break; } i += step; } } else { // descending while i > stop { if !it(i) { break } + // avoiding underflow. break if i + step < min_value + if i < min_value - step { break; } i += step; } } @@ -421,10 +425,26 @@ pub fn test_ranges() { for range_step(36,30,-2) |i| { l.push(i); } - assert!(l == ~[0,1,2, - 13,12,11, - 20,22,24, - 36,34,32]); + for range_step(max_value - 2, max_value, 2) |i| { + l.push(i); + } + for range_step(max_value - 3, max_value, 2) |i| { + l.push(i); + } + for range_step(min_value + 2, min_value, -2) |i| { + l.push(i); + } + for range_step(min_value + 3, min_value, -2) |i| { + l.push(i); + } + assert_eq!(l, ~[0,1,2, + 13,12,11, + 20,22,24, + 36,34,32, + max_value-2, + max_value-3,max_value-1, + min_value+2, + min_value+3,min_value+1]); // None of the `fail`s should execute. for range(10,0) |_i| { diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 39af025217c..412921b8c28 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -78,12 +78,15 @@ pub fn range_step(start: T, if step >= 0 { while i < stop { if !it(i) { break } + // avoiding overflow. break if i + step > max_value + if i > max_value - (step as T) { break; } i += step as T; } - } - else { + } else { while i > stop { if !it(i) { break } + // avoiding underflow. break if i + step < min_value + if i < min_value + ((-step) as T) { break; } i -= -step as T; } } @@ -371,11 +374,27 @@ pub fn test_ranges() { for range_step(36,30,-2) |i| { l.push(i); } + for range_step(max_value - 2, max_value, 2) |i| { + l.push(i); + } + for range_step(max_value - 3, max_value, 2) |i| { + l.push(i); + } + for range_step(min_value + 2, min_value, -2) |i| { + l.push(i); + } + for range_step(min_value + 3, min_value, -2) |i| { + l.push(i); + } - assert!(l == ~[0,1,2, - 13,12,11, - 20,22,24, - 36,34,32]); + assert_eq!(l, ~[0,1,2, + 13,12,11, + 20,22,24, + 36,34,32, + max_value-2, + max_value-3,max_value-1, + min_value+2, + min_value+3,min_value+1]); // None of the `fail`s should execute. for range(0,0) |_i| { |
