summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2022-05-06 20:15:49 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2022-05-06 20:15:49 +0000
commit6e0491e59baef723c1ef53c789584102838ae4aa (patch)
treea0f745b637ea11b191f94288857da42ae1b57013
parent01e5b50fdd3f78663256bfc680f49c988ac04bf6 (diff)
parent5ebc00c63a9b2739d36e5658500d17a648d49658 (diff)
downloaduwb-6e0491e59baef723c1ef53c789584102838ae4aa.tar.gz
Merge "Fuzz some UciNotifications sending back from HAL to UCI layer." into tm-dev
-rwxr-xr-xsrc/Android.bp1
-rw-r--r--src/fuzz/fuzzer.rs177
-rw-r--r--src/rust/event_manager/mock_event_manager.rs4
3 files changed, 146 insertions, 36 deletions
diff --git a/src/Android.bp b/src/Android.bp
index 5fca6f6..cb41ffc 100755
--- a/src/Android.bp
+++ b/src/Android.bp
@@ -205,6 +205,7 @@ rust_fuzz {
"fuzz/fuzzer.rs",
],
rustlibs: [
+ "android.hardware.uwb-V1-rust",
"libarbitrary",
"liblog_rust",
"libnum_traits",
diff --git a/src/fuzz/fuzzer.rs b/src/fuzz/fuzzer.rs
index e96a010..b30e992 100644
--- a/src/fuzz/fuzzer.rs
+++ b/src/fuzz/fuzzer.rs
@@ -1,6 +1,9 @@
#![no_main]
#![allow(missing_docs)]
+use android_hardware_uwb::aidl::android::hardware::uwb::{
+ UwbEvent::UwbEvent, UwbStatus::UwbStatus,
+};
use libfuzzer_sys::{arbitrary::Arbitrary, fuzz_target};
use log::{error, info};
use num_traits::cast::FromPrimitive;
@@ -9,12 +12,13 @@ use tokio::sync::mpsc;
use uwb_uci_packets::{
AndroidGetPowerStatsCmdBuilder, AndroidGetPowerStatsRspBuilder,
AndroidSetCountryCodeCmdBuilder, AndroidSetCountryCodeRspBuilder, DeviceResetRspBuilder,
- GetCapsInfoCmdBuilder, GetCapsInfoRspBuilder, GetDeviceInfoCmdBuilder, GetDeviceInfoRspBuilder,
- PowerStats, RangeStartCmdBuilder, RangeStartRspBuilder, RangeStopCmdBuilder,
- RangeStopRspBuilder, SessionDeinitCmdBuilder, SessionDeinitRspBuilder,
- SessionGetAppConfigCmdBuilder, SessionGetAppConfigRspBuilder, SessionGetCountCmdBuilder,
- SessionGetCountRspBuilder, SessionGetStateCmdBuilder, SessionGetStateRspBuilder,
- SessionInitCmdBuilder, SessionInitRspBuilder, SessionSetAppConfigRspBuilder, SessionState,
+ DeviceState, DeviceStatusNtfBuilder, GenericErrorBuilder, GetCapsInfoCmdBuilder,
+ GetCapsInfoRspBuilder, GetDeviceInfoCmdBuilder, GetDeviceInfoRspBuilder, PowerStats,
+ RangeStartCmdBuilder, RangeStartRspBuilder, RangeStopCmdBuilder, RangeStopRspBuilder,
+ ReasonCode, SessionDeinitCmdBuilder, SessionDeinitRspBuilder, SessionGetAppConfigCmdBuilder,
+ SessionGetAppConfigRspBuilder, SessionGetCountCmdBuilder, SessionGetCountRspBuilder,
+ SessionGetStateCmdBuilder, SessionGetStateRspBuilder, SessionInitCmdBuilder,
+ SessionInitRspBuilder, SessionSetAppConfigRspBuilder, SessionState, SessionStatusNtfBuilder,
SessionType, SessionUpdateControllerMulticastListRspBuilder, StatusCode, UciCommandPacket,
UciPacketChild, UciPacketPacket, UciVendor_9_ResponseBuilder,
};
@@ -25,36 +29,91 @@ use uwb_uci_rust::uci::{
uci_hmsgs, uci_hrcv, Dispatcher, DispatcherImpl, HalCallback, JNICommand, SyncUwbAdaptation,
};
-fn create_dispatcher_with_mock_adaptation(msgs: Vec<JNICommand>) -> Result<DispatcherImpl, UwbErr> {
+#[derive(Debug, Clone, Arbitrary)]
+enum UciNotification {
+ GenericError { status: u8 },
+ DeviceStatusNtf { device_state: u8 },
+ SessionStatusNtf { session_id: u32, session_state: u8, reason_code: u8 },
+}
+
+#[derive(Debug, Clone, Arbitrary)]
+enum Command {
+ JNICmd(JNICommand),
+ UciNtf(UciNotification),
+}
+
+fn create_dispatcher_with_mock_adaptation(
+ msgs: Vec<Command>,
+) -> Result<(DispatcherImpl, mpsc::UnboundedSender<HalCallback>), UwbErr> {
let (rsp_sender, rsp_receiver) = mpsc::unbounded_channel::<HalCallback>();
- let mut mock_adaptation = Arc::new(MockUwbAdaptation::new(rsp_sender));
+ let mut mock_adaptation = Arc::new(MockUwbAdaptation::new(rsp_sender.clone()));
let mut mock_event_manager = MockEventManager::new();
for msg in &msgs {
match msg {
- JNICommand::Enable => {
- mock_adaptation.expect_hal_open(Ok(()));
- mock_adaptation.expect_core_initialization(Ok(()));
- }
- JNICommand::Disable(_graceful) => {
- mock_adaptation.expect_hal_close(Ok(()));
- }
- _ => {
- let (cmd, rsp) = match generate_fake_cmd_rsp(msg) {
- Ok((command, response)) => (command, response),
- Err(e) => {
+ Command::JNICmd(cmd) => match cmd {
+ JNICommand::Enable => {
+ mock_adaptation.expect_hal_open(Ok(()));
+ mock_adaptation.expect_core_initialization(Ok(()));
+ }
+ JNICommand::Disable(_graceful) => {
+ break;
+ }
+ _ => {
+ let (cmd, rsp) = match generate_fake_cmd_rsp(cmd) {
+ Ok((command, response)) => (command, response),
+ Err(e) => {
+ mock_adaptation.clear_expected_calls();
+ mock_event_manager.clear_expected_calls();
+ return Err(e);
+ }
+ };
+ mock_adaptation.expect_send_uci_message(cmd, Some(rsp), None, Ok(()))
+ }
+ },
+ Command::UciNtf(ntf) => match ntf {
+ UciNotification::GenericError { status } => {
+ if StatusCode::from_u8(*status).is_none() {
mock_adaptation.clear_expected_calls();
- return Err(e);
+ mock_event_manager.clear_expected_calls();
+ return Err(UwbErr::InvalidArgs);
}
- };
- mock_adaptation.expect_send_uci_message(cmd, Some(rsp), None, Ok(()));
- }
+ mock_event_manager.expect_core_generic_error_notification_received(Ok(()))
+ }
+ UciNotification::DeviceStatusNtf { device_state } => {
+ if DeviceState::from_u8(*device_state).is_none() {
+ mock_adaptation.clear_expected_calls();
+ mock_event_manager.clear_expected_calls();
+ return Err(UwbErr::InvalidArgs);
+ }
+ mock_event_manager.expect_device_status_notification_received(Ok(()))
+ }
+ UciNotification::SessionStatusNtf {
+ session_id: _session_ids,
+ session_state,
+ reason_code,
+ } => {
+ if SessionState::from_u8(*session_state).is_none()
+ || ReasonCode::from_u8(*reason_code).is_none()
+ || *session_state == 0
+ {
+ mock_adaptation.clear_expected_calls();
+ mock_event_manager.clear_expected_calls();
+ return Err(UwbErr::InvalidArgs);
+ }
+ mock_event_manager.expect_session_status_notification_received(Ok(()))
+ }
+ },
}
}
- DispatcherImpl::new_for_testing(
- mock_event_manager,
- mock_adaptation as SyncUwbAdaptation,
- rsp_receiver,
- )
+ mock_adaptation.expect_hal_close(Ok(()));
+ Ok((
+ DispatcherImpl::new_for_testing(
+ mock_event_manager,
+ mock_adaptation as SyncUwbAdaptation,
+ rsp_receiver,
+ )?,
+ rsp_sender,
+ ))
}
fn generate_fake_cmd_rsp(
@@ -214,22 +273,68 @@ fn generate_fake_cmd_rsp(
}
}
-fn consume_command(msgs: Vec<JNICommand>) -> Result<(), UwbErr> {
- let mut mock_dispatcher = create_dispatcher_with_mock_adaptation(msgs.clone())?;
+fn consume_command(msgs: Vec<Command>) -> Result<(), UwbErr> {
+ let (mut mock_dispatcher, mut rsp_sender) =
+ create_dispatcher_with_mock_adaptation(msgs.clone())?;
for msg in msgs {
match msg {
- JNICommand::Enable => {
- mock_dispatcher.send_jni_command(JNICommand::Enable)?;
- }
- _ => {
- mock_dispatcher.block_on_jni_command(msg)?;
+ Command::JNICmd(cmd) => match cmd {
+ JNICommand::Enable => {
+ mock_dispatcher.send_jni_command(JNICommand::Enable)?;
+ }
+ JNICommand::Disable(_graceful) => {
+ break;
+ }
+ _ => {
+ mock_dispatcher.block_on_jni_command(cmd)?;
+ }
+ },
+ Command::UciNtf(ntf) => {
+ let evt = match ntf {
+ UciNotification::GenericError { status } => {
+ uci_hrcv::UciNotification::GenericError(
+ GenericErrorBuilder {
+ status: StatusCode::from_u8(status).ok_or(UwbErr::InvalidArgs)?,
+ }
+ .build(),
+ )
+ }
+ UciNotification::DeviceStatusNtf { device_state } => {
+ uci_hrcv::UciNotification::DeviceStatusNtf(
+ DeviceStatusNtfBuilder {
+ device_state: DeviceState::from_u8(device_state)
+ .ok_or(UwbErr::InvalidArgs)?,
+ }
+ .build(),
+ )
+ }
+ UciNotification::SessionStatusNtf {
+ session_id,
+ session_state,
+ reason_code,
+ } => uci_hrcv::UciNotification::SessionStatusNtf(
+ SessionStatusNtfBuilder {
+ session_id,
+ session_state: SessionState::from_u8(session_state)
+ .ok_or(UwbErr::InvalidArgs)?,
+ reason_code: ReasonCode::from_u8(reason_code)
+ .ok_or(UwbErr::InvalidArgs)?,
+ }
+ .build(),
+ ),
+ };
+ rsp_sender
+ .send(HalCallback::UciNtf(evt))
+ .unwrap_or_else(|e| error!("Error sending uci notification: {:?}", e));
}
}
}
+ mock_dispatcher.send_jni_command(JNICommand::Disable(true))?;
+ mock_dispatcher.wait_for_exit()?;
Ok(())
}
-fuzz_target!(|msgs: Vec<JNICommand>| {
+fuzz_target!(|msgs: Vec<Command>| {
match consume_command(msgs) {
Ok(()) => info!("fuzzing success"),
Err(e) => error!("fuzzing failed: {:?}", e),
diff --git a/src/rust/event_manager/mock_event_manager.rs b/src/rust/event_manager/mock_event_manager.rs
index 2a3c2cc..bc84afb 100644
--- a/src/rust/event_manager/mock_event_manager.rs
+++ b/src/rust/event_manager/mock_event_manager.rs
@@ -91,6 +91,10 @@ impl MockEventManager {
Err(Error::JniCall(JniError::Unknown))
})
}
+
+ pub fn clear_expected_calls(&self) {
+ self.expected_calls.lock().unwrap().clear();
+ }
}
#[cfg(any(test, fuzzing))]