Update ForkserverBytesCoverageSugar to use parse_afl_cmdline, latest features (#1343)
* update forkserversugar to use parse_afl_cmdline * added tokens/persistent/deferred to forkserver sugar * removed deferred option * added build_dynamic_map call; removed generic const * clippy --------- Co-authored-by: Dominik Maier <domenukk@gmail.com>
This commit is contained in:
parent
3e0e753e9f
commit
72e54ac2f4
@ -24,7 +24,7 @@ use libafl::{
|
|||||||
scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator},
|
scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator},
|
||||||
token_mutations::Tokens,
|
token_mutations::Tokens,
|
||||||
},
|
},
|
||||||
observers::{ConstMapObserver, HitcountsMapObserver, TimeObserver},
|
observers::{HitcountsMapObserver, StdMapObserver, TimeObserver},
|
||||||
schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler},
|
schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler},
|
||||||
stages::StdMutationalStage,
|
stages::StdMutationalStage,
|
||||||
state::{HasCorpus, HasMetadata, StdState},
|
state::{HasCorpus, HasMetadata, StdState},
|
||||||
@ -39,7 +39,7 @@ pub const DEFAULT_MAP_SIZE: usize = 65536;
|
|||||||
|
|
||||||
/// Creates a Forkserver-based fuzzer.
|
/// Creates a Forkserver-based fuzzer.
|
||||||
#[derive(Debug, TypedBuilder)]
|
#[derive(Debug, TypedBuilder)]
|
||||||
pub struct ForkserverBytesCoverageSugar<'a, const MAP_SIZE: usize> {
|
pub struct ForkserverBytesCoverageSugar<'a> {
|
||||||
/// Laucher configuration (default is random)
|
/// Laucher configuration (default is random)
|
||||||
#[builder(default = None, setter(strip_option))]
|
#[builder(default = None, setter(strip_option))]
|
||||||
configuration: Option<String>,
|
configuration: Option<String>,
|
||||||
@ -80,10 +80,15 @@ pub struct ForkserverBytesCoverageSugar<'a, const MAP_SIZE: usize> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::similar_names)]
|
#[allow(clippy::similar_names)]
|
||||||
impl<'a, const MAP_SIZE: usize> ForkserverBytesCoverageSugar<'a, MAP_SIZE> {
|
impl<'a> ForkserverBytesCoverageSugar<'a> {
|
||||||
/// Runs the fuzzer.
|
/// Runs the fuzzer.
|
||||||
#[allow(clippy::too_many_lines, clippy::similar_names)]
|
#[allow(clippy::too_many_lines, clippy::similar_names)]
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
|
// a large initial map size that should be enough
|
||||||
|
// to house all potential coverage maps for our targets
|
||||||
|
// (we will eventually reduce the used size according to the actual map)
|
||||||
|
const MAP_SIZE: usize = 2_621_440;
|
||||||
|
|
||||||
let conf = match self.configuration.as_ref() {
|
let conf = match self.configuration.as_ref() {
|
||||||
Some(name) => EventConfig::from_name(name),
|
Some(name) => EventConfig::from_name(name),
|
||||||
None => EventConfig::AlwaysUnique,
|
None => EventConfig::AlwaysUnique,
|
||||||
@ -121,13 +126,12 @@ impl<'a, const MAP_SIZE: usize> ForkserverBytesCoverageSugar<'a, MAP_SIZE> {
|
|||||||
shmem.write_to_env("__AFL_SHM_ID").unwrap();
|
shmem.write_to_env("__AFL_SHM_ID").unwrap();
|
||||||
let shmem_map = shmem.as_mut_slice();
|
let shmem_map = shmem.as_mut_slice();
|
||||||
|
|
||||||
|
// To let know the AFL++ binary that we have a big map
|
||||||
|
std::env::set_var("AFL_MAP_SIZE", format!("{MAP_SIZE}"));
|
||||||
|
|
||||||
// Create an observation channel using the coverage map
|
// Create an observation channel using the coverage map
|
||||||
let edges_observer = unsafe {
|
let edges_observer =
|
||||||
HitcountsMapObserver::new(ConstMapObserver::<_, MAP_SIZE>::from_mut_ptr(
|
unsafe { HitcountsMapObserver::new(StdMapObserver::new("shared_mem", shmem_map)) };
|
||||||
"shared_mem",
|
|
||||||
shmem_map.as_mut_ptr(),
|
|
||||||
))
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create an observation channel to keep track of the execution time
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("time");
|
let time_observer = TimeObserver::new("time");
|
||||||
@ -160,12 +164,8 @@ impl<'a, const MAP_SIZE: usize> ForkserverBytesCoverageSugar<'a, MAP_SIZE> {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a dictionary if not existing
|
// Create an empty set of tokens, first populated by the target program
|
||||||
if let Some(tokens_file) = &self.tokens_file {
|
let mut tokens = Tokens::new();
|
||||||
if state.metadata_map().get::<Tokens>().is_none() {
|
|
||||||
state.add_metadata(Tokens::from_file(tokens_file)?);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A minimization+queue policy to get testcasess from the corpus
|
// A minimization+queue policy to get testcasess from the corpus
|
||||||
let scheduler = IndexesLenTimeMinimizerScheduler::new(QueueScheduler::new());
|
let scheduler = IndexesLenTimeMinimizerScheduler::new(QueueScheduler::new());
|
||||||
@ -176,18 +176,34 @@ impl<'a, const MAP_SIZE: usize> ForkserverBytesCoverageSugar<'a, MAP_SIZE> {
|
|||||||
let forkserver = if self.shmem_testcase {
|
let forkserver = if self.shmem_testcase {
|
||||||
ForkserverExecutorBuilder::new()
|
ForkserverExecutorBuilder::new()
|
||||||
.program(self.program.clone())
|
.program(self.program.clone())
|
||||||
.args(self.arguments)
|
.parse_afl_cmdline(self.arguments)
|
||||||
|
.is_persistent(true)
|
||||||
|
.autotokens(&mut tokens)
|
||||||
|
.coverage_map_size(MAP_SIZE)
|
||||||
.debug_child(self.debug_output)
|
.debug_child(self.debug_output)
|
||||||
.shmem_provider(&mut shmem_provider_client)
|
.shmem_provider(&mut shmem_provider_client)
|
||||||
.build(tuple_list!(edges_observer, time_observer))
|
.build_dynamic_map(edges_observer, tuple_list!(time_observer))
|
||||||
} else {
|
} else {
|
||||||
ForkserverExecutorBuilder::new()
|
ForkserverExecutorBuilder::new()
|
||||||
.program(self.program.clone())
|
.program(self.program.clone())
|
||||||
.args(self.arguments)
|
.parse_afl_cmdline(self.arguments)
|
||||||
|
.is_persistent(true)
|
||||||
|
.autotokens(&mut tokens)
|
||||||
|
.coverage_map_size(MAP_SIZE)
|
||||||
.debug_child(self.debug_output)
|
.debug_child(self.debug_output)
|
||||||
.build(tuple_list!(edges_observer, time_observer))
|
.build_dynamic_map(edges_observer, tuple_list!(time_observer))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if let Some(tokens_file) = &self.tokens_file {
|
||||||
|
// if a token file is provided, load it into our set of tokens
|
||||||
|
tokens.add_from_file(tokens_file)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tokens.is_empty() {
|
||||||
|
// add any known tokens to the state
|
||||||
|
state.add_metadata(tokens);
|
||||||
|
}
|
||||||
|
|
||||||
// Create the executor for an in-process function with one observer for edge coverage and one for the execution time
|
// Create the executor for an in-process function with one observer for edge coverage and one for the execution time
|
||||||
let mut executor = TimeoutForkserverExecutor::new(
|
let mut executor = TimeoutForkserverExecutor::new(
|
||||||
forkserver.expect("Failed to create the executor."),
|
forkserver.expect("Failed to create the executor."),
|
||||||
@ -346,7 +362,7 @@ pub mod pybind {
|
|||||||
/// Run the fuzzer
|
/// Run the fuzzer
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
pub fn run(&self, program: String, arguments: Vec<String>) {
|
pub fn run(&self, program: String, arguments: Vec<String>) {
|
||||||
forkserver::ForkserverBytesCoverageSugar::<{ forkserver::DEFAULT_MAP_SIZE }>::builder()
|
forkserver::ForkserverBytesCoverageSugar::builder()
|
||||||
.input_dirs(&self.input_dirs)
|
.input_dirs(&self.input_dirs)
|
||||||
.output_dir(self.output_dir.clone())
|
.output_dir(self.output_dir.clone())
|
||||||
.broker_port(self.broker_port)
|
.broker_port(self.broker_port)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user