@@ -87,24 +87,24 @@ impl Config {
8787 // Extract numeric part and check if it's too large before parsing
8888 let duration_str = options. get_one :: < String > ( options:: DURATION ) . unwrap ( ) ;
8989 let duration = {
90- // Find where the unit suffix starts (first non-digit, non-decimal character)
90+ // Find where the unit suffix starts (first non-digit character)
9191 let numeric_end = duration_str
92- . find ( |c : char | !c. is_ascii_digit ( ) && c != '.' )
92+ . find ( |c : char | !c. is_ascii_digit ( ) )
9393 . unwrap_or ( duration_str. len ( ) ) ;
9494 let numeric_part = & duration_str[ ..numeric_end] ;
9595
96- // If the numeric part is huge, cap at maximum valid duration
97- // i64::MAX seconds is ~292 billion years, i64::MAX days overflows
98- if let Ok ( num) = numeric_part. parse :: < f64 > ( ) {
99- // Cap at i64::MAX / 86400 days to prevent overflow in day->second conversion
100- const MAX_SAFE_DAYS : f64 = ( i64:: MAX / 86400 ) as f64 ;
101- if num > MAX_SAFE_DAYS {
96+ // Use u128 for robust overflow detection without precision loss
97+ if let Ok ( num) = numeric_part. parse :: < u128 > ( ) {
98+ // Cap at u64::MAX to prevent overflow in any duration conversion
99+ const MAX_SAFE_DURATION_NUM : u128 = u64:: MAX as u128 ;
100+ if num > MAX_SAFE_DURATION_NUM {
102101 Duration :: from_secs ( libc:: time_t:: MAX as u64 )
103102 } else {
104103 parse_time:: from_str ( duration_str, true )
105104 . map_err ( |err| UUsageError :: new ( ExitStatus :: TimeoutFailed . into ( ) , err) ) ?
106105 }
107106 } else {
107+ // Fallback for non-integer durations like "1.5d"
108108 parse_time:: from_str ( duration_str, true )
109109 . map_err ( |err| UUsageError :: new ( ExitStatus :: TimeoutFailed . into ( ) , err) ) ?
110110 }
0 commit comments