@@ -63,45 +63,50 @@ struct Config {
6363/// Parse a duration string with overflow protection
6464/// Caps extremely large values at a safe maximum that works on all platforms
6565fn parse_duration_with_overflow_protection ( duration_str : & str ) -> UResult < Duration > {
66- // Pre-check for extremely large values that would overflow
67- // Only intercept if it's a simple integer + unit suffix pattern
68- let numeric_end = duration_str
69- . find ( |c : char | !c. is_ascii_digit ( ) )
70- . unwrap_or ( duration_str. len ( ) ) ;
71-
72- // Only apply overflow protection if we have a simple pattern: all digits followed by optional unit
73- if numeric_end > 0
74- && ( numeric_end == duration_str. len ( )
75- || matches ! (
76- duration_str. chars( ) . nth( numeric_end) ,
77- Some ( 's' ) | Some ( 'm' ) | Some ( 'h' ) | Some ( 'd' )
78- ) )
79- {
80- let numeric_part = & duration_str[ ..numeric_end] ;
81- let unit_suffix = & duration_str[ numeric_end..] ;
82-
83- if let Ok ( num) = numeric_part. parse :: < u128 > ( ) {
84- // Check if this would cause overflow
85- let ( _multiplier, max_safe) = match unit_suffix {
86- "" | "s" => ( 1u64 , u64:: MAX ) ,
87- "m" => ( 60 , u64:: MAX / 60 ) ,
88- "h" => ( 3600 , u64:: MAX / 3600 ) ,
89- "d" => ( 86400 , u64:: MAX / 86400 ) ,
90- _ => ( 1u64 , u64:: MAX ) , // Shouldn't reach here
91- } ;
92-
93- if num > max_safe as u128 {
94- // Cap at a safe maximum (~34 years) that works on all platforms
95- // This matches the cap in process.rs for kqueue/sigtimedwait
96- const MAX_SAFE_TIMEOUT_SECS : u64 = ( i32:: MAX / 2 ) as u64 ;
97- return Ok ( Duration :: from_secs ( MAX_SAFE_TIMEOUT_SECS ) ) ;
66+ // Try standard parsing first
67+ match parse_time:: from_str ( duration_str, true ) {
68+ Ok ( duration) => Ok ( duration) ,
69+ Err ( _) => {
70+ // If parsing fails, check if it's due to overflow with huge values
71+ // Only try to handle simple numeric patterns: digits + optional unit suffix
72+ let numeric_end = duration_str
73+ . find ( |c : char | !c. is_ascii_digit ( ) )
74+ . unwrap_or ( duration_str. len ( ) ) ;
75+
76+ if numeric_end > 0 {
77+ let numeric_part = & duration_str[ ..numeric_end] ;
78+ let unit_suffix = & duration_str[ numeric_end..] ;
79+
80+ if let Ok ( num) = numeric_part. parse :: < u128 > ( ) {
81+ // Check if this looks like a huge value that would overflow
82+ let max_safe = match unit_suffix {
83+ "" | "s" => u64:: MAX ,
84+ "m" => u64:: MAX / 60 ,
85+ "h" => u64:: MAX / 3600 ,
86+ "d" => u64:: MAX / 86400 ,
87+ _ => {
88+ return Err ( UUsageError :: new (
89+ ExitStatus :: TimeoutFailed . into ( ) ,
90+ format ! ( "invalid time interval {duration_str}" ) ,
91+ ) ) ;
92+ }
93+ } ;
94+
95+ if num > max_safe as u128 {
96+ // Cap at a safe maximum (~34 years) that works on all platforms
97+ const MAX_SAFE_TIMEOUT_SECS : u64 = ( i32:: MAX / 2 ) as u64 ;
98+ return Ok ( Duration :: from_secs ( MAX_SAFE_TIMEOUT_SECS ) ) ;
99+ }
100+ }
98101 }
102+
103+ // If it wasn't an overflow case, return the original error
104+ Err ( UUsageError :: new (
105+ ExitStatus :: TimeoutFailed . into ( ) ,
106+ format ! ( "invalid time interval {duration_str}" ) ,
107+ ) )
99108 }
100109 }
101-
102- // For all other cases (including normal values), use the standard parser
103- parse_time:: from_str ( duration_str, true )
104- . map_err ( |err| UUsageError :: new ( ExitStatus :: TimeoutFailed . into ( ) , err) )
105110}
106111
107112impl Config {
0 commit comments