Skip to content

Commit 25f3b29

Browse files
committed
auto merge of #9010 : aaronlaursen/rust/master, r=alexcrichton
Here's a fix for issue #7588, "Overflow handling of from_str methods is broken". The integer overflow issues are taken care of by checking to see if the multiply-by-radix-and-add-next-digit process is reversible. If it overflowed, then some information is lost and the process is irreversible, in which case, None is returned. Floats now consistently return Some(Inf) of Some(-Inf) on overflow thanks to a call to NumStrConv::inf() and NumStrConv::neg_inf() respectively when the overflow is detected (which yields a value of None in the case of ints and uints anyway). This is my first contribution to Rust, and my first time using the language in general, so any and all feedback is appreciated.
2 parents 12bca20 + caf5321 commit 25f3b29

File tree

1 file changed

+31
-4
lines changed

1 file changed

+31
-4
lines changed

src/libstd/num/strconv.rs

+31-4
Original file line numberDiff line numberDiff line change
@@ -552,8 +552,18 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+
552552
// Detect overflow by comparing to last value, except
553553
// if we've not seen any non-zero digits.
554554
if last_accum != _0 {
555-
if accum_positive && accum <= last_accum { return None; }
556-
if !accum_positive && accum >= last_accum { return None; }
555+
if accum_positive && accum <= last_accum { return NumStrConv::inf(); }
556+
if !accum_positive && accum >= last_accum { return NumStrConv::neg_inf(); }
557+
558+
// Detect overflow by reversing the shift-and-add proccess
559+
if accum_positive &&
560+
(last_accum != ((accum - cast(digit as int))/radix_gen.clone())) {
561+
return NumStrConv::inf();
562+
}
563+
if !accum_positive &&
564+
(last_accum != ((accum + cast(digit as int))/radix_gen.clone())) {
565+
return NumStrConv::neg_inf();
566+
}
557567
}
558568
last_accum = accum.clone();
559569
}
@@ -597,8 +607,8 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+
597607
}
598608

599609
// Detect overflow by comparing to last value
600-
if accum_positive && accum < last_accum { return None; }
601-
if !accum_positive && accum > last_accum { return None; }
610+
if accum_positive && accum < last_accum { return NumStrConv::inf(); }
611+
if !accum_positive && accum > last_accum { return NumStrConv::neg_inf(); }
602612
last_accum = accum.clone();
603613
}
604614
None => match c {
@@ -702,6 +712,23 @@ mod test {
702712
ExpNone, false, false);
703713
assert_eq!(n, None);
704714
}
715+
716+
#[test]
717+
fn from_str_issue7588() {
718+
let u : Option<u8> = from_str_common("1000", 10, false, false, false,
719+
ExpNone, false, false);
720+
assert_eq!(u, None);
721+
let s : Option<i16> = from_str_common("80000", 10, false, false, false,
722+
ExpNone, false, false);
723+
assert_eq!(s, None);
724+
let f : Option<f32> = from_str_common(
725+
"10000000000000000000000000000000000000000", 10, false, false, false,
726+
ExpNone, false, false);
727+
assert_eq!(f, NumStrConv::inf())
728+
let fe : Option<f32> = from_str_common("1e40", 10, false, false, false,
729+
ExpDec, false, false);
730+
assert_eq!(fe, NumStrConv::inf())
731+
}
705732
}
706733

707734
#[cfg(test)]

0 commit comments

Comments
 (0)