@@ -103,15 +103,18 @@ fn parse_exponent_no_decimal(s: &str, j: usize) -> Result<PreciseNumber, ParseNu
103103 // displayed in decimal notation. For example, "1e-2" will be
104104 // displayed as "0.01", but "1e2" will be displayed as "100",
105105 // without a decimal point.
106- let x: BigDecimal = {
107- let parsed_decimal = s
108- . parse :: < BigDecimal > ( )
109- . map_err ( |_| ParseNumberError :: Float ) ?;
110- if parsed_decimal == BigDecimal :: zero ( ) {
111- BigDecimal :: zero ( )
112- } else {
113- parsed_decimal
114- }
106+
107+ // In ['BigDecimal'], a positive scale represents a negative power of 10.
108+ // This means the exponent value from the number must be inverted. However,
109+ // since the |i64::MIN| > |i64::MAX| (i.e. |−2^63| > |2^63−1|) inverting a
110+ // valid negative value could result in an overflow. To prevent this, we
111+ // limit the minimal value with i64::MIN + 1.
112+ let exponent = exponent. max ( i64:: MIN + 1 ) ;
113+ let base: BigInt = s[ ..j] . parse ( ) . map_err ( |_| ParseNumberError :: Float ) ?;
114+ let x = if base. is_zero ( ) {
115+ BigDecimal :: zero ( )
116+ } else {
117+ BigDecimal :: from_bigint ( base, -exponent)
115118 } ;
116119
117120 let num_integral_digits = if is_minus_zero_float ( s, & x) {
@@ -599,4 +602,18 @@ mod tests {
599602 assert_eq ! ( num_fractional_digits( "-0e-1" ) , 1 ) ;
600603 assert_eq ! ( num_fractional_digits( "-0.0e-1" ) , 2 ) ;
601604 }
605+
606+ #[ test]
607+ fn test_parse_min_exponents ( ) {
608+ // Make sure exponents <= i64::MIN do not cause errors
609+ assert ! ( "1e-9223372036854775807" . parse:: <PreciseNumber >( ) . is_ok( ) ) ;
610+ assert ! ( "1e-9223372036854775808" . parse:: <PreciseNumber >( ) . is_ok( ) ) ;
611+ }
612+
613+ #[ test]
614+ fn test_parse_max_exponents ( ) {
615+ // Make sure exponents >= i64::MAX cause errors
616+ assert ! ( "1e9223372036854775807" . parse:: <PreciseNumber >( ) . is_err( ) ) ;
617+ assert ! ( "1e9223372036854775808" . parse:: <PreciseNumber >( ) . is_err( ) ) ;
618+ }
602619}
0 commit comments