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))
             }
         }
     };

Reply via email to