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

Commit 37b7fa88 authored by Pawan Wagh's avatar Pawan Wagh
Browse files

Using const array of functions in rust parcel fuzzer

Using const array of closures and renaming varibles.
Generating single operation instead of vec.

Bug: 164122727
Test: m parcel_fuzzer_rs
Change-Id: I1ba39e9bfb0db90fff864261ef0bfc9b533cf296
parent f8956600
Loading
Loading
Loading
Loading
+23 −26
Original line number Original line Diff line number Diff line
@@ -22,7 +22,7 @@ extern crate libfuzzer_sys;


mod read_utils;
mod read_utils;


use crate::read_utils::get_read_funcs;
use crate::read_utils::READ_FUNCS;
use binder::binder_impl::{
use binder::binder_impl::{
    Binder, BorrowedParcel, IBinderInternal, Parcel, Stability, TransactionCode,
    Binder, BorrowedParcel, IBinderInternal, Parcel, Stability, TransactionCode,
};
};
@@ -34,18 +34,18 @@ use binder_random_parcel_rs::create_random_parcel;
use libfuzzer_sys::arbitrary::Arbitrary;
use libfuzzer_sys::arbitrary::Arbitrary;


#[derive(Arbitrary, Debug)]
#[derive(Arbitrary, Debug)]
enum ReadOperations {
enum ReadOperation {
    SetDataPosition { pos: i32 },
    SetDataPosition { pos: i32 },
    GetDataSize,
    GetDataSize,
    ReadParcelableHolder { is_vintf: bool },
    ReadParcelableHolder { is_vintf: bool },
    ReadBasicTypes { indexes: Vec<usize> },
    ReadBasicTypes { instructions: Vec<usize> },
}
}


#[derive(Arbitrary, Debug)]
#[derive(Arbitrary, Debug)]
enum Operations<'a> {
enum Operation<'a> {
    Transact { code: u32, flag: u32, data: &'a [u8] },
    Transact { code: u32, flag: u32, data: &'a [u8] },
    Append { start: i32, len: i32, data1: &'a [u8], data2: &'a [u8], append_all: bool },
    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
/// Interface to fuzz transact with random parcel
@@ -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]) {
fn do_read_fuzz(read_operations: Vec<ReadOperation>, data: &[u8]) {
    let read_funcs = get_read_funcs();
    let parcel = create_random_parcel(data);
    let parcel = create_random_parcel(data);


    for operation in read_operations {
    for operation in read_operations {
        match operation {
        match operation {
            ReadOperations::SetDataPosition { pos } => {
            ReadOperation::SetDataPosition { pos } => {
                unsafe {
                unsafe {
                    // Safety: Safe if pos is less than current size of the parcel.
                    // Safety: Safe if pos is less than current size of the parcel.
                    // It relies on C++ code for bound checks
                    // It relies on C++ code for bound checks
@@ -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();
                let data_size = parcel.get_data_size();
                println!("data size from parcel: {:?}", 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 stability = if is_vintf { Stability::Vintf } else { Stability::Local };
                let mut holder: ParcelableHolder = ParcelableHolder::new(stability);
                let mut holder: ParcelableHolder = ParcelableHolder::new(stability);
                match holder.read_from_parcel(parcel.borrowed_ref()) {
                match holder.read_from_parcel(parcel.borrowed_ref()) {
@@ -135,30 +134,28 @@ fn do_read_fuzz(read_operations: Vec<ReadOperations>, data: &[u8]) {
                }
                }
            }
            }


            ReadOperations::ReadBasicTypes { indexes } => {
            ReadOperation::ReadBasicTypes { instructions } => {
                for index in indexes.iter() {
                for instruction in instructions.iter() {
                    let read_index = index % read_funcs.len();
                    let read_index = instruction % READ_FUNCS.len();
                    read_funcs[read_index](parcel.borrowed_ref());
                    READ_FUNCS[read_index](parcel.borrowed_ref());
                }
                }
            }
            }
        }
        }
    }
    }
}
}


fuzz_target!(|operations: Vec<Operations>| {
fuzz_target!(|operation: Operation| {
    for operation in operations {
    match operation {
    match operation {
            Operations::Transact { code, flag, data } => {
        Operation::Transact { code, flag, data } => {
            do_transact(code, data, flag);
            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);
            do_append_fuzz(start, len, data1, data2, append_all);
        }
        }


            Operations::Read { indexes, data } => {
        Operation::Read { read_operations, data } => {
                do_read_fuzz(indexes, data);
            do_read_fuzz(read_operations, data);
            }
        }
        }
    }
    }
});
});
+74 −78
Original line number Original line Diff line number Diff line
@@ -22,7 +22,7 @@ use binderReadParcelIface::aidl::SingleDataParcelable::SingleDataParcelable;


macro_rules! read_parcel_interface {
macro_rules! read_parcel_interface {
    ($data_type:ty) => {
    ($data_type:ty) => {
        |parcel| {
        |parcel: &BorrowedParcel<'_>| {
            let _res = parcel.read::<$data_type>();
            let _res = parcel.read::<$data_type>();
        }
        }
    };
    };
@@ -57,52 +57,51 @@ impl binder::Parcelable for SomeParcelable {


binder::impl_deserialize_for_parcelable!(SomeParcelable);
binder::impl_deserialize_for_parcelable!(SomeParcelable);


pub fn get_read_funcs() -> Vec<Box<dyn Fn(&BorrowedParcel<'_>)>> {
pub const READ_FUNCS: &[fn(&BorrowedParcel<'_>)] = &[
    let read_funcs: Vec<Box<dyn Fn(&BorrowedParcel<'_>)>> = vec![
    //read basic types
    //read basic types
        Box::new(read_parcel_interface!(bool)),
    read_parcel_interface!(bool),
        Box::new(read_parcel_interface!(i8)),
    read_parcel_interface!(i8),
        Box::new(read_parcel_interface!(i32)),
    read_parcel_interface!(i32),
        Box::new(read_parcel_interface!(i64)),
    read_parcel_interface!(i64),
        Box::new(read_parcel_interface!(f32)),
    read_parcel_interface!(f32),
        Box::new(read_parcel_interface!(f64)),
    read_parcel_interface!(f64),
        Box::new(read_parcel_interface!(u16)),
    read_parcel_interface!(u16),
        Box::new(read_parcel_interface!(u32)),
    read_parcel_interface!(u32),
        Box::new(read_parcel_interface!(u64)),
    read_parcel_interface!(u64),
        Box::new(read_parcel_interface!(String)),
    read_parcel_interface!(String),
    //read vec of basic types
    //read vec of basic types
        Box::new(read_parcel_interface!(Vec<i8>)),
    read_parcel_interface!(Vec<i8>),
        Box::new(read_parcel_interface!(Vec<i32>)),
    read_parcel_interface!(Vec<i32>),
        Box::new(read_parcel_interface!(Vec<i64>)),
    read_parcel_interface!(Vec<i64>),
        Box::new(read_parcel_interface!(Vec<f32>)),
    read_parcel_interface!(Vec<f32>),
        Box::new(read_parcel_interface!(Vec<f64>)),
    read_parcel_interface!(Vec<f64>),
        Box::new(read_parcel_interface!(Vec<u16>)),
    read_parcel_interface!(Vec<u16>),
        Box::new(read_parcel_interface!(Vec<u32>)),
    read_parcel_interface!(Vec<u32>),
        Box::new(read_parcel_interface!(Vec<u64>)),
    read_parcel_interface!(Vec<u64>),
        Box::new(read_parcel_interface!(Vec<String>)),
    read_parcel_interface!(Vec<String>),
        Box::new(read_parcel_interface!(Option<Vec<i8>>)),
    read_parcel_interface!(Option<Vec<i8>>),
        Box::new(read_parcel_interface!(Option<Vec<i32>>)),
    read_parcel_interface!(Option<Vec<i32>>),
        Box::new(read_parcel_interface!(Option<Vec<i64>>)),
    read_parcel_interface!(Option<Vec<i64>>),
        Box::new(read_parcel_interface!(Option<Vec<f32>>)),
    read_parcel_interface!(Option<Vec<f32>>),
        Box::new(read_parcel_interface!(Option<Vec<f64>>)),
    read_parcel_interface!(Option<Vec<f64>>),
        Box::new(read_parcel_interface!(Option<Vec<u16>>)),
    read_parcel_interface!(Option<Vec<u16>>),
        Box::new(read_parcel_interface!(Option<Vec<u32>>)),
    read_parcel_interface!(Option<Vec<u32>>),
        Box::new(read_parcel_interface!(Option<Vec<u64>>)),
    read_parcel_interface!(Option<Vec<u64>>),
        Box::new(read_parcel_interface!(Option<Vec<String>>)),
    read_parcel_interface!(Option<Vec<String>>),
        Box::new(read_parcel_interface!(ParcelFileDescriptor)),
    read_parcel_interface!(ParcelFileDescriptor),
        Box::new(read_parcel_interface!(Vec<Option<ParcelFileDescriptor>>)),
    read_parcel_interface!(Vec<Option<ParcelFileDescriptor>>),
        Box::new(read_parcel_interface!(Option<Vec<ParcelFileDescriptor>>)),
    read_parcel_interface!(Option<Vec<ParcelFileDescriptor>>),
        Box::new(read_parcel_interface!(Option<Vec<Option<ParcelFileDescriptor>>>)),
    read_parcel_interface!(Option<Vec<Option<ParcelFileDescriptor>>>),
        Box::new(read_parcel_interface!(SpIBinder)),
    read_parcel_interface!(SpIBinder),
        Box::new(read_parcel_interface!(Vec<Option<SpIBinder>>)),
    read_parcel_interface!(Vec<Option<SpIBinder>>),
        Box::new(read_parcel_interface!(Option<Vec<SpIBinder>>)),
    read_parcel_interface!(Option<Vec<SpIBinder>>),
        Box::new(read_parcel_interface!(Option<Vec<Option<SpIBinder>>>)),
    read_parcel_interface!(Option<Vec<Option<SpIBinder>>>),
        Box::new(read_parcel_interface!(SomeParcelable)),
    read_parcel_interface!(SomeParcelable),
        Box::new(read_parcel_interface!(Vec<Option<SomeParcelable>>)),
    read_parcel_interface!(Vec<Option<SomeParcelable>>),
        Box::new(read_parcel_interface!(Option<Vec<SomeParcelable>>)),
    read_parcel_interface!(Option<Vec<SomeParcelable>>),
        Box::new(read_parcel_interface!(Option<Vec<Option<SomeParcelable>>>)),
    read_parcel_interface!(Option<Vec<Option<SomeParcelable>>>),
    // Fuzz read_from_parcel for AIDL generated parcelables
    // Fuzz read_from_parcel for AIDL generated parcelables
        Box::new(|parcel| {
    |parcel| {
        let mut empty_parcelable: EmptyParcelable = EmptyParcelable::default();
        let mut empty_parcelable: EmptyParcelable = EmptyParcelable::default();
        match empty_parcelable.read_from_parcel(parcel) {
        match empty_parcelable.read_from_parcel(parcel) {
            Ok(result) => result,
            Ok(result) => result,
@@ -110,8 +109,8 @@ pub fn get_read_funcs() -> Vec<Box<dyn Fn(&BorrowedParcel<'_>)>> {
                println!("EmptyParcelable: error occurred while reading from a parcel: {:?}", e)
                println!("EmptyParcelable: error occurred while reading from a parcel: {:?}", e)
            }
            }
        }
        }
        }),
    },
        Box::new(|parcel| {
    |parcel| {
        let mut single_parcelable: SingleDataParcelable = SingleDataParcelable::default();
        let mut single_parcelable: SingleDataParcelable = SingleDataParcelable::default();
        match single_parcelable.read_from_parcel(parcel) {
        match single_parcelable.read_from_parcel(parcel) {
            Ok(result) => result,
            Ok(result) => result,
@@ -120,8 +119,8 @@ pub fn get_read_funcs() -> Vec<Box<dyn Fn(&BorrowedParcel<'_>)>> {
                e
                e
            ),
            ),
        }
        }
        }),
    },
        Box::new(|parcel| {
    |parcel| {
        let mut generic_parcelable: GenericDataParcelable = GenericDataParcelable::default();
        let mut generic_parcelable: GenericDataParcelable = GenericDataParcelable::default();
        match generic_parcelable.read_from_parcel(parcel) {
        match generic_parcelable.read_from_parcel(parcel) {
            Ok(result) => result,
            Ok(result) => result,
@@ -130,8 +129,5 @@ pub fn get_read_funcs() -> Vec<Box<dyn Fn(&BorrowedParcel<'_>)>> {
                e
                e
            ),
            ),
        }
        }
        }),
    },
];
];

    read_funcs
}