From 26117f15898a9a6bc5d9ac077ffffc2006d723d5 Mon Sep 17 00:00:00 2001 From: Erik Fong Date: Sat, 14 Mar 2026 16:26:26 -0400 Subject: [PATCH] Soundness Fix for the Trigger struct as well as added unsafe call for the QuickTune struct since the type is not yet fully represented with rusts type system, and the fact the C struct is a union that we do not enforce. --- src/bladerf.rs | 37 ++++++++++++++++++----------------- src/types/backend.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++ src/types/trigger.rs | 12 ++++++++++++ 3 files changed, 77 insertions(+), 18 deletions(-) diff --git a/src/bladerf.rs b/src/bladerf.rs index fae8f18..7e143e5 100644 --- a/src/bladerf.rs +++ b/src/bladerf.rs @@ -634,7 +634,11 @@ pub trait BladeRF: Sized + Drop { /// TODO: Get this moved over as a method to the streamer structs once we add the ability to do metadata /// /// Related `libbladerf` docs: - fn schedule_retune( + /// + /// # Safety + /// At the moment, the conversion from the [QuickTune] struct to the [bladerf_quick_tune] only handles one of the two cases it could be. + /// This neeed to be fixed. Look at the source code and the bladerf docs as if you had to use the C ABI directly. + unsafe fn schedule_retune( &self, channel: Channel, time: u64, @@ -679,7 +683,10 @@ pub trait BladeRF: Sized + Drop { /// /// /// Related `libbladerf` docs: - fn get_quick_tune(&self, channel: Channel) -> Result { + /// # Safety + /// At the moment, the conversion from the [QuickTune] struct to the [bladerf_quick_tune] only handles one of the two cases it could be. + /// This neeed to be fixed. Look at the source code and the bladerf docs as if you had to use the C ABI directly. + unsafe fn get_quick_tune(&self, channel: Channel) -> Result { let mut quick_tune = QuickTune { freqsel: 0, vcocap: 0, @@ -1063,15 +1070,9 @@ pub trait BladeRF: Sized + Drop { /// /// Related `libbladerf` docs: unsafe fn trigger_arm(&self, trigger: &Trigger, arm: bool) -> Result<()> { - let res = unsafe { - bladerf_trigger_arm( - self.get_device_ptr(), - trigger as *const Trigger as *const bladerf_trigger, - arm, - 0, - 0, - ) - }; + let brf_trigger = trigger.into(); + + let res = unsafe { bladerf_trigger_arm(self.get_device_ptr(), &brf_trigger, arm, 0, 0) }; check_res!(res); Ok(()) } @@ -1088,12 +1089,9 @@ pub trait BladeRF: Sized + Drop { /// /// Related `libbladerf` docs: unsafe fn trigger_fire(&self, trigger: &Trigger) -> Result<()> { - let res = unsafe { - bladerf_trigger_fire( - self.get_device_ptr(), - trigger as *const Trigger as *const bladerf_trigger, - ) - }; + let brf_trigger = trigger.into(); + + let res = unsafe { bladerf_trigger_fire(self.get_device_ptr(), &brf_trigger) }; check_res!(res); Ok(()) } @@ -1112,10 +1110,13 @@ pub trait BladeRF: Sized + Drop { let mut fire_requested = false; let mut resv1 = 0u64; let mut resv2 = 0u64; + + let brf_trigger = trigger.into(); + let res = unsafe { bladerf_trigger_state( self.get_device_ptr(), - trigger as *const Trigger as *const bladerf_trigger, + &brf_trigger, &mut is_armed, &mut has_fired, &mut fire_requested, diff --git a/src/types/backend.rs b/src/types/backend.rs index 5008e57..e572caf 100644 --- a/src/types/backend.rs +++ b/src/types/backend.rs @@ -34,3 +34,49 @@ impl From for bladerf_backend { value as i32 as bladerf_backend } } + +#[cfg(test)] +mod test { + use libbladerf_sys::bladerf_backend; + + use crate::Backend; + + #[test] + /// Precautionary test since the From impl has 2 casts as I believe the [bladerf_backend] type is not consistent across platforms. + fn backend_enum_conversion_test() { + let bk = Backend::Any; + let bk_int: i64 = (bk as i32).into(); + assert_eq!( + bk_int, + >::into(bk.into()) + ); + + let bk = Backend::LibUsb; + let bk_int: i64 = (bk as i32).into(); + assert_eq!( + bk_int, + >::into(bk.into()) + ); + + let bk = Backend::Linux; + let bk_int: i64 = (bk as i32).into(); + assert_eq!( + bk_int, + >::into(bk.into()) + ); + + let bk = Backend::Cypress; + let bk_int: i64 = (bk as i32).into(); + assert_eq!( + bk_int, + >::into(bk.into()) + ); + + let bk = Backend::Dummy; + let bk_int: i64 = (bk as i32).into(); + assert_eq!( + bk_int, + >::into(bk.into()) + ); + } +} diff --git a/src/types/trigger.rs b/src/types/trigger.rs index ffa4fbf..9be4b68 100644 --- a/src/types/trigger.rs +++ b/src/types/trigger.rs @@ -75,6 +75,7 @@ impl TryFrom for TriggerSignal { /// Trigger configuration /// /// Related `libbladerf` docs: +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Trigger { /// The channel associated with this trigger pub channel: Channel, @@ -86,6 +87,17 @@ pub struct Trigger { pub options: u64, } +impl From<&Trigger> for bladerf_trigger { + fn from(value: &Trigger) -> Self { + bladerf_trigger { + channel: value.channel as bladerf_channel, + role: value.role as bladerf_trigger_role, + signal: value.signal as bladerf_trigger_signal, + options: value.options, + } + } +} + impl TryFrom for Trigger { type Error = Error;