@@ -80,7 +80,14 @@ pub fn from_str(string: &str, allow_suffixes: bool) -> Result<Duration, String>
8080
8181 // Allow non-negative durations (-0 is fine), and infinity.
8282 let num = match num {
83- ExtendedBigDecimal :: BigDecimal ( bd) if !bd. is_negative ( ) => bd,
83+ ExtendedBigDecimal :: BigDecimal ( bd) if !bd. is_negative ( ) => {
84+ if bd. fractional_digit_count ( ) <= -20 {
85+ // bd >= 10^20 > u64::MAX -- early return to avoid
86+ // potentially expensive to-nanoseconds conversion
87+ return Ok ( Duration :: MAX ) ;
88+ }
89+ bd
90+ }
8491 ExtendedBigDecimal :: MinusZero => 0 . into ( ) ,
8592 ExtendedBigDecimal :: Infinity => return Ok ( Duration :: MAX ) ,
8693 _ => return Err ( format ! ( "invalid time interval {}" , string. quote( ) ) ) ,
@@ -128,6 +135,7 @@ mod tests {
128135 fn test_overflow ( ) {
129136 // u64 seconds overflow (in Duration)
130137 assert_eq ! ( from_str( "9223372036854775808d" , true ) , Ok ( Duration :: MAX ) ) ;
138+ assert_eq ! ( from_str( "1e6666666666668320" , true ) , Ok ( Duration :: MAX ) ) ;
131139 // ExtendedBigDecimal overflow
132140 assert_eq ! ( from_str( "1e92233720368547758080" , false ) , Ok ( Duration :: MAX ) ) ;
133141 assert_eq ! ( from_str( "1e92233720368547758080" , false ) , Ok ( Duration :: MAX ) ) ;
0 commit comments