From b3ebd4c6b577fa93b9cd7621f9043438af7cdf7a Mon Sep 17 00:00:00 2001 From: Finn Bear Date: Tue, 25 Apr 2023 15:00:31 -0700 Subject: [PATCH] Bugfix - Fix overflow in duration parser (#1865) --- lib/src/sql/duration.rs | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/lib/src/sql/duration.rs b/lib/src/sql/duration.rs index 2a60e70a..1cbb67d6 100644 --- a/lib/src/sql/duration.rs +++ b/lib/src/sql/duration.rs @@ -308,22 +308,22 @@ pub fn duration(i: &str) -> IResult<&str, Duration> { fn duration_raw(i: &str) -> IResult<&str, Duration> { let (i, v) = part(i)?; let (i, u) = unit(i)?; - Ok(( - i, - Duration(match u { - "ns" => time::Duration::from_nanos(v), - "µs" => time::Duration::from_micros(v), - "us" => time::Duration::from_micros(v), - "ms" => time::Duration::from_millis(v), - "s" => time::Duration::from_secs(v), - "m" => time::Duration::from_secs(v * SECONDS_PER_MINUTE), - "h" => time::Duration::from_secs(v * SECONDS_PER_HOUR), - "d" => time::Duration::from_secs(v * SECONDS_PER_DAY), - "w" => time::Duration::from_secs(v * SECONDS_PER_WEEK), - "y" => time::Duration::from_secs(v * SECONDS_PER_YEAR), - _ => time::Duration::ZERO, - }), - )) + + let std_duration = match u { + "ns" => Some(time::Duration::from_nanos(v)), + "µs" => Some(time::Duration::from_micros(v)), + "us" => Some(time::Duration::from_micros(v)), + "ms" => Some(time::Duration::from_millis(v)), + "s" => Some(time::Duration::from_secs(v)), + "m" => v.checked_mul(SECONDS_PER_MINUTE).map(time::Duration::from_secs), + "h" => v.checked_mul(SECONDS_PER_HOUR).map(time::Duration::from_secs), + "d" => v.checked_mul(SECONDS_PER_DAY).map(time::Duration::from_secs), + "w" => v.checked_mul(SECONDS_PER_WEEK).map(time::Duration::from_secs), + "y" => v.checked_mul(SECONDS_PER_YEAR).map(time::Duration::from_secs), + _ => unreachable!("shouldn't have parsed {u} as duration unit"), + }; + + std_duration.map(|d| (i, Duration(d))).ok_or(nom::Err::Error(crate::sql::Error::Parser(i))) } fn part(i: &str) -> IResult<&str, u64> { @@ -440,4 +440,11 @@ mod tests { assert_eq!("500ms", format!("{}", out)); assert_eq!(out.0, Duration::new(0, 500000000)); } + + #[test] + fn duration_overflow() { + let sql = "10000000000000000d"; + let res = duration(sql); + assert!(res.is_err()); + } }