diff options
| author | Aaron Laursen <aaronlaursen@gmail.com> | 2013-08-30 17:45:20 -0500 |
|---|---|---|
| committer | aaronlaursen <aaronlaursen@gmail.com> | 2013-09-06 13:00:34 -0500 |
| commit | caf5321eb45db8ba64d3f9f4b9e16febfeb46a4c (patch) | |
| tree | af81a2b9d507109f11e4cf5c52519914f9081ea8 /src/libstd | |
| parent | 116c034791e094840bc7bccee48113426665bc9f (diff) | |
| download | rust-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.rs | 35 |
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)] |
