about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-04-09 07:52:04 -0700
committerbors <bors@rust-lang.org>2013-04-09 07:52:04 -0700
commit412a07055c211f2dec4fb87f25b87d2d71fb13de (patch)
treede1953e40e10262584cb436135d1bc6e203c3d36 /src
parente56a17879aaa88787326e0bf3f7742980fed270e (diff)
parent89676d6a5960aa51ee1e6975c423e979819a407c (diff)
downloadrust-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.rs28
-rw-r--r--src/libcore/num/uint-template.rs31
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| {