From abbeb46deb3e20e792b04f2adf6d9124050efd15 Mon Sep 17 00:00:00 2001 From: Oleksandr Kylymnychenko Date: Wed, 22 Feb 2023 12:58:45 +0100 Subject: [PATCH 1/4] fix(sentry-types): switch to checked version of `from_secs_f64` This change make use of `try_from_secs_f64` (the checked version of `from_secs_f64`), avoding panics if the incoming seconds is negative, overflows Duration or not finite. Only one gotcha here, is that this function was added only in rust `1.66.0`, which is above current MSRV. --- sentry-types/src/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry-types/src/utils.rs b/sentry-types/src/utils.rs index 8f3d81e1..40d716c1 100644 --- a/sentry-types/src/utils.rs +++ b/sentry-types/src/utils.rs @@ -13,7 +13,7 @@ pub fn datetime_to_timestamp(st: &SystemTime) -> f64 { } pub fn timestamp_to_datetime(ts: f64) -> Option { - let duration = Duration::from_secs_f64(ts); + let duration = Duration::try_from_secs_f64(ts).ok()?; SystemTime::UNIX_EPOCH.checked_add(duration) } From c9875393d2ca62497dc18c30dbe9fc6b017d59e0 Mon Sep 17 00:00:00 2001 From: Oleksandr Kylymnychenko Date: Thu, 23 Feb 2023 21:13:03 +0100 Subject: [PATCH 2/4] Add check for incoming timestamp Before converting an intoming `f64` to `Duration` using `from_secs_f64`, check if if the value fits into `Duration` type and the function won't panic. Starting from Rust `1.66.0` it is possible to use `Duration::try_from_secs_f64` which returns Option and does not panic. --- sentry-types/src/utils.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sentry-types/src/utils.rs b/sentry-types/src/utils.rs index 40d716c1..d71ff8d4 100644 --- a/sentry-types/src/utils.rs +++ b/sentry-types/src/utils.rs @@ -13,7 +13,11 @@ pub fn datetime_to_timestamp(st: &SystemTime) -> f64 { } pub fn timestamp_to_datetime(ts: f64) -> Option { - let duration = Duration::try_from_secs_f64(ts).ok()?; + // Starting from Rust 1.66.0 it is possible to use `Duration::try_from_secs_f64`. + if ts == f64::INFINITY || ts < 0.0 || ts > Duration::MAX.as_secs_f64() { + return None; + } + let duration = Duration::from_secs_f64(ts); SystemTime::UNIX_EPOCH.checked_add(duration) } From daf5c1efc99d4c66684d0d1798c97f861f98ba4a Mon Sep 17 00:00:00 2001 From: Oleksandr Kylymnychenko Date: Thu, 23 Feb 2023 21:24:37 +0100 Subject: [PATCH 3/4] Add tests --- sentry-types/src/utils.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sentry-types/src/utils.rs b/sentry-types/src/utils.rs index d71ff8d4..2ae069dd 100644 --- a/sentry-types/src/utils.rs +++ b/sentry-types/src/utils.rs @@ -192,3 +192,16 @@ pub mod ts_rfc3339_opt { } } } + +#[cfg(test)] +mod tests { + use super::timestamp_to_datetime; + + #[test] + fn test_timestamp_to_datetime() { + assert!(timestamp_to_datetime(-10000.0).is_none()); + assert!(timestamp_to_datetime(f64::INFINITY).is_none()); + assert!(timestamp_to_datetime(f64::MAX).is_none()); + assert!(timestamp_to_datetime(123123123.0).is_some()); + } +} From 140f9e6dd6fd0e47e60f7975b4e3910e98a17e32 Mon Sep 17 00:00:00 2001 From: Oleksandr Kylymnychenko Date: Fri, 24 Feb 2023 10:38:51 +0100 Subject: [PATCH 4/4] use try_from_secs_f64 func --- sentry-types/src/utils.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sentry-types/src/utils.rs b/sentry-types/src/utils.rs index 2ae069dd..aa3cd2a0 100644 --- a/sentry-types/src/utils.rs +++ b/sentry-types/src/utils.rs @@ -13,11 +13,7 @@ pub fn datetime_to_timestamp(st: &SystemTime) -> f64 { } pub fn timestamp_to_datetime(ts: f64) -> Option { - // Starting from Rust 1.66.0 it is possible to use `Duration::try_from_secs_f64`. - if ts == f64::INFINITY || ts < 0.0 || ts > Duration::MAX.as_secs_f64() { - return None; - } - let duration = Duration::from_secs_f64(ts); + let duration = Duration::try_from_secs_f64(ts).ok()?; SystemTime::UNIX_EPOCH.checked_add(duration) }