Skip to content

Commit 1985b41

Browse files
committed
rust: time: Check various time conversion errors
When debug assertions are enabled, ensure that the time conversions are sensible. If there is an overflow on time with the assertions disabled, just use Default, which will be zero. Signed-off-by: David Brown <[email protected]>
1 parent 7dd9266 commit 1985b41

File tree

1 file changed

+26
-3
lines changed

1 file changed

+26
-3
lines changed

zephyr/src/time.rs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
//! by non-constant values). Similarly, the `fugit` crate offers constructors that aim to result
2525
//! in constants when possible, avoiding costly division operations.
2626
27-
use zephyr_sys::k_timeout_t;
27+
use zephyr_sys::{k_timeout_t, k_ticks_t};
28+
29+
use core::fmt::Debug;
2830

2931
// The system ticks, is mostly a constant, but there are some boards that use a dynamic tick
3032
// frequency, and thus need to read this at runtime.
@@ -70,14 +72,20 @@ pub struct Timeout(pub k_timeout_t);
7072
// From allows methods to take a time of various types and convert it into a Zephyr timeout.
7173
impl From<Duration> for Timeout {
7274
fn from(value: Duration) -> Timeout {
73-
Timeout(k_timeout_t { ticks: value.ticks() as i64 })
75+
let ticks: k_ticks_t = checked_cast(value.ticks());
76+
debug_assert_ne!(ticks, crate::sys::K_FOREVER.ticks);
77+
debug_assert_ne!(ticks, crate::sys::K_NO_WAIT.ticks);
78+
Timeout(k_timeout_t { ticks })
7479
}
7580
}
7681

7782
#[cfg(CONFIG_TIMEOUT_64BIT)]
7883
impl From<Instant> for Timeout {
7984
fn from(value: Instant) -> Timeout {
80-
Timeout(k_timeout_t { ticks: -1 - 1 - (value.ticks() as i64) })
85+
let ticks: k_ticks_t = checked_cast(value.ticks());
86+
debug_assert_ne!(ticks, crate::sys::K_FOREVER.ticks);
87+
debug_assert_ne!(ticks, crate::sys::K_NO_WAIT.ticks);
88+
Timeout(k_timeout_t { ticks: -1 - 1 - ticks })
8189
}
8290
}
8391

@@ -110,3 +118,18 @@ pub fn sleep<T>(timeout: T) -> Duration
110118
let rest = unsafe { crate::raw::k_sleep(timeout.0) };
111119
Duration::millis(rest as Tick)
112120
}
121+
122+
/// Convert from the Tick time type, which is unsigned, to the `k_ticks_t` type. When debug
123+
/// assertions are enabled, it will panic on overflow.
124+
fn checked_cast<I, O>(tick: I) -> O
125+
where
126+
I: TryInto<O>,
127+
I::Error: Debug,
128+
O: Default,
129+
{
130+
if cfg!(debug_assertions) {
131+
tick.try_into().expect("Overflow in time conversion")
132+
} else {
133+
tick.try_into().unwrap_or(O::default())
134+
}
135+
}

0 commit comments

Comments
 (0)