Skip to content

Commit 690994e

Browse files
Restore working overflow protection code from before rebase
1 parent 6a71a45 commit 690994e

File tree

1 file changed

+36
-41
lines changed

1 file changed

+36
-41
lines changed

src/uu/timeout/src/timeout.rs

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -63,50 +63,45 @@ struct Config {
6363
/// Parse a duration string with overflow protection
6464
/// Caps extremely large values at a safe maximum that works on all platforms
6565
fn parse_duration_with_overflow_protection(duration_str: &str) -> UResult<Duration> {
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-
}
101-
}
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}"),
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')
10778
))
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));
98+
}
10899
}
109100
}
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))
110105
}
111106

112107
impl Config {

0 commit comments

Comments
 (0)