Loading libs/binder/rust/tests/parcel_fuzzer/parcel_fuzzer.rs +23 −26 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ extern crate libfuzzer_sys; mod read_utils; use crate::read_utils::get_read_funcs; use crate::read_utils::READ_FUNCS; use binder::binder_impl::{ Binder, BorrowedParcel, IBinderInternal, Parcel, Stability, TransactionCode, }; Loading @@ -34,18 +34,18 @@ use binder_random_parcel_rs::create_random_parcel; use libfuzzer_sys::arbitrary::Arbitrary; #[derive(Arbitrary, Debug)] enum ReadOperations { enum ReadOperation { SetDataPosition { pos: i32 }, GetDataSize, ReadParcelableHolder { is_vintf: bool }, ReadBasicTypes { indexes: Vec<usize> }, ReadBasicTypes { instructions: Vec<usize> }, } #[derive(Arbitrary, Debug)] enum Operations<'a> { enum Operation<'a> { Transact { code: u32, flag: u32, data: &'a [u8] }, Append { start: i32, len: i32, data1: &'a [u8], data2: &'a [u8], append_all: bool }, Read { indexes: Vec<ReadOperations>, data: &'a [u8] }, Read { read_operations: Vec<ReadOperation>, data: &'a [u8] }, } /// Interface to fuzz transact with random parcel Loading Loading @@ -102,13 +102,12 @@ fn do_append_fuzz(start: i32, len: i32, data1: &[u8], data2: &[u8], append_all: }; } fn do_read_fuzz(read_operations: Vec<ReadOperations>, data: &[u8]) { let read_funcs = get_read_funcs(); fn do_read_fuzz(read_operations: Vec<ReadOperation>, data: &[u8]) { let parcel = create_random_parcel(data); for operation in read_operations { match operation { ReadOperations::SetDataPosition { pos } => { ReadOperation::SetDataPosition { pos } => { unsafe { // Safety: Safe if pos is less than current size of the parcel. // It relies on C++ code for bound checks Loading @@ -119,12 +118,12 @@ fn do_read_fuzz(read_operations: Vec<ReadOperations>, data: &[u8]) { } } ReadOperations::GetDataSize => { ReadOperation::GetDataSize => { let data_size = parcel.get_data_size(); println!("data size from parcel: {:?}", data_size); } ReadOperations::ReadParcelableHolder { is_vintf } => { ReadOperation::ReadParcelableHolder { is_vintf } => { let stability = if is_vintf { Stability::Vintf } else { Stability::Local }; let mut holder: ParcelableHolder = ParcelableHolder::new(stability); match holder.read_from_parcel(parcel.borrowed_ref()) { Loading @@ -135,30 +134,28 @@ fn do_read_fuzz(read_operations: Vec<ReadOperations>, data: &[u8]) { } } ReadOperations::ReadBasicTypes { indexes } => { for index in indexes.iter() { let read_index = index % read_funcs.len(); read_funcs[read_index](parcel.borrowed_ref()); ReadOperation::ReadBasicTypes { instructions } => { for instruction in instructions.iter() { let read_index = instruction % READ_FUNCS.len(); READ_FUNCS[read_index](parcel.borrowed_ref()); } } } } } fuzz_target!(|operations: Vec<Operations>| { for operation in operations { fuzz_target!(|operation: Operation| { match operation { Operations::Transact { code, flag, data } => { Operation::Transact { code, flag, data } => { do_transact(code, data, flag); } Operations::Append { start, len, data1, data2, append_all } => { Operation::Append { start, len, data1, data2, append_all } => { do_append_fuzz(start, len, data1, data2, append_all); } Operations::Read { indexes, data } => { do_read_fuzz(indexes, data); } Operation::Read { read_operations, data } => { do_read_fuzz(read_operations, data); } } }); libs/binder/rust/tests/parcel_fuzzer/read_utils.rs +74 −78 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ use binderReadParcelIface::aidl::SingleDataParcelable::SingleDataParcelable; macro_rules! read_parcel_interface { ($data_type:ty) => { |parcel| { |parcel: &BorrowedParcel<'_>| { let _res = parcel.read::<$data_type>(); } }; Loading Loading @@ -57,52 +57,51 @@ impl binder::Parcelable for SomeParcelable { binder::impl_deserialize_for_parcelable!(SomeParcelable); pub fn get_read_funcs() -> Vec<Box<dyn Fn(&BorrowedParcel<'_>)>> { let read_funcs: Vec<Box<dyn Fn(&BorrowedParcel<'_>)>> = vec![ pub const READ_FUNCS: &[fn(&BorrowedParcel<'_>)] = &[ //read basic types Box::new(read_parcel_interface!(bool)), Box::new(read_parcel_interface!(i8)), Box::new(read_parcel_interface!(i32)), Box::new(read_parcel_interface!(i64)), Box::new(read_parcel_interface!(f32)), Box::new(read_parcel_interface!(f64)), Box::new(read_parcel_interface!(u16)), Box::new(read_parcel_interface!(u32)), Box::new(read_parcel_interface!(u64)), Box::new(read_parcel_interface!(String)), read_parcel_interface!(bool), read_parcel_interface!(i8), read_parcel_interface!(i32), read_parcel_interface!(i64), read_parcel_interface!(f32), read_parcel_interface!(f64), read_parcel_interface!(u16), read_parcel_interface!(u32), read_parcel_interface!(u64), read_parcel_interface!(String), //read vec of basic types Box::new(read_parcel_interface!(Vec<i8>)), Box::new(read_parcel_interface!(Vec<i32>)), Box::new(read_parcel_interface!(Vec<i64>)), Box::new(read_parcel_interface!(Vec<f32>)), Box::new(read_parcel_interface!(Vec<f64>)), Box::new(read_parcel_interface!(Vec<u16>)), Box::new(read_parcel_interface!(Vec<u32>)), Box::new(read_parcel_interface!(Vec<u64>)), Box::new(read_parcel_interface!(Vec<String>)), Box::new(read_parcel_interface!(Option<Vec<i8>>)), Box::new(read_parcel_interface!(Option<Vec<i32>>)), Box::new(read_parcel_interface!(Option<Vec<i64>>)), Box::new(read_parcel_interface!(Option<Vec<f32>>)), Box::new(read_parcel_interface!(Option<Vec<f64>>)), Box::new(read_parcel_interface!(Option<Vec<u16>>)), Box::new(read_parcel_interface!(Option<Vec<u32>>)), Box::new(read_parcel_interface!(Option<Vec<u64>>)), Box::new(read_parcel_interface!(Option<Vec<String>>)), Box::new(read_parcel_interface!(ParcelFileDescriptor)), Box::new(read_parcel_interface!(Vec<Option<ParcelFileDescriptor>>)), Box::new(read_parcel_interface!(Option<Vec<ParcelFileDescriptor>>)), Box::new(read_parcel_interface!(Option<Vec<Option<ParcelFileDescriptor>>>)), Box::new(read_parcel_interface!(SpIBinder)), Box::new(read_parcel_interface!(Vec<Option<SpIBinder>>)), Box::new(read_parcel_interface!(Option<Vec<SpIBinder>>)), Box::new(read_parcel_interface!(Option<Vec<Option<SpIBinder>>>)), Box::new(read_parcel_interface!(SomeParcelable)), Box::new(read_parcel_interface!(Vec<Option<SomeParcelable>>)), Box::new(read_parcel_interface!(Option<Vec<SomeParcelable>>)), Box::new(read_parcel_interface!(Option<Vec<Option<SomeParcelable>>>)), read_parcel_interface!(Vec<i8>), read_parcel_interface!(Vec<i32>), read_parcel_interface!(Vec<i64>), read_parcel_interface!(Vec<f32>), read_parcel_interface!(Vec<f64>), read_parcel_interface!(Vec<u16>), read_parcel_interface!(Vec<u32>), read_parcel_interface!(Vec<u64>), read_parcel_interface!(Vec<String>), read_parcel_interface!(Option<Vec<i8>>), read_parcel_interface!(Option<Vec<i32>>), read_parcel_interface!(Option<Vec<i64>>), read_parcel_interface!(Option<Vec<f32>>), read_parcel_interface!(Option<Vec<f64>>), read_parcel_interface!(Option<Vec<u16>>), read_parcel_interface!(Option<Vec<u32>>), read_parcel_interface!(Option<Vec<u64>>), read_parcel_interface!(Option<Vec<String>>), read_parcel_interface!(ParcelFileDescriptor), read_parcel_interface!(Vec<Option<ParcelFileDescriptor>>), read_parcel_interface!(Option<Vec<ParcelFileDescriptor>>), read_parcel_interface!(Option<Vec<Option<ParcelFileDescriptor>>>), read_parcel_interface!(SpIBinder), read_parcel_interface!(Vec<Option<SpIBinder>>), read_parcel_interface!(Option<Vec<SpIBinder>>), read_parcel_interface!(Option<Vec<Option<SpIBinder>>>), read_parcel_interface!(SomeParcelable), read_parcel_interface!(Vec<Option<SomeParcelable>>), read_parcel_interface!(Option<Vec<SomeParcelable>>), read_parcel_interface!(Option<Vec<Option<SomeParcelable>>>), // Fuzz read_from_parcel for AIDL generated parcelables Box::new(|parcel| { |parcel| { let mut empty_parcelable: EmptyParcelable = EmptyParcelable::default(); match empty_parcelable.read_from_parcel(parcel) { Ok(result) => result, Loading @@ -110,8 +109,8 @@ pub fn get_read_funcs() -> Vec<Box<dyn Fn(&BorrowedParcel<'_>)>> { println!("EmptyParcelable: error occurred while reading from a parcel: {:?}", e) } } }), Box::new(|parcel| { }, |parcel| { let mut single_parcelable: SingleDataParcelable = SingleDataParcelable::default(); match single_parcelable.read_from_parcel(parcel) { Ok(result) => result, Loading @@ -120,8 +119,8 @@ pub fn get_read_funcs() -> Vec<Box<dyn Fn(&BorrowedParcel<'_>)>> { e ), } }), Box::new(|parcel| { }, |parcel| { let mut generic_parcelable: GenericDataParcelable = GenericDataParcelable::default(); match generic_parcelable.read_from_parcel(parcel) { Ok(result) => result, Loading @@ -130,8 +129,5 @@ pub fn get_read_funcs() -> Vec<Box<dyn Fn(&BorrowedParcel<'_>)>> { e ), } }), }, ]; read_funcs } Loading
libs/binder/rust/tests/parcel_fuzzer/parcel_fuzzer.rs +23 −26 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ extern crate libfuzzer_sys; mod read_utils; use crate::read_utils::get_read_funcs; use crate::read_utils::READ_FUNCS; use binder::binder_impl::{ Binder, BorrowedParcel, IBinderInternal, Parcel, Stability, TransactionCode, }; Loading @@ -34,18 +34,18 @@ use binder_random_parcel_rs::create_random_parcel; use libfuzzer_sys::arbitrary::Arbitrary; #[derive(Arbitrary, Debug)] enum ReadOperations { enum ReadOperation { SetDataPosition { pos: i32 }, GetDataSize, ReadParcelableHolder { is_vintf: bool }, ReadBasicTypes { indexes: Vec<usize> }, ReadBasicTypes { instructions: Vec<usize> }, } #[derive(Arbitrary, Debug)] enum Operations<'a> { enum Operation<'a> { Transact { code: u32, flag: u32, data: &'a [u8] }, Append { start: i32, len: i32, data1: &'a [u8], data2: &'a [u8], append_all: bool }, Read { indexes: Vec<ReadOperations>, data: &'a [u8] }, Read { read_operations: Vec<ReadOperation>, data: &'a [u8] }, } /// Interface to fuzz transact with random parcel Loading Loading @@ -102,13 +102,12 @@ fn do_append_fuzz(start: i32, len: i32, data1: &[u8], data2: &[u8], append_all: }; } fn do_read_fuzz(read_operations: Vec<ReadOperations>, data: &[u8]) { let read_funcs = get_read_funcs(); fn do_read_fuzz(read_operations: Vec<ReadOperation>, data: &[u8]) { let parcel = create_random_parcel(data); for operation in read_operations { match operation { ReadOperations::SetDataPosition { pos } => { ReadOperation::SetDataPosition { pos } => { unsafe { // Safety: Safe if pos is less than current size of the parcel. // It relies on C++ code for bound checks Loading @@ -119,12 +118,12 @@ fn do_read_fuzz(read_operations: Vec<ReadOperations>, data: &[u8]) { } } ReadOperations::GetDataSize => { ReadOperation::GetDataSize => { let data_size = parcel.get_data_size(); println!("data size from parcel: {:?}", data_size); } ReadOperations::ReadParcelableHolder { is_vintf } => { ReadOperation::ReadParcelableHolder { is_vintf } => { let stability = if is_vintf { Stability::Vintf } else { Stability::Local }; let mut holder: ParcelableHolder = ParcelableHolder::new(stability); match holder.read_from_parcel(parcel.borrowed_ref()) { Loading @@ -135,30 +134,28 @@ fn do_read_fuzz(read_operations: Vec<ReadOperations>, data: &[u8]) { } } ReadOperations::ReadBasicTypes { indexes } => { for index in indexes.iter() { let read_index = index % read_funcs.len(); read_funcs[read_index](parcel.borrowed_ref()); ReadOperation::ReadBasicTypes { instructions } => { for instruction in instructions.iter() { let read_index = instruction % READ_FUNCS.len(); READ_FUNCS[read_index](parcel.borrowed_ref()); } } } } } fuzz_target!(|operations: Vec<Operations>| { for operation in operations { fuzz_target!(|operation: Operation| { match operation { Operations::Transact { code, flag, data } => { Operation::Transact { code, flag, data } => { do_transact(code, data, flag); } Operations::Append { start, len, data1, data2, append_all } => { Operation::Append { start, len, data1, data2, append_all } => { do_append_fuzz(start, len, data1, data2, append_all); } Operations::Read { indexes, data } => { do_read_fuzz(indexes, data); } Operation::Read { read_operations, data } => { do_read_fuzz(read_operations, data); } } });
libs/binder/rust/tests/parcel_fuzzer/read_utils.rs +74 −78 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ use binderReadParcelIface::aidl::SingleDataParcelable::SingleDataParcelable; macro_rules! read_parcel_interface { ($data_type:ty) => { |parcel| { |parcel: &BorrowedParcel<'_>| { let _res = parcel.read::<$data_type>(); } }; Loading Loading @@ -57,52 +57,51 @@ impl binder::Parcelable for SomeParcelable { binder::impl_deserialize_for_parcelable!(SomeParcelable); pub fn get_read_funcs() -> Vec<Box<dyn Fn(&BorrowedParcel<'_>)>> { let read_funcs: Vec<Box<dyn Fn(&BorrowedParcel<'_>)>> = vec![ pub const READ_FUNCS: &[fn(&BorrowedParcel<'_>)] = &[ //read basic types Box::new(read_parcel_interface!(bool)), Box::new(read_parcel_interface!(i8)), Box::new(read_parcel_interface!(i32)), Box::new(read_parcel_interface!(i64)), Box::new(read_parcel_interface!(f32)), Box::new(read_parcel_interface!(f64)), Box::new(read_parcel_interface!(u16)), Box::new(read_parcel_interface!(u32)), Box::new(read_parcel_interface!(u64)), Box::new(read_parcel_interface!(String)), read_parcel_interface!(bool), read_parcel_interface!(i8), read_parcel_interface!(i32), read_parcel_interface!(i64), read_parcel_interface!(f32), read_parcel_interface!(f64), read_parcel_interface!(u16), read_parcel_interface!(u32), read_parcel_interface!(u64), read_parcel_interface!(String), //read vec of basic types Box::new(read_parcel_interface!(Vec<i8>)), Box::new(read_parcel_interface!(Vec<i32>)), Box::new(read_parcel_interface!(Vec<i64>)), Box::new(read_parcel_interface!(Vec<f32>)), Box::new(read_parcel_interface!(Vec<f64>)), Box::new(read_parcel_interface!(Vec<u16>)), Box::new(read_parcel_interface!(Vec<u32>)), Box::new(read_parcel_interface!(Vec<u64>)), Box::new(read_parcel_interface!(Vec<String>)), Box::new(read_parcel_interface!(Option<Vec<i8>>)), Box::new(read_parcel_interface!(Option<Vec<i32>>)), Box::new(read_parcel_interface!(Option<Vec<i64>>)), Box::new(read_parcel_interface!(Option<Vec<f32>>)), Box::new(read_parcel_interface!(Option<Vec<f64>>)), Box::new(read_parcel_interface!(Option<Vec<u16>>)), Box::new(read_parcel_interface!(Option<Vec<u32>>)), Box::new(read_parcel_interface!(Option<Vec<u64>>)), Box::new(read_parcel_interface!(Option<Vec<String>>)), Box::new(read_parcel_interface!(ParcelFileDescriptor)), Box::new(read_parcel_interface!(Vec<Option<ParcelFileDescriptor>>)), Box::new(read_parcel_interface!(Option<Vec<ParcelFileDescriptor>>)), Box::new(read_parcel_interface!(Option<Vec<Option<ParcelFileDescriptor>>>)), Box::new(read_parcel_interface!(SpIBinder)), Box::new(read_parcel_interface!(Vec<Option<SpIBinder>>)), Box::new(read_parcel_interface!(Option<Vec<SpIBinder>>)), Box::new(read_parcel_interface!(Option<Vec<Option<SpIBinder>>>)), Box::new(read_parcel_interface!(SomeParcelable)), Box::new(read_parcel_interface!(Vec<Option<SomeParcelable>>)), Box::new(read_parcel_interface!(Option<Vec<SomeParcelable>>)), Box::new(read_parcel_interface!(Option<Vec<Option<SomeParcelable>>>)), read_parcel_interface!(Vec<i8>), read_parcel_interface!(Vec<i32>), read_parcel_interface!(Vec<i64>), read_parcel_interface!(Vec<f32>), read_parcel_interface!(Vec<f64>), read_parcel_interface!(Vec<u16>), read_parcel_interface!(Vec<u32>), read_parcel_interface!(Vec<u64>), read_parcel_interface!(Vec<String>), read_parcel_interface!(Option<Vec<i8>>), read_parcel_interface!(Option<Vec<i32>>), read_parcel_interface!(Option<Vec<i64>>), read_parcel_interface!(Option<Vec<f32>>), read_parcel_interface!(Option<Vec<f64>>), read_parcel_interface!(Option<Vec<u16>>), read_parcel_interface!(Option<Vec<u32>>), read_parcel_interface!(Option<Vec<u64>>), read_parcel_interface!(Option<Vec<String>>), read_parcel_interface!(ParcelFileDescriptor), read_parcel_interface!(Vec<Option<ParcelFileDescriptor>>), read_parcel_interface!(Option<Vec<ParcelFileDescriptor>>), read_parcel_interface!(Option<Vec<Option<ParcelFileDescriptor>>>), read_parcel_interface!(SpIBinder), read_parcel_interface!(Vec<Option<SpIBinder>>), read_parcel_interface!(Option<Vec<SpIBinder>>), read_parcel_interface!(Option<Vec<Option<SpIBinder>>>), read_parcel_interface!(SomeParcelable), read_parcel_interface!(Vec<Option<SomeParcelable>>), read_parcel_interface!(Option<Vec<SomeParcelable>>), read_parcel_interface!(Option<Vec<Option<SomeParcelable>>>), // Fuzz read_from_parcel for AIDL generated parcelables Box::new(|parcel| { |parcel| { let mut empty_parcelable: EmptyParcelable = EmptyParcelable::default(); match empty_parcelable.read_from_parcel(parcel) { Ok(result) => result, Loading @@ -110,8 +109,8 @@ pub fn get_read_funcs() -> Vec<Box<dyn Fn(&BorrowedParcel<'_>)>> { println!("EmptyParcelable: error occurred while reading from a parcel: {:?}", e) } } }), Box::new(|parcel| { }, |parcel| { let mut single_parcelable: SingleDataParcelable = SingleDataParcelable::default(); match single_parcelable.read_from_parcel(parcel) { Ok(result) => result, Loading @@ -120,8 +119,8 @@ pub fn get_read_funcs() -> Vec<Box<dyn Fn(&BorrowedParcel<'_>)>> { e ), } }), Box::new(|parcel| { }, |parcel| { let mut generic_parcelable: GenericDataParcelable = GenericDataParcelable::default(); match generic_parcelable.read_from_parcel(parcel) { Ok(result) => result, Loading @@ -130,8 +129,5 @@ pub fn get_read_funcs() -> Vec<Box<dyn Fn(&BorrowedParcel<'_>)>> { e ), } }), }, ]; read_funcs }