Make CommandExecutor Generic on the specific Input (#2129)

This commit is contained in:
Valentin Huber 2024-05-02 21:39:06 +02:00 committed by GitHub
parent 2e81dc6c59
commit 7fe0c576db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 27 additions and 24 deletions

View File

@ -15,7 +15,7 @@ use libafl::{
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback}, feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
fuzzer::{Fuzzer, StdFuzzer}, fuzzer::{Fuzzer, StdFuzzer},
generators::RandPrintablesGenerator, generators::RandPrintablesGenerator,
inputs::{HasTargetBytes, Input}, inputs::{BytesInput, HasTargetBytes},
monitors::SimpleMonitor, monitors::SimpleMonitor,
mutators::scheduled::{havoc_mutations, StdScheduledMutator}, mutators::scheduled::{havoc_mutations, StdScheduledMutator},
observers::{get_asan_runtime_flags, AsanBacktraceObserver, StdMapObserver}, observers::{get_asan_runtime_flags, AsanBacktraceObserver, StdMapObserver},
@ -85,8 +85,8 @@ pub fn main() {
shmem_id: ShMemId, shmem_id: ShMemId,
} }
impl CommandConfigurator for MyExecutor { impl CommandConfigurator<BytesInput> for MyExecutor {
fn spawn_child<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<Child, Error> { fn spawn_child(&mut self, input: &BytesInput) -> Result<Child, Error> {
let mut command = Command::new("./test_command"); let mut command = Command::new("./test_command");
let command = command let command = command

View File

@ -43,7 +43,7 @@ use libafl_bolts::{
rands::StdRand, rands::StdRand,
shmem::{ShMem, ShMemProvider, StdShMemProvider}, shmem::{ShMem, ShMemProvider, StdShMemProvider},
tuples::{tuple_list, Referenceable}, tuples::{tuple_list, Referenceable},
AsSliceMut, AsSlice AsSlice, AsSliceMut,
}; };
use libafl_targets::{ use libafl_targets::{
libfuzzer_initialize, libfuzzer_test_one_input, std_edges_map_observer, CmpLogObserver, libfuzzer_initialize, libfuzzer_test_one_input, std_edges_map_observer, CmpLogObserver,
@ -237,8 +237,8 @@ fn fuzz(
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct MyCommandConfigurator; pub struct MyCommandConfigurator;
impl CommandConfigurator for MyCommandConfigurator { impl CommandConfigurator<BytesInput> for MyCommandConfigurator {
fn spawn_child<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<Child, Error> { fn spawn_child(&mut self, input: &BytesInput) -> Result<Child, Error> {
input.to_file("cur_input")?; input.to_file("cur_input")?;
Ok(Command::new("./target_symcc.out") Ok(Command::new("./target_symcc.out")

View File

@ -87,11 +87,11 @@ pub struct StdCommandConfigurator {
command: Command, command: Command,
} }
impl CommandConfigurator for StdCommandConfigurator { impl<I> CommandConfigurator<I> for StdCommandConfigurator
fn spawn_child<I>(&mut self, input: &I) -> Result<Child, Error> where
where I: HasTargetBytes,
I: Input + HasTargetBytes, {
{ fn spawn_child(&mut self, input: &I) -> Result<Child, Error> {
match &mut self.input_location { match &mut self.input_location {
InputLocation::Arg { argnum } => { InputLocation::Arg { argnum } => {
let args = self.command.get_args(); let args = self.command.get_args();
@ -217,6 +217,7 @@ impl<OT, S> CommandExecutor<OT, S, StdCommandConfigurator>
where where
OT: MatchName + ObserversTuple<S>, OT: MatchName + ObserversTuple<S>,
S: UsesInput, S: UsesInput,
S::Input: HasTargetBytes,
{ {
/// Creates a new `CommandExecutor`. /// Creates a new `CommandExecutor`.
/// Instead of parsing the Command for `@@`, it will /// Instead of parsing the Command for `@@`, it will
@ -314,8 +315,7 @@ impl<EM, OT, S, T, Z> Executor<EM, Z> for CommandExecutor<OT, S, T>
where where
EM: UsesState<State = S>, EM: UsesState<State = S>,
S: State + HasExecutions, S: State + HasExecutions,
S::Input: HasTargetBytes, T: CommandConfigurator<S::Input>,
T: CommandConfigurator,
OT: Debug + MatchName + ObserversTuple<S>, OT: Debug + MatchName + ObserversTuple<S>,
Z: UsesState<State = S>, Z: UsesState<State = S>,
{ {
@ -567,6 +567,7 @@ impl CommandExecutorBuilder {
where where
OT: MatchName + ObserversTuple<S>, OT: MatchName + ObserversTuple<S>,
S: UsesInput, S: UsesInput,
S::Input: Input + HasTargetBytes,
{ {
let Some(program) = &self.program else { let Some(program) = &self.program else {
return Err(Error::illegal_argument( return Err(Error::illegal_argument(
@ -612,7 +613,12 @@ impl CommandExecutorBuilder {
timeout: self.timeout, timeout: self.timeout,
command, command,
}; };
Ok(configurator.into_executor::<OT, S>(observers)) Ok(
<StdCommandConfigurator as CommandConfigurator<S::Input>>::into_executor::<OT, S>(
configurator,
observers,
),
)
} }
} }
@ -621,15 +627,15 @@ impl CommandExecutorBuilder {
#[cfg_attr(all(feature = "std", unix), doc = " ```")] #[cfg_attr(all(feature = "std", unix), doc = " ```")]
#[cfg_attr(not(all(feature = "std", unix)), doc = " ```ignore")] #[cfg_attr(not(all(feature = "std", unix)), doc = " ```ignore")]
/// use std::{io::Write, process::{Stdio, Command, Child}, time::Duration}; /// use std::{io::Write, process::{Stdio, Command, Child}, time::Duration};
/// use libafl::{Error, inputs::{HasTargetBytes, Input, UsesInput}, executors::{Executor, command::CommandConfigurator}, state::{UsesState, HasExecutions}}; /// use libafl::{Error, inputs::{BytesInput, HasTargetBytes, Input, UsesInput}, executors::{Executor, command::CommandConfigurator}, state::{UsesState, HasExecutions}};
/// use libafl_bolts::AsSlice; /// use libafl_bolts::AsSlice;
/// #[derive(Debug)] /// #[derive(Debug)]
/// struct MyExecutor; /// struct MyExecutor;
/// ///
/// impl CommandConfigurator for MyExecutor { /// impl CommandConfigurator<BytesInput> for MyExecutor {
/// fn spawn_child<I: HasTargetBytes>( /// fn spawn_child(
/// &mut self, /// &mut self,
/// input: &I, /// input: &BytesInput,
/// ) -> Result<Child, Error> { /// ) -> Result<Child, Error> {
/// let mut command = Command::new("../if"); /// let mut command = Command::new("../if");
/// command /// command
@ -652,19 +658,16 @@ impl CommandExecutorBuilder {
/// where /// where
/// EM: UsesState, /// EM: UsesState,
/// Z: UsesState<State = EM::State>, /// Z: UsesState<State = EM::State>,
/// EM::State: UsesInput + HasExecutions, /// EM::State: UsesInput<Input = BytesInput> + HasExecutions,
/// EM::Input: HasTargetBytes
/// { /// {
/// MyExecutor.into_executor(()) /// MyExecutor.into_executor(())
/// } /// }
/// ``` /// ```
#[cfg(all(feature = "std", any(unix, doc)))] #[cfg(all(feature = "std", any(unix, doc)))]
pub trait CommandConfigurator: Sized { pub trait CommandConfigurator<I>: Sized {
/// Spawns a new process with the given configuration. /// Spawns a new process with the given configuration.
fn spawn_child<I>(&mut self, input: &I) -> Result<Child, Error> fn spawn_child(&mut self, input: &I) -> Result<Child, Error>;
where
I: Input + HasTargetBytes;
/// Provides timeout duration for execution of the child process. /// Provides timeout duration for execution of the child process.
fn exec_timeout(&self) -> Duration; fn exec_timeout(&self) -> Duration;