From 3d727ca747247d6ada6736f2647d4b5ccd789e3b Mon Sep 17 00:00:00 2001 From: Ignat Loskutov Date: Thu, 25 Sep 2025 01:42:37 +0200 Subject: [PATCH] uucore: parse_time: avoid expensive `with_scale(9)` for huge inputs The conversion routine used to parse the time into a BigDecimal and normalize it into nanoseconds; however, for an input like 1e6666666666668320 it would require allocating a number with 6666666666668329 zeroes, which is obviously suboptimal (and redundant, as `Duration` uses `u64` for seconds). Fixes #8634. --- src/uucore/src/lib/features/parser/parse_time.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/uucore/src/lib/features/parser/parse_time.rs b/src/uucore/src/lib/features/parser/parse_time.rs index 3ec2e6332..60412d713 100644 --- a/src/uucore/src/lib/features/parser/parse_time.rs +++ b/src/uucore/src/lib/features/parser/parse_time.rs @@ -80,7 +80,14 @@ pub fn from_str(string: &str, allow_suffixes: bool) -> Result // Allow non-negative durations (-0 is fine), and infinity. let num = match num { - ExtendedBigDecimal::BigDecimal(bd) if !bd.is_negative() => bd, + ExtendedBigDecimal::BigDecimal(bd) if !bd.is_negative() => { + if bd.fractional_digit_count() <= -20 { + // bd >= 10^20 > u64::MAX -- early return to avoid + // potentially expensive to-nanoseconds conversion + return Ok(Duration::MAX); + } + bd + } ExtendedBigDecimal::MinusZero => 0.into(), ExtendedBigDecimal::Infinity => return Ok(Duration::MAX), _ => return Err(format!("invalid time interval {}", string.quote())), @@ -128,6 +135,7 @@ mod tests { fn test_overflow() { // u64 seconds overflow (in Duration) assert_eq!(from_str("9223372036854775808d", true), Ok(Duration::MAX)); + assert_eq!(from_str("1e6666666666668320", true), Ok(Duration::MAX)); // ExtendedBigDecimal overflow assert_eq!(from_str("1e92233720368547758080", false), Ok(Duration::MAX)); assert_eq!(from_str("1e92233720368547758080", false), Ok(Duration::MAX));