forked from mirrors/gstreamer-rs
gst/ClockTime: panic building from GST_CLOCK_TIME_NONE
Using `ClockTime::from_nseconds` it was possible to build a valid `ClockTime` which would match `GST_CLOCK_TIME_NONE` when passed to the C API, leading to unexpected behaviour as `GST_CLOCK_TIME_NONE` is represented as an `Option::<ClockTime>::None` in Rust. This commit panics when this function is called with `GST_CLOCK_TIME_NONE` (defined as `u64::MAX`). This is similar to what happens when calling other `ClockTime` constructors (e.g. `from_seconds`) with too large a value: the internal multiplication overflows leading to a panic.
This commit is contained in:
parent
b8e1c25c85
commit
55ef309b16
1 changed files with 61 additions and 4 deletions
|
@ -50,23 +50,68 @@ impl ClockTime {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rustdoc-stripper-ignore-next
|
||||||
|
/// Builds a new `ClockTime` which value is the given number of seconds.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the resulting duration in nanoseconds exceeds the `u64` range.
|
||||||
|
#[track_caller]
|
||||||
pub const fn from_seconds(seconds: u64) -> Self {
|
pub const fn from_seconds(seconds: u64) -> Self {
|
||||||
skip_assert_initialized!();
|
skip_assert_initialized!();
|
||||||
ClockTime(seconds * Self::SECOND.0)
|
// `Option::expect` is not `const` as of rustc 1.63.0.
|
||||||
|
ClockTime(match seconds.checked_mul(Self::SECOND.0) {
|
||||||
|
Some(res) => res,
|
||||||
|
None => panic!("Out of `ClockTime` range"),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rustdoc-stripper-ignore-next
|
||||||
|
/// Builds a new `ClockTime` which value is the given number of milliseconds.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the resulting duration in nanoseconds exceeds the `u64` range.
|
||||||
|
#[track_caller]
|
||||||
pub const fn from_mseconds(mseconds: u64) -> Self {
|
pub const fn from_mseconds(mseconds: u64) -> Self {
|
||||||
skip_assert_initialized!();
|
skip_assert_initialized!();
|
||||||
ClockTime(mseconds * Self::MSECOND.0)
|
// `Option::expect` is not `const` as of rustc 1.63.0.
|
||||||
|
ClockTime(match mseconds.checked_mul(Self::MSECOND.0) {
|
||||||
|
Some(res) => res,
|
||||||
|
None => panic!("Out of `ClockTime` range"),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rustdoc-stripper-ignore-next
|
||||||
|
/// Builds a new `ClockTime` which value is the given number of microseconds.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the resulting duration in nanoseconds exceeds the `u64` range.
|
||||||
|
#[track_caller]
|
||||||
pub const fn from_useconds(useconds: u64) -> Self {
|
pub const fn from_useconds(useconds: u64) -> Self {
|
||||||
skip_assert_initialized!();
|
skip_assert_initialized!();
|
||||||
ClockTime(useconds * Self::USECOND.0)
|
// `Option::expect` is not `const` as of rustc 1.63.0.
|
||||||
|
ClockTime(match useconds.checked_mul(Self::USECOND.0) {
|
||||||
|
Some(res) => res,
|
||||||
|
None => panic!("Out of `ClockTime` range"),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rustdoc-stripper-ignore-next
|
||||||
|
/// Builds a new `ClockTime` which value is the given number of nanoseconds.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the requested duration equals `GST_CLOCK_TIME_NONE`
|
||||||
|
/// (`u64::MAX`).
|
||||||
|
#[track_caller]
|
||||||
pub const fn from_nseconds(nseconds: u64) -> Self {
|
pub const fn from_nseconds(nseconds: u64) -> Self {
|
||||||
skip_assert_initialized!();
|
skip_assert_initialized!();
|
||||||
|
assert!(
|
||||||
|
nseconds != ffi::GST_CLOCK_TIME_NONE,
|
||||||
|
"Attempt to build a `ClockTime` with value `GST_CLOCK_TIME_NONE`",
|
||||||
|
);
|
||||||
ClockTime(nseconds * Self::NSECOND.0)
|
ClockTime(nseconds * Self::NSECOND.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,7 +158,7 @@ impl glib::value::ToValue for ClockTime {
|
||||||
if gct == ffi::GST_CLOCK_TIME_NONE {
|
if gct == ffi::GST_CLOCK_TIME_NONE {
|
||||||
crate::warning!(
|
crate::warning!(
|
||||||
crate::CAT_RUST,
|
crate::CAT_RUST,
|
||||||
"converting a defined `ClockTime` with value `ffi::GST_CLOCK_TIME_NONE` to `Value`, this is probably not what you wanted.",
|
"converting a defined `ClockTime` with value `GST_CLOCK_TIME_NONE` to `Value`, this is probably not what you wanted.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
unsafe { glib::gobject_ffi::g_value_set_uint64(value.to_glib_none_mut().0, gct) }
|
unsafe { glib::gobject_ffi::g_value_set_uint64(value.to_glib_none_mut().0, gct) }
|
||||||
|
@ -864,4 +909,16 @@ mod tests {
|
||||||
.sum();
|
.sum();
|
||||||
assert_eq!(s, ClockTime::from_seconds(3));
|
assert_eq!(s, ClockTime::from_seconds(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn attempt_to_build_from_clock_time_none() {
|
||||||
|
let _ = ClockTime::from_nseconds(ffi::GST_CLOCK_TIME_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn attempt_to_build_from_u64max() {
|
||||||
|
let _ = ClockTime::from_nseconds(u64::MAX);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue