about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorAaron Laursen <aaronlaursen@gmail.com>2013-08-30 17:45:20 -0500
committeraaronlaursen <aaronlaursen@gmail.com>2013-09-06 13:00:34 -0500
commitcaf5321eb45db8ba64d3f9f4b9e16febfeb46a4c (patch)
treeaf81a2b9d507109f11e4cf5c52519914f9081ea8 /src/libstd
parent116c034791e094840bc7bccee48113426665bc9f (diff)
downloadrust-caf5321eb45db8ba64d3f9f4b9e16febfeb46a4c.tar.gz
rust-caf5321eb45db8ba64d3f9f4b9e16febfeb46a4c.zip
fix for issue #7588, overflow now handled correctly
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/num/strconv.rs35
1 files changed, 31 insertions, 4 deletions
diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs
index 6fba8a6dd13..fe93f20e109 100644
--- a/src/libstd/num/strconv.rs
+++ b/src/libstd/num/strconv.rs
@@ -552,8 +552,18 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+
                 // Detect overflow by comparing to last value, except
                 // if we've not seen any non-zero digits.
                 if last_accum != _0 {
-                    if accum_positive && accum <= last_accum { return None; }
-                    if !accum_positive && accum >= last_accum { return None; }
+                    if accum_positive && accum <= last_accum { return NumStrConv::inf(); }
+                    if !accum_positive && accum >= last_accum { return NumStrConv::neg_inf(); }
+
+                    // Detect overflow by reversing the shift-and-add proccess
+                    if accum_positive &&
+                        (last_accum != ((accum - cast(digit as int))/radix_gen.clone())) {
+                        return NumStrConv::inf();
+                    }
+                    if !accum_positive &&
+                        (last_accum != ((accum + cast(digit as int))/radix_gen.clone())) {
+                        return NumStrConv::neg_inf();
+                    }
                 }
                 last_accum = accum.clone();
             }
@@ -597,8 +607,8 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+
                     }
 
                     // Detect overflow by comparing to last value
-                    if accum_positive && accum < last_accum { return None; }
-                    if !accum_positive && accum > last_accum { return None; }
+                    if accum_positive && accum < last_accum { return NumStrConv::inf(); }
+                    if !accum_positive && accum > last_accum { return NumStrConv::neg_inf(); }
                     last_accum = accum.clone();
                 }
                 None => match c {
@@ -702,6 +712,23 @@ mod test {
                                              ExpNone, false, false);
         assert_eq!(n, None);
     }
+
+    #[test]
+    fn from_str_issue7588() {
+        let u : Option<u8> = from_str_common("1000", 10, false, false, false,
+                                            ExpNone, false, false);
+        assert_eq!(u, None);
+        let s : Option<i16> = from_str_common("80000", 10, false, false, false,
+                                             ExpNone, false, false);
+        assert_eq!(s, None);
+        let f : Option<f32> = from_str_common(
+            "10000000000000000000000000000000000000000", 10, false, false, false,
+            ExpNone, false, false);
+        assert_eq!(f, NumStrConv::inf())
+        let fe : Option<f32> = from_str_common("1e40", 10, false, false, false,
+                                            ExpDec, false, false);
+        assert_eq!(fe, NumStrConv::inf())
+    }
 }
 
 #[cfg(test)]