This is an automated email from the ASF dual-hosted git repository. tustvold pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/master by this push: new 66883638d making use of checked multiplication and addition to avoid silent overflow (#3886) 66883638d is described below commit 66883638dad39ad5ad54b105e87ec73eed8f8123 Author: Alex Huang <huangweijun1...@gmail.com> AuthorDate: Tue Mar 21 11:39:18 2023 +0100 making use of checked multiplication and addition to avoid silent overflow (#3886) --- arrow-cast/src/cast.rs | 22 ++++++++++++++++++++++ arrow-cast/src/parse.rs | 27 ++++++++++++++++----------- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/arrow-cast/src/cast.rs b/arrow-cast/src/cast.rs index 1bd502740..72d1bc1cb 100644 --- a/arrow-cast/src/cast.rs +++ b/arrow-cast/src/cast.rs @@ -5273,6 +5273,28 @@ mod tests { IntervalUnit::DayTime, r#"Cast error: Cannot cast 1 day 1.5 milliseconds to IntervalDayTime because the nanos part isn't multiple of milliseconds"# ); + + // overflow + test_unsafe_string_to_interval_err!( + vec![Some(format!( + "{} century {} year {} month", + i64::MAX - 2, + i64::MAX - 2, + i64::MAX - 2 + ))], + IntervalUnit::DayTime, + r#"Parser error: Parsed interval field value out of range: 11068046444225730000000 months 331764692165666300000000 days 28663672503769583000000000000000000000 nanos"# + ); + test_unsafe_string_to_interval_err!( + vec![Some(format!( + "{} year {} month {} day", + i64::MAX - 2, + i64::MAX - 2, + i64::MAX - 2 + ))], + IntervalUnit::MonthDayNano, + r#"Parser error: Parsed interval field value out of range: 110680464442257310000 months 3043712772162076000000 days 262179884170819100000000000000000000 nanos"# + ); } #[test] diff --git a/arrow-cast/src/parse.rs b/arrow-cast/src/parse.rs index 30cebb4bf..ced951ca8 100644 --- a/arrow-cast/src/parse.rs +++ b/arrow-cast/src/parse.rs @@ -838,13 +838,13 @@ fn parse_interval(leading_field: &str, value: &str) -> Result<MonthDayNano, Arro match it { IntervalType::Century => { - align_interval_parts(interval_period * 1200_f64, 0.0, 0.0) + align_interval_parts(interval_period.mul_checked(1200_f64)?, 0.0, 0.0) } IntervalType::Decade => { - align_interval_parts(interval_period * 120_f64, 0.0, 0.0) + align_interval_parts(interval_period.mul_checked(120_f64)?, 0.0, 0.0) } IntervalType::Year => { - align_interval_parts(interval_period * 12_f64, 0.0, 0.0) + align_interval_parts(interval_period.mul_checked(12_f64)?, 0.0, 0.0) } IntervalType::Month => align_interval_parts(interval_period, 0.0, 0.0), IntervalType::Week => align_interval_parts(0.0, interval_period * 7_f64, 0.0), @@ -852,16 +852,21 @@ fn parse_interval(leading_field: &str, value: &str) -> Result<MonthDayNano, Arro IntervalType::Hour => Ok(( 0, 0, - (interval_period * SECONDS_PER_HOUR * NANOS_PER_SECOND) as i64, + (interval_period.mul_checked(SECONDS_PER_HOUR * NANOS_PER_SECOND))? + as i64, + )), + IntervalType::Minute => Ok(( + 0, + 0, + (interval_period.mul_checked(60_f64 * NANOS_PER_SECOND))? as i64, + )), + IntervalType::Second => Ok(( + 0, + 0, + (interval_period.mul_checked(NANOS_PER_SECOND))? as i64, )), - IntervalType::Minute => { - Ok((0, 0, (interval_period * 60_f64 * NANOS_PER_SECOND) as i64)) - } - IntervalType::Second => { - Ok((0, 0, (interval_period * NANOS_PER_SECOND) as i64)) - } IntervalType::Millisecond => { - Ok((0, 0, (interval_period * 1_000_000f64) as i64)) + Ok((0, 0, (interval_period.mul_checked(1_000_000f64))? as i64)) } } };