Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2fbfa7e3 authored by Hsin-chen Chuang's avatar Hsin-chen Chuang
Browse files

floss: Introduce LTCheckedPtr/Mut (Lifetime-checked pointer) to topshim

The wrapper holds the raw pointer and clones the lifetime from the
pointing object, which forces the compiler to check and fail when the
wrapper lives longer than the data.

Bug: 249687132
Tag: #floss
Test: build.py --target test; Deployed to CB and checked basic features
Change-Id: I07a81a0d8b262d0d0008709164d460fa7e86b0e1
parent 1d3620c2
Loading
Loading
Loading
Loading
+15 −14
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@

use crate::bindings::root as bindings;
use crate::topstack::get_dispatchers;
use crate::utils::{LTCheckedPtr, LTCheckedPtrMut};
use num_traits::cast::{FromPrimitive, ToPrimitive};
use std::cmp;
use std::convert::TryFrom;
@@ -496,10 +497,10 @@ impl BluetoothProperty {
    }

    /// Given a mutable array, this will copy the data to that array and return a
    /// pointer to it.
    /// LTCheckedPtrMut to it.
    ///
    /// The lifetime of the returned pointer is tied to that of the slice given.
    fn get_data_ptr<'a>(&'a self, data: &'a mut [u8]) -> *mut u8 {
    fn get_data_ptr<'a>(&'a self, data: &'a mut [u8]) -> LTCheckedPtrMut<'a, u8> {
        let len = self.get_len();
        match &*self {
            BluetoothProperty::BdName(name) => {
@@ -601,7 +602,7 @@ impl BluetoothProperty {
            BluetoothProperty::Unknown() => (),
        };

        data.as_mut_ptr()
        data.into()
    }
}

@@ -686,7 +687,7 @@ impl From<BluetoothProperty> for (Box<[u8]>, bindings::bt_property_t) {
        let prop = bindings::bt_property_t {
            type_: prop.get_type().into(),
            len: prop.get_len() as i32,
            val: prop.get_data_ptr(&mut data) as *mut std::os::raw::c_void,
            val: prop.get_data_ptr(&mut data).cast_into::<std::os::raw::c_void>(),
        };

        (data, prop)
@@ -1042,7 +1043,7 @@ impl BluetoothInterface {
            le_rand_cb: Some(le_rand_cb),
        });

        let rawcb: *mut bindings::bt_callbacks_t = &mut *callbacks;
        let cb_ptr = LTCheckedPtrMut::from(&mut callbacks);

        let (guest_mode, is_common_criteria_mode, config_compare_result, is_atv) =
            (false, false, 0, false);
@@ -1050,7 +1051,7 @@ impl BluetoothInterface {
        let init = ccall!(
            self,
            init,
            rawcb,
            cb_ptr.into(),
            guest_mode,
            is_common_criteria_mode,
            config_compare_result,
@@ -1088,7 +1089,8 @@ impl BluetoothInterface {

    pub fn set_adapter_property(&self, prop: BluetoothProperty) -> i32 {
        let prop_pair: (Box<[u8]>, bindings::bt_property_t) = prop.into();
        ccall!(self, set_adapter_property, &prop_pair.1)
        let prop_ptr = LTCheckedPtr::from_ref(&prop_pair.1);
        ccall!(self, set_adapter_property, prop_ptr.into())
    }

    pub fn get_remote_device_properties(&self, addr: &mut RawAddress) -> i32 {
@@ -1112,8 +1114,9 @@ impl BluetoothInterface {
        prop: BluetoothProperty,
    ) -> i32 {
        let prop_pair: (Box<[u8]>, bindings::bt_property_t) = prop.into();
        let prop_ptr = LTCheckedPtr::from_ref(&prop_pair.1);
        let ffi_addr = cast_to_ffi_address!(addr as *const RawAddress);
        ccall!(self, set_remote_device_property, ffi_addr, &prop_pair.1)
        ccall!(self, set_remote_device_property, ffi_addr, prop_ptr.into())
    }

    pub fn get_remote_services(&self, addr: &mut RawAddress, transport: BtTransport) -> i32 {
@@ -1158,7 +1161,8 @@ impl BluetoothInterface {
        pin_code: &mut BtPinCode,
    ) -> i32 {
        let ffi_addr = cast_to_const_ffi_address!(addr as *const RawAddress);
        ccall!(self, pin_reply, ffi_addr, accept, pin_len, pin_code)
        let pin_code_ptr = LTCheckedPtrMut::from_ref(pin_code);
        ccall!(self, pin_reply, ffi_addr, accept, pin_len, pin_code_ptr.into())
    }

    pub fn ssp_reply(
@@ -1222,11 +1226,8 @@ impl BluetoothInterface {
        profile: SupportedProfiles,
    ) -> *const std::os::raw::c_void {
        let cprofile = Vec::<u8>::from(profile);
        ccall!(
            self,
            get_profile_interface,
            cprofile.as_slice().as_ptr() as *const std::os::raw::c_char
        )
        let cprofile_ptr = LTCheckedPtr::from(&cprofile);
        ccall!(self, get_profile_interface, cprofile_ptr.cast_into::<std::os::raw::c_char>())
    }

    pub(crate) fn as_raw_ptr(&self) -> *const u8 {
+2 −0
Original line number Diff line number Diff line
@@ -31,3 +31,5 @@ pub mod metrics;
pub mod profiles;

pub mod topstack;

mod utils;
+20 −19
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ use crate::profiles::gatt::bindings::{
    BleAdvertiserInterface, BleScannerInterface,
};
use crate::topstack::get_dispatchers;
use crate::utils::LTCheckedPtr;
use crate::{cast_to_ffi_address, ccall, deref_ffi_address, mutcxxcall};

use num_traits::cast::{FromPrimitive, ToPrimitive};
@@ -1121,12 +1122,8 @@ impl GattClient {
    }

    pub fn search_service(&self, conn_id: i32, filter_uuid: Option<Uuid>) -> BtStatus {
        let filter_uuid_ptr = match filter_uuid {
            None => std::ptr::null(),
            Some(uuid) => &uuid,
        };

        BtStatus::from(ccall!(self, search_service, conn_id, filter_uuid_ptr))
        let filter_uuid_ptr = LTCheckedPtr::from(&filter_uuid);
        BtStatus::from(ccall!(self, search_service, conn_id, filter_uuid_ptr.into()))
    }

    pub fn btif_gattc_discover_service_by_uuid(&self, conn_id: i32, uuid: &Uuid) {
@@ -1164,6 +1161,7 @@ impl GattClient {
        auth_req: i32,
        value: &[u8],
    ) -> BtStatus {
        let value_ptr = LTCheckedPtr::from(value);
        BtStatus::from(ccall!(
            self,
            write_characteristic,
@@ -1171,7 +1169,7 @@ impl GattClient {
            handle,
            write_type,
            auth_req,
            value.as_ptr(),
            value_ptr.into(),
            value.len()
        ))
    }
@@ -1187,13 +1185,14 @@ impl GattClient {
        auth_req: i32,
        value: &[u8],
    ) -> BtStatus {
        let value_ptr = LTCheckedPtr::from(value);
        BtStatus::from(ccall!(
            self,
            write_descriptor,
            conn_id,
            handle,
            auth_req,
            value.as_ptr(),
            value_ptr.into(),
            value.len()
        ))
    }
@@ -1320,7 +1319,8 @@ impl GattServer {
    }

    pub fn add_service(&self, server_if: i32, service: &[BtGattDbElement]) -> BtStatus {
        BtStatus::from(ccall!(self, add_service, server_if, service.as_ptr(), service.len()))
        let service_ptr = LTCheckedPtr::from(service);
        BtStatus::from(ccall!(self, add_service, server_if, service_ptr.into(), service.len()))
    }

    pub fn stop_service(&self, server_if: i32, service_handle: i32) -> BtStatus {
@@ -1339,6 +1339,7 @@ impl GattServer {
        confirm: i32,
        value: &[u8],
    ) -> BtStatus {
        let value_ptr = LTCheckedPtr::from(value);
        BtStatus::from(ccall!(
            self,
            send_indication,
@@ -1346,7 +1347,7 @@ impl GattServer {
            attribute_handle,
            conn_id,
            confirm,
            value.as_ptr(),
            value_ptr.into(),
            value.len()
        ))
    }
@@ -1727,7 +1728,7 @@ impl Gatt {
            panic!("Tried to set dispatcher for GattAdvCallbacks but it already existed");
        }

        let mut gatt_client_callbacks = Box::new(btgatt_client_callbacks_t {
        let gatt_client_callbacks = Box::new(btgatt_client_callbacks_t {
            register_client_cb: Some(gc_register_client_cb),
            open_cb: Some(gc_open_cb),
            close_cb: Some(gc_close_cb),
@@ -1752,7 +1753,7 @@ impl Gatt {
            services_added_cb: None,
        });

        let mut gatt_server_callbacks = Box::new(btgatt_server_callbacks_t {
        let gatt_server_callbacks = Box::new(btgatt_server_callbacks_t {
            register_server_cb: Some(gs_register_server_cb),
            connection_cb: Some(gs_connection_cb),
            service_added_cb: Some(gs_service_added_cb),
@@ -1771,23 +1772,23 @@ impl Gatt {
            conn_updated_cb: Some(gs_conn_updated_cb),
        });

        let mut gatt_scanner_callbacks = Box::new(btgatt_scanner_callbacks_t {
        let gatt_scanner_callbacks = Box::new(btgatt_scanner_callbacks_t {
            scan_result_cb: None,
            batchscan_reports_cb: None,
            batchscan_threshold_cb: None,
            track_adv_event_cb: None,
        });

        let mut callbacks = Box::new(btgatt_callbacks_t {
        let callbacks = Box::new(btgatt_callbacks_t {
            size: std::mem::size_of::<btgatt_callbacks_t>(),
            client: &mut *gatt_client_callbacks,
            server: &mut *gatt_server_callbacks,
            scanner: &mut *gatt_scanner_callbacks,
            client: &*gatt_client_callbacks,
            server: &*gatt_server_callbacks,
            scanner: &*gatt_scanner_callbacks,
        });

        let rawcb = &mut *callbacks;
        let cb_ptr = LTCheckedPtr::from(&callbacks);

        let init = ccall!(self, init, rawcb);
        let init = ccall!(self, init, cb_ptr.into());
        self.is_init = init == 0;
        self.callbacks = Some(callbacks);
        self.gatt_client_callbacks = Some(gatt_client_callbacks);
+5 −3
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ use crate::bindings::root as bindings;
use crate::btif::{BluetoothInterface, BtStatus, RawAddress, SupportedProfiles, ToggleableProfile};
use crate::profiles::hid_host::bindings::bthh_interface_t;
use crate::topstack::get_dispatchers;
use crate::utils::LTCheckedPtrMut;
use crate::{cast_to_ffi_address, ccall, deref_ffi_address};

use num_traits::cast::{FromPrimitive, ToPrimitive};
@@ -171,9 +172,9 @@ impl ToggleableProfile for HidHost {
    }

    fn enable(&mut self) -> bool {
        let rawcb = &mut **self.callbacks.as_mut().unwrap();
        let cb_ptr = LTCheckedPtrMut::from(self.callbacks.as_mut().unwrap());

        let init = ccall!(self, init, rawcb);
        let init = ccall!(self, init, cb_ptr.into());
        self.is_init = BtStatus::from(init) == BtStatus::Success;
        self._is_enabled = self.is_init;
        true
@@ -309,12 +310,13 @@ impl HidHost {
        report: &mut [u8],
    ) -> BtStatus {
        let ffi_addr = cast_to_ffi_address!(addr as *mut RawAddress);
        let report_ptr = LTCheckedPtrMut::from(report);
        BtStatus::from(ccall!(
            self,
            set_report,
            ffi_addr,
            bindings::bthh_report_type_t::from(report_type),
            report.as_mut_ptr() as *mut std::os::raw::c_char
            report_ptr.cast_into::<std::os::raw::c_char>()
        ))
    }

+12 −7
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ use crate::btif::{
    SupportedProfiles, Uuid,
};
use crate::topstack::get_dispatchers;
use crate::utils::{LTCheckedPtr, LTCheckedPtrMut};
use crate::{cast_to_ffi_address, ccall, deref_const_ffi_address};
use topshim_macros::cb_variant;

@@ -252,18 +253,21 @@ impl From<bindings::bluetooth_sdp_record> for BtSdpRecord {

impl BtSdpRecord {
    fn convert_header<'a>(hdr: &'a mut BtSdpHeaderOverlay) -> bindings::bluetooth_sdp_hdr_overlay {
        let srv_name_ptr = LTCheckedPtrMut::from(&mut hdr.hdr.service_name);
        let user1_ptr = LTCheckedPtr::from(&hdr.user1_data);
        let user2_ptr = LTCheckedPtr::from(&hdr.user2_data);
        bindings::bluetooth_sdp_hdr_overlay {
            type_: hdr.hdr.sdp_type.to_u32().unwrap(),
            uuid: hdr.hdr.uuid,
            service_name_length: hdr.hdr.service_name_length,
            service_name: hdr.hdr.service_name.as_mut_ptr() as *mut c_char,
            service_name: srv_name_ptr.cast_into::<c_char>(),
            rfcomm_channel_number: hdr.hdr.rfcomm_channel_number,
            l2cap_psm: hdr.hdr.l2cap_psm,
            profile_version: hdr.hdr.profile_version,
            user1_ptr_len: hdr.user1_len,
            user1_ptr: hdr.user1_data.as_mut_ptr(),
            user1_ptr: user1_ptr.into(),
            user2_ptr_len: hdr.user2_len,
            user2_ptr: hdr.user2_data.as_mut_ptr(),
            user2_ptr: user2_ptr.into(),
        }
    }

@@ -382,9 +386,9 @@ impl Sdp {
            sdp_search_cb: Some(sdp_search_cb),
        });

        let rawcb = &mut *callbacks;
        let cb_ptr = LTCheckedPtrMut::from(&mut callbacks);

        let init = ccall!(self, init, rawcb);
        let init = ccall!(self, init, cb_ptr.into());
        self.is_init = BtStatus::from(init) == BtStatus::Success;
        self.callbacks = Some(callbacks);

@@ -398,8 +402,9 @@ impl Sdp {

    pub fn create_sdp_record(&self, record: &mut BtSdpRecord, handle: &mut i32) -> BtStatus {
        let mut converted = record.get_unsafe_record();
        let ptr = (&mut converted) as *mut bindings::bluetooth_sdp_record;
        BtStatus::from(ccall!(self, create_sdp_record, ptr, handle))
        let record_ptr = LTCheckedPtrMut::from_ref(&mut converted);
        let handle_ptr = LTCheckedPtrMut::from_ref(handle);
        BtStatus::from(ccall!(self, create_sdp_record, record_ptr.into(), handle_ptr.into()))
    }

    pub fn remove_sdp_record(&self, handle: i32) -> BtStatus {
Loading