new ondisk corpus
This commit is contained in:
parent
3b0883721e
commit
a5cc8313db
@ -5,10 +5,11 @@ use std::{env, path::PathBuf};
|
|||||||
|
|
||||||
use libafl::{
|
use libafl::{
|
||||||
bolts::{shmem::UnixShMem, tuples::tuple_list},
|
bolts::{shmem::UnixShMem, tuples::tuple_list},
|
||||||
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus},
|
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus, RandCorpusScheduler},
|
||||||
events::setup_restarting_mgr,
|
events::setup_restarting_mgr,
|
||||||
executors::{inprocess::InProcessExecutor, Executor, ExitKind},
|
executors::{inprocess::InProcessExecutor, Executor, ExitKind},
|
||||||
feedbacks::{CrashFeedback, MaxMapFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||||
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
mutators::scheduled::HavocBytesMutator,
|
mutators::scheduled::HavocBytesMutator,
|
||||||
mutators::token_mutations::TokensMetadata,
|
mutators::token_mutations::TokensMetadata,
|
||||||
@ -17,7 +18,7 @@ use libafl::{
|
|||||||
state::{HasCorpus, HasMetadata, State},
|
state::{HasCorpus, HasMetadata, State},
|
||||||
stats::SimpleStats,
|
stats::SimpleStats,
|
||||||
utils::{current_nanos, StdRand},
|
utils::{current_nanos, StdRand},
|
||||||
Error, Fuzzer, StdFuzzer,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The name of the coverage map observer, to find it again in the observer list
|
/// The name of the coverage map observer, to find it again in the observer list
|
||||||
@ -69,13 +70,12 @@ pub fn main() {
|
|||||||
|
|
||||||
/// The actual fuzzer
|
/// The actual fuzzer
|
||||||
fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) -> Result<(), Error> {
|
fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) -> Result<(), Error> {
|
||||||
let mut rand = StdRand::new(current_nanos());
|
|
||||||
// 'While the stats are state, they are usually used in the broker - which is likely never restarted
|
// 'While the stats are state, they are usually used in the broker - which is likely never restarted
|
||||||
let stats = SimpleStats::new(|s| println!("{}", s));
|
let stats = SimpleStats::new(|s| println!("{}", s));
|
||||||
|
|
||||||
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
||||||
let (state, mut restarting_mgr) =
|
let (state, mut restarting_mgr) =
|
||||||
setup_restarting_mgr::<_, _, _, _, _, _, UnixShMem, _>(stats, broker_port)
|
setup_restarting_mgr::<_, _, UnixShMem, _>(stats, broker_port)
|
||||||
.expect("Failed to setup the restarter".into());
|
.expect("Failed to setup the restarter".into());
|
||||||
|
|
||||||
// Create an observation channel using the coverage map
|
// Create an observation channel using the coverage map
|
||||||
@ -86,6 +86,7 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
|
|||||||
|
|
||||||
// If not restarting, create a State from scratch
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or(State::new(
|
let mut state = state.unwrap_or(State::new(
|
||||||
|
StdRand::new(current_nanos()),
|
||||||
InMemoryCorpus::new(),
|
InMemoryCorpus::new(),
|
||||||
tuple_list!(MaxMapFeedback::new_with_observer(
|
tuple_list!(MaxMapFeedback::new_with_observer(
|
||||||
&NAME_COV_MAP,
|
&NAME_COV_MAP,
|
||||||
@ -111,7 +112,7 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
|
|||||||
// Setup a basic mutator with a mutational stage
|
// Setup a basic mutator with a mutational stage
|
||||||
let mutator = HavocBytesMutator::default();
|
let mutator = HavocBytesMutator::default();
|
||||||
let stage = StdMutationalStage::new(mutator);
|
let stage = StdMutationalStage::new(mutator);
|
||||||
let mut fuzzer = StdFuzzer::new(tuple_list!(stage));
|
let fuzzer = StdFuzzer::new(RandCorpusScheduler::new(), tuple_list!(stage));
|
||||||
|
|
||||||
// Create the executor
|
// Create the executor
|
||||||
let mut executor = InProcessExecutor::new(
|
let mut executor = InProcessExecutor::new(
|
||||||
@ -141,5 +142,7 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
|
|||||||
println!("We imported {} inputs from disk.", state.corpus().count());
|
println!("We imported {} inputs from disk.", state.corpus().count());
|
||||||
}
|
}
|
||||||
|
|
||||||
fuzzer.fuzz_loop(&mut rand, &mut executor, &mut state, &mut restarting_mgr)
|
fuzzer.fuzz_loop(&mut state, &mut executor, &mut restarting_mgr)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -72,3 +72,15 @@ where
|
|||||||
&mut self.current
|
&mut self.current
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<I> InMemoryCorpus<I>
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
entries: vec![],
|
||||||
|
current: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6,6 +6,11 @@ pub use testcase::Testcase;
|
|||||||
pub mod inmemory;
|
pub mod inmemory;
|
||||||
pub use inmemory::InMemoryCorpus;
|
pub use inmemory::InMemoryCorpus;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub mod ondisk;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use ondisk::OnDiskCorpus;
|
||||||
|
|
||||||
pub mod queue;
|
pub mod queue;
|
||||||
pub use queue::QueueCorpusScheduler;
|
pub use queue::QueueCorpusScheduler;
|
||||||
|
|
||||||
@ -110,4 +115,18 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<C, I, R, S> RandCorpusScheduler<C, I, R, S>
|
||||||
|
where
|
||||||
|
S: HasCorpus<C, I> + HasRand<R>,
|
||||||
|
C: Corpus<I>,
|
||||||
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
|
{
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type StdCorpusScheduler<C, I, R, S> = RandCorpusScheduler<C, I, R, S>;
|
pub type StdCorpusScheduler<C, I, R, S> = RandCorpusScheduler<C, I, R, S>;
|
||||||
|
@ -1,104 +1,104 @@
|
|||||||
//! The ondisk corpus stores unused testcases to disk.
|
//! The ondisk corpus stores unused testcases to disk.
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::{cell::RefCell, marker::PhantomData};
|
use core::cell::RefCell;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::{
|
use crate::{corpus::Corpus, corpus::Testcase, inputs::Input, Error};
|
||||||
corpus::Corpus, corpus::HasTestcaseVec, corpus::Testcase, inputs::Input, utils::Rand, Error,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A corpus able to store testcases to disk, and load them from disk, when they are being used.
|
/// A corpus able to store testcases to disk, and load them from disk, when they are being used.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
|
||||||
#[serde(bound = "I: serde::de::DeserializeOwned")]
|
#[serde(bound = "I: serde::de::DeserializeOwned")]
|
||||||
pub struct OnDiskCorpus<I, R>
|
pub struct OnDiskCorpus<I>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
|
||||||
{
|
{
|
||||||
entries: Vec<RefCell<Testcase<I>>>,
|
entries: Vec<RefCell<Testcase<I>>>,
|
||||||
|
current: Option<usize>,
|
||||||
dir_path: PathBuf,
|
dir_path: PathBuf,
|
||||||
pos: usize,
|
|
||||||
phantom: PhantomData<R>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
impl<I> Corpus<I> for OnDiskCorpus<I>
|
||||||
impl<I, R> HasTestcaseVec<I> for OnDiskCorpus<I, R>
|
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
|
||||||
{
|
{
|
||||||
|
/// Returns the number of elements
|
||||||
#[inline]
|
#[inline]
|
||||||
fn entries(&self) -> &[RefCell<Testcase<I>>] {
|
fn count(&self) -> usize {
|
||||||
&self.entries
|
self.entries.len()
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn entries_mut(&mut self) -> &mut Vec<RefCell<Testcase<I>>> {
|
|
||||||
&mut self.entries
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
/// Add an entry to the corpus and return its index
|
||||||
impl<I, R> Corpus<I, R> for OnDiskCorpus<I, R>
|
#[inline]
|
||||||
where
|
fn add(&mut self, mut testcase: Testcase<I>) -> Result<usize, Error> {
|
||||||
I: Input,
|
match testcase.filename() {
|
||||||
R: Rand,
|
|
||||||
{
|
|
||||||
/// Add an entry and save it to disk
|
|
||||||
fn add(&mut self, mut entry: Testcase<I>) -> usize {
|
|
||||||
match entry.filename() {
|
|
||||||
None => {
|
None => {
|
||||||
// TODO walk entry metadatas to ask for pices of filename (e.g. :havoc in AFL)
|
// TODO walk entry metadatas to ask for pices of filename (e.g. :havoc in AFL)
|
||||||
let filename = self.dir_path.join(format!("id_{}", &self.entries.len()));
|
let filename = self.dir_path.join(format!("id_{}", &self.entries.len()));
|
||||||
let filename_str = filename.to_str().expect("Invalid Path");
|
let filename_str = filename.to_str().expect("Invalid Path");
|
||||||
entry.set_filename(filename_str.into());
|
testcase.set_filename(filename_str.into());
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
entry
|
testcase
|
||||||
.store_input()
|
.store_input()
|
||||||
.expect("Could not save testcase to disk".into());
|
.expect("Could not save testcase to disk".into());
|
||||||
self.entries.push(RefCell::new(entry));
|
self.entries.push(RefCell::new(testcase));
|
||||||
self.entries.len() - 1
|
Ok(self.entries.len() - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Replaces the testcase at the given idx
|
||||||
#[inline]
|
#[inline]
|
||||||
fn current_testcase(&self) -> (&RefCell<Testcase<I>>, usize) {
|
fn replace(&mut self, idx: usize, testcase: Testcase<I>) -> Result<(), Error> {
|
||||||
(self.get(self.pos), self.pos)
|
if idx >= self.entries.len() {
|
||||||
|
return Err(Error::KeyNotFound(format!("Index {} out of bounds", idx)));
|
||||||
|
}
|
||||||
|
self.entries[idx] = RefCell::new(testcase);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the next entry
|
/// Removes an entry from the corpus, returning it if it was present.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self, rand: &mut R) -> Result<(&RefCell<Testcase<I>>, usize), Error> {
|
fn remove(&mut self, idx: usize) -> Result<Option<Testcase<I>>, Error> {
|
||||||
if self.count() == 0 {
|
if idx >= self.entries.len() {
|
||||||
Err(Error::Empty("No entries in corpus".to_owned()))
|
Ok(None)
|
||||||
} else {
|
} else {
|
||||||
let len = { self.entries().len() };
|
Ok(Some(self.entries.remove(idx).into_inner()))
|
||||||
let id = rand.below(len as u64) as usize;
|
|
||||||
self.pos = id;
|
|
||||||
Ok((self.get(id), id))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO save and remove files, cache, etc..., ATM use just InMemoryCorpus
|
/// Get by id
|
||||||
|
#[inline]
|
||||||
|
fn get(&self, idx: usize) -> Result<&RefCell<Testcase<I>>, Error> {
|
||||||
|
Ok(&self.entries[idx])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
/// Current testcase scheduled
|
||||||
impl<I, R> OnDiskCorpus<I, R>
|
#[inline]
|
||||||
|
fn current(&self) -> &Option<usize> {
|
||||||
|
&self.current
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Current testcase scheduled (mut)
|
||||||
|
#[inline]
|
||||||
|
fn current_mut(&mut self) -> &mut Option<usize> {
|
||||||
|
&mut self.current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I> OnDiskCorpus<I>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
|
||||||
{
|
{
|
||||||
pub fn new(dir_path: PathBuf) -> Self {
|
pub fn new(dir_path: PathBuf) -> Self {
|
||||||
Self {
|
Self {
|
||||||
dir_path: dir_path,
|
|
||||||
entries: vec![],
|
entries: vec![],
|
||||||
pos: 0,
|
current: None,
|
||||||
phantom: PhantomData,
|
dir_path: dir_path,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,19 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<C, I, S> QueueCorpusScheduler<C, I, S>
|
||||||
|
where
|
||||||
|
S: HasCorpus<C, I>,
|
||||||
|
C: Corpus<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
@ -15,7 +15,6 @@ use crate::{
|
|||||||
inputs::{HasTargetBytes, Input},
|
inputs::{HasTargetBytes, Input},
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
state::{HasObjectives, HasSolutions},
|
state::{HasObjectives, HasSolutions},
|
||||||
utils::Rand,
|
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -124,7 +123,7 @@ where
|
|||||||
/// * `name` - the name of this executor (to address it along the way)
|
/// * `name` - the name of this executor (to address it along the way)
|
||||||
/// * `harness_fn` - the harness, executiong the function
|
/// * `harness_fn` - the harness, executiong the function
|
||||||
/// * `observers` - the observers observing the target during execution
|
/// * `observers` - the observers observing the target during execution
|
||||||
pub fn new<EM, OC, OFT, R, S>(
|
pub fn new<EM, OC, OFT, S>(
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
harness_fn: HarnessFunction<Self>,
|
harness_fn: HarnessFunction<Self>,
|
||||||
observers: OT,
|
observers: OT,
|
||||||
@ -136,12 +135,11 @@ where
|
|||||||
OC: Corpus<I>,
|
OC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OFT: FeedbacksTuple<I>,
|
||||||
S: HasObjectives<OFT, I> + HasSolutions<OC, I>,
|
S: HasObjectives<OFT, I> + HasSolutions<OC, I>,
|
||||||
R: Rand,
|
|
||||||
{
|
{
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
unsafe {
|
unsafe {
|
||||||
setup_crash_handlers::<EM, I, OC, OFT, OT, R, S>();
|
setup_crash_handlers::<EM, I, OC, OFT, OT, S>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@ -179,7 +177,6 @@ pub mod unix_signals {
|
|||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
state::{HasObjectives, HasSolutions},
|
state::{HasObjectives, HasSolutions},
|
||||||
utils::Rand,
|
|
||||||
};
|
};
|
||||||
/// Let's get 8 mb for now.
|
/// Let's get 8 mb for now.
|
||||||
const SIGNAL_STACK_SIZE: usize = 2 << 22;
|
const SIGNAL_STACK_SIZE: usize = 2 << 22;
|
||||||
@ -195,18 +192,14 @@ pub mod unix_signals {
|
|||||||
/// This is needed for certain non-rust side effects, as well as unix signal handling.
|
/// This is needed for certain non-rust side effects, as well as unix signal handling.
|
||||||
static mut CURRENT_INPUT_PTR: *const c_void = ptr::null();
|
static mut CURRENT_INPUT_PTR: *const c_void = ptr::null();
|
||||||
|
|
||||||
unsafe fn inmem_handle_crash<EM, I, OC, OFT, OT, R, S>(
|
unsafe fn inmem_handle_crash<EM, I, OC, OFT, OT, S>(_sig: c_int, info: siginfo_t, _void: c_void)
|
||||||
_sig: c_int,
|
where
|
||||||
info: siginfo_t,
|
|
||||||
_void: c_void,
|
|
||||||
) where
|
|
||||||
EM: EventManager<I, S>,
|
EM: EventManager<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
OC: Corpus<I>,
|
OC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OFT: FeedbacksTuple<I>,
|
||||||
S: HasObjectives<OFT, I> + HasSolutions<OC, I>,
|
S: HasObjectives<OFT, I> + HasSolutions<OC, I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
|
||||||
{
|
{
|
||||||
if CURRENT_INPUT_PTR == ptr::null() {
|
if CURRENT_INPUT_PTR == ptr::null() {
|
||||||
println!(
|
println!(
|
||||||
@ -271,7 +264,7 @@ pub mod unix_signals {
|
|||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn inmem_handle_timeout<EM, I, OC, OFT, OT, R, S>(
|
unsafe fn inmem_handle_timeout<EM, I, OC, OFT, OT, S>(
|
||||||
_sig: c_int,
|
_sig: c_int,
|
||||||
_info: siginfo_t,
|
_info: siginfo_t,
|
||||||
_void: c_void,
|
_void: c_void,
|
||||||
@ -282,7 +275,6 @@ pub mod unix_signals {
|
|||||||
OFT: FeedbacksTuple<I>,
|
OFT: FeedbacksTuple<I>,
|
||||||
S: HasObjectives<OFT, I> + HasSolutions<OC, I>,
|
S: HasObjectives<OFT, I> + HasSolutions<OC, I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
|
||||||
{
|
{
|
||||||
dbg!("TIMEOUT/SIGUSR2 received");
|
dbg!("TIMEOUT/SIGUSR2 received");
|
||||||
if CURRENT_INPUT_PTR.is_null() {
|
if CURRENT_INPUT_PTR.is_null() {
|
||||||
@ -350,7 +342,7 @@ pub mod unix_signals {
|
|||||||
OBSERVERS_PTR = ptr::null();
|
OBSERVERS_PTR = ptr::null();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn setup_crash_handlers<EM, I, OC, OFT, OT, R, S>()
|
pub unsafe fn setup_crash_handlers<EM, I, OC, OFT, OT, S>()
|
||||||
where
|
where
|
||||||
EM: EventManager<I, S>,
|
EM: EventManager<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
@ -358,7 +350,6 @@ pub mod unix_signals {
|
|||||||
OFT: FeedbacksTuple<I>,
|
OFT: FeedbacksTuple<I>,
|
||||||
S: HasObjectives<OFT, I> + HasSolutions<OC, I>,
|
S: HasObjectives<OFT, I> + HasSolutions<OC, I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
|
||||||
{
|
{
|
||||||
// First, set up our own stack to be used during segfault handling. (and specify `SA_ONSTACK` in `sigaction`)
|
// First, set up our own stack to be used during segfault handling. (and specify `SA_ONSTACK` in `sigaction`)
|
||||||
if SIGNAL_STACK_PTR.is_null() {
|
if SIGNAL_STACK_PTR.is_null() {
|
||||||
@ -375,7 +366,7 @@ pub mod unix_signals {
|
|||||||
let mut sa: sigaction = mem::zeroed();
|
let mut sa: sigaction = mem::zeroed();
|
||||||
libc::sigemptyset(&mut sa.sa_mask as *mut libc::sigset_t);
|
libc::sigemptyset(&mut sa.sa_mask as *mut libc::sigset_t);
|
||||||
sa.sa_flags = SA_NODEFER | SA_SIGINFO | SA_ONSTACK;
|
sa.sa_flags = SA_NODEFER | SA_SIGINFO | SA_ONSTACK;
|
||||||
sa.sa_sigaction = inmem_handle_crash::<EM, I, OC, OFT, OT, R, S> as usize;
|
sa.sa_sigaction = inmem_handle_crash::<EM, I, OC, OFT, OT, S> as usize;
|
||||||
for (sig, msg) in &[
|
for (sig, msg) in &[
|
||||||
(SIGSEGV, "segfault"),
|
(SIGSEGV, "segfault"),
|
||||||
(SIGBUS, "sigbus"),
|
(SIGBUS, "sigbus"),
|
||||||
@ -389,7 +380,7 @@ pub mod unix_signals {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sa.sa_sigaction = inmem_handle_timeout::<EM, I, OC, OFT, OT, R, S> as usize;
|
sa.sa_sigaction = inmem_handle_timeout::<EM, I, OC, OFT, OT, S> as usize;
|
||||||
if sigaction(SIGUSR2, &mut sa as *mut sigaction, ptr::null_mut()) < 0 {
|
if sigaction(SIGUSR2, &mut sa as *mut sigaction, ptr::null_mut()) < 0 {
|
||||||
panic!("Could not set up sigusr2 handler for timeouts");
|
panic!("Could not set up sigusr2 handler for timeouts");
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,12 @@ use crate::{
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
/// Holds a set of stages
|
/// Holds a set of stages
|
||||||
pub trait HasStages<ST, E, EM, S>: Sized
|
pub trait HasStages<ST, E, EM, I, S>
|
||||||
where
|
where
|
||||||
ST: StagesTuple<E, EM, Self, S>,
|
ST: StagesTuple<E, EM, I, S>,
|
||||||
|
E: Executor<I>,
|
||||||
|
EM: EventManager<I, S>,
|
||||||
|
I: Input,
|
||||||
{
|
{
|
||||||
fn stages(&self) -> &ST;
|
fn stages(&self) -> &ST;
|
||||||
|
|
||||||
@ -44,7 +47,9 @@ pub trait Fuzzer<E, EM, S> {
|
|||||||
pub struct StdFuzzer<CS, ST, E, EM, I, OT, S>
|
pub struct StdFuzzer<CS, ST, E, EM, I, OT, S>
|
||||||
where
|
where
|
||||||
CS: CorpusScheduler<I, S>,
|
CS: CorpusScheduler<I, S>,
|
||||||
ST: StagesTuple<E, EM, Self, S>,
|
ST: StagesTuple<E, EM, I, S>,
|
||||||
|
E: Executor<I>,
|
||||||
|
EM: EventManager<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
scheduler: CS,
|
scheduler: CS,
|
||||||
@ -52,10 +57,12 @@ where
|
|||||||
phantom: PhantomData<(E, EM, I, OT, S)>,
|
phantom: PhantomData<(E, EM, I, OT, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<CS, ST, E, EM, I, OT, S> HasStages<ST, E, EM, S> for StdFuzzer<CS, ST, E, EM, I, OT, S>
|
impl<CS, ST, E, EM, I, OT, S> HasStages<ST, E, EM, I, S> for StdFuzzer<CS, ST, E, EM, I, OT, S>
|
||||||
where
|
where
|
||||||
CS: CorpusScheduler<I, S>,
|
CS: CorpusScheduler<I, S>,
|
||||||
ST: StagesTuple<E, EM, Self, S>,
|
ST: StagesTuple<E, EM, I, S>,
|
||||||
|
E: Executor<I>,
|
||||||
|
EM: EventManager<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn stages(&self) -> &ST {
|
fn stages(&self) -> &ST {
|
||||||
@ -70,7 +77,9 @@ where
|
|||||||
impl<CS, ST, E, EM, I, OT, S> HasCorpusScheduler<CS, I, S> for StdFuzzer<CS, ST, E, EM, I, OT, S>
|
impl<CS, ST, E, EM, I, OT, S> HasCorpusScheduler<CS, I, S> for StdFuzzer<CS, ST, E, EM, I, OT, S>
|
||||||
where
|
where
|
||||||
CS: CorpusScheduler<I, S>,
|
CS: CorpusScheduler<I, S>,
|
||||||
ST: StagesTuple<E, EM, Self, S>,
|
ST: StagesTuple<E, EM, I, S>,
|
||||||
|
E: Executor<I>,
|
||||||
|
EM: EventManager<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn scheduler(&self) -> &CS {
|
fn scheduler(&self) -> &CS {
|
||||||
@ -86,7 +95,7 @@ impl<CS, ST, E, EM, I, OT, S> Fuzzer<E, EM, S> for StdFuzzer<CS, ST, E, EM, I, O
|
|||||||
where
|
where
|
||||||
CS: CorpusScheduler<I, S>,
|
CS: CorpusScheduler<I, S>,
|
||||||
S: HasExecutions,
|
S: HasExecutions,
|
||||||
ST: StagesTuple<E, EM, Self, S>,
|
ST: StagesTuple<E, EM, I, S>,
|
||||||
EM: EventManager<I, S>,
|
EM: EventManager<I, S>,
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I> + HasObservers<OT>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
@ -95,8 +104,7 @@ where
|
|||||||
fn fuzz_one(&self, state: &mut S, executor: &mut E, manager: &mut EM) -> Result<usize, Error> {
|
fn fuzz_one(&self, state: &mut S, executor: &mut E, manager: &mut EM) -> Result<usize, Error> {
|
||||||
let idx = self.scheduler().next(state)?;
|
let idx = self.scheduler().next(state)?;
|
||||||
|
|
||||||
self.stages()
|
self.stages().perform_all(state, executor, manager, idx)?;
|
||||||
.perform_all(self, state, executor, manager, idx)?;
|
|
||||||
|
|
||||||
manager.process(state, executor)?;
|
manager.process(state, executor)?;
|
||||||
Ok(idx)
|
Ok(idx)
|
||||||
@ -125,7 +133,9 @@ where
|
|||||||
impl<CS, ST, E, EM, I, OT, S> StdFuzzer<CS, ST, E, EM, I, OT, S>
|
impl<CS, ST, E, EM, I, OT, S> StdFuzzer<CS, ST, E, EM, I, OT, S>
|
||||||
where
|
where
|
||||||
CS: CorpusScheduler<I, S>,
|
CS: CorpusScheduler<I, S>,
|
||||||
ST: StagesTuple<E, EM, Self, S>,
|
ST: StagesTuple<E, EM, I, S>,
|
||||||
|
E: Executor<I>,
|
||||||
|
EM: EventManager<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
pub fn new(scheduler: CS, stages: ST) -> Self {
|
pub fn new(scheduler: CS, stages: ST) -> Self {
|
||||||
|
@ -14,18 +14,16 @@ use crate::{inputs::Input, Error};
|
|||||||
|
|
||||||
/// A mutator takes input, and mutates it.
|
/// A mutator takes input, and mutates it.
|
||||||
/// Simple as that.
|
/// Simple as that.
|
||||||
pub trait Mutator<F, I, S>
|
pub trait Mutator<I, S>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
/// Mutate a given input
|
/// Mutate a given input
|
||||||
fn mutate(&self, fuzzer: &F, state: &mut S, input: &mut I, stage_idx: i32)
|
fn mutate(&self, state: &mut S, input: &mut I, stage_idx: i32) -> Result<(), Error>;
|
||||||
-> Result<(), Error>;
|
|
||||||
|
|
||||||
/// Post-process given the outcome of the execution
|
/// Post-process given the outcome of the execution
|
||||||
fn post_exec(
|
fn post_exec(
|
||||||
&self,
|
&self,
|
||||||
_fuzzer: &F,
|
|
||||||
_state: &mut S,
|
_state: &mut S,
|
||||||
_is_interesting: u32,
|
_is_interesting: u32,
|
||||||
_stage_idx: i32,
|
_stage_idx: i32,
|
||||||
|
@ -27,20 +27,20 @@ pub enum MutationResult {
|
|||||||
|
|
||||||
// TODO maybe the mutator arg is not needed
|
// TODO maybe the mutator arg is not needed
|
||||||
/// The generic function type that identifies mutations
|
/// The generic function type that identifies mutations
|
||||||
pub type MutationFunction<F, I, M, S> = fn(&M, &F, &mut S, &mut I) -> Result<MutationResult, Error>;
|
pub type MutationFunction<I, M, S> = fn(&M, &mut S, &mut I) -> Result<MutationResult, Error>;
|
||||||
|
|
||||||
pub trait ComposedByMutations<F, I, S>
|
pub trait ComposedByMutations<I, S>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
/// Get a mutation by index
|
/// Get a mutation by index
|
||||||
fn mutation_by_idx(&self, index: usize) -> MutationFunction<F, I, Self, S>;
|
fn mutation_by_idx(&self, index: usize) -> MutationFunction<I, Self, S>;
|
||||||
|
|
||||||
/// Get the number of mutations
|
/// Get the number of mutations
|
||||||
fn mutations_count(&self) -> usize;
|
fn mutations_count(&self) -> usize;
|
||||||
|
|
||||||
/// Add a mutation
|
/// Add a mutation
|
||||||
fn add_mutation(&mut self, mutation: MutationFunction<F, I, Self, S>);
|
fn add_mutation(&mut self, mutation: MutationFunction<I, Self, S>);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mem move in the own vec
|
/// Mem move in the own vec
|
||||||
@ -123,9 +123,9 @@ const INTERESTING_32: [i32; 27] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
/// Bitflip mutation for inputs with a bytes vector
|
/// Bitflip mutation for inputs with a bytes vector
|
||||||
pub fn mutation_bitflip<F, I, M, R, S>(
|
pub fn mutation_bitflip<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -146,9 +146,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_byteflip<F, I, M, R, S>(
|
pub fn mutation_byteflip<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -169,9 +169,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_byteinc<F, I, M, R, S>(
|
pub fn mutation_byteinc<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -193,9 +193,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_bytedec<F, I, M, R, S>(
|
pub fn mutation_bytedec<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -217,9 +217,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_byteneg<F, I, M, R, S>(
|
pub fn mutation_byteneg<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -240,9 +240,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_byterand<F, I, M, R, S>(
|
pub fn mutation_byterand<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -263,9 +263,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_byteadd<F, I, M, R, S>(
|
pub fn mutation_byteadd<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -291,9 +291,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_wordadd<F, I, M, R, S>(
|
pub fn mutation_wordadd<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -321,9 +321,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_dwordadd<F, I, M, R, S>(
|
pub fn mutation_dwordadd<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -351,9 +351,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_qwordadd<F, I, M, R, S>(
|
pub fn mutation_qwordadd<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -381,9 +381,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_byteinteresting<F, I, M, R, S>(
|
pub fn mutation_byteinteresting<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -405,9 +405,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_wordinteresting<F, I, M, R, S>(
|
pub fn mutation_wordinteresting<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -435,9 +435,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_dwordinteresting<F, I, M, R, S>(
|
pub fn mutation_dwordinteresting<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -465,9 +465,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_bytesdelete<F, I, M, R, S>(
|
pub fn mutation_bytesdelete<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -488,9 +488,9 @@ where
|
|||||||
Ok(MutationResult::Mutated)
|
Ok(MutationResult::Mutated)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_bytesexpand<F, I, M, R, S>(
|
pub fn mutation_bytesexpand<I, M, R, S>(
|
||||||
mutator: &M,
|
mutator: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -518,9 +518,9 @@ where
|
|||||||
Ok(MutationResult::Mutated)
|
Ok(MutationResult::Mutated)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_bytesinsert<F, I, M, R, S>(
|
pub fn mutation_bytesinsert<I, M, R, S>(
|
||||||
mutator: &M,
|
mutator: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -551,9 +551,9 @@ where
|
|||||||
Ok(MutationResult::Mutated)
|
Ok(MutationResult::Mutated)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_bytesrandinsert<F, I, M, R, S>(
|
pub fn mutation_bytesrandinsert<I, M, R, S>(
|
||||||
mutator: &M,
|
mutator: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -584,9 +584,9 @@ where
|
|||||||
Ok(MutationResult::Mutated)
|
Ok(MutationResult::Mutated)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_bytesset<F, I, M, R, S>(
|
pub fn mutation_bytesset<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -609,9 +609,9 @@ where
|
|||||||
Ok(MutationResult::Mutated)
|
Ok(MutationResult::Mutated)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_bytesrandset<F, I, M, R, S>(
|
pub fn mutation_bytesrandset<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -634,9 +634,9 @@ where
|
|||||||
Ok(MutationResult::Mutated)
|
Ok(MutationResult::Mutated)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_bytescopy<F, I, M, R, S>(
|
pub fn mutation_bytescopy<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -659,9 +659,9 @@ where
|
|||||||
Ok(MutationResult::Mutated)
|
Ok(MutationResult::Mutated)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutation_bytesswap<F, I, M, R, S>(
|
pub fn mutation_bytesswap<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -687,9 +687,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Crossover insert mutation
|
/// Crossover insert mutation
|
||||||
pub fn mutation_crossover_insert<C, F, I, M, R, S>(
|
pub fn mutation_crossover_insert<C, I, M, R, S>(
|
||||||
mutator: &M,
|
mutator: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -745,9 +745,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Crossover replace mutation
|
/// Crossover replace mutation
|
||||||
pub fn mutation_crossover_replace<C, F, I, M, R, S>(
|
pub fn mutation_crossover_replace<C, I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -808,9 +808,9 @@ fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Splicing mutation from AFL
|
/// Splicing mutation from AFL
|
||||||
pub fn mutation_splice<C, F, I, M, R, S>(
|
pub fn mutation_splice<C, I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
|
@ -15,7 +15,7 @@ use crate::{
|
|||||||
pub use crate::mutators::mutations::*;
|
pub use crate::mutators::mutations::*;
|
||||||
pub use crate::mutators::token_mutations::*;
|
pub use crate::mutators::token_mutations::*;
|
||||||
|
|
||||||
pub trait ScheduledMutator<F, I, S>: Mutator<F, I, S> + ComposedByMutations<F, I, S>
|
pub trait ScheduledMutator<I, S>: Mutator<I, S> + ComposedByMutations<I, S>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
@ -27,34 +27,28 @@ where
|
|||||||
|
|
||||||
/// New default implementation for mutate
|
/// New default implementation for mutate
|
||||||
/// Implementations must forward mutate() to this method
|
/// Implementations must forward mutate() to this method
|
||||||
fn scheduled_mutate(
|
fn scheduled_mutate(&self, state: &mut S, input: &mut I, _stage_idx: i32) -> Result<(), Error> {
|
||||||
&self,
|
|
||||||
fuzzer: &F,
|
|
||||||
state: &mut S,
|
|
||||||
input: &mut I,
|
|
||||||
_stage_idx: i32,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let num = self.iterations(state, input);
|
let num = self.iterations(state, input);
|
||||||
for _ in 0..num {
|
for _ in 0..num {
|
||||||
let idx = self.schedule(self.mutations_count(), state, input);
|
let idx = self.schedule(self.mutations_count(), state, input);
|
||||||
self.mutation_by_idx(idx)(self, fuzzer, state, input)?;
|
self.mutation_by_idx(idx)(self, state, input)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StdScheduledMutator<F, I, R, S>
|
pub struct StdScheduledMutator<I, R, S>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
S: HasRand<R>,
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
mutations: Vec<MutationFunction<F, I, Self, S>>,
|
mutations: Vec<MutationFunction<I, Self, S>>,
|
||||||
max_size: usize,
|
max_size: usize,
|
||||||
phantom: PhantomData<R>,
|
phantom: PhantomData<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, I, R, S> Debug for StdScheduledMutator<F, I, R, S>
|
impl<I, R, S> Debug for StdScheduledMutator<I, R, S>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
S: HasRand<R>,
|
S: HasRand<R>,
|
||||||
@ -71,31 +65,25 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, I, R, S> Mutator<F, I, S> for StdScheduledMutator<F, I, R, S>
|
impl<I, R, S> Mutator<I, S> for StdScheduledMutator<I, R, S>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
S: HasRand<R>,
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
fn mutate(
|
fn mutate(&self, state: &mut S, input: &mut I, _stage_idx: i32) -> Result<(), Error> {
|
||||||
&self,
|
self.scheduled_mutate(state, input, _stage_idx)
|
||||||
fuzzer: &F,
|
|
||||||
state: &mut S,
|
|
||||||
input: &mut I,
|
|
||||||
_stage_idx: i32,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.scheduled_mutate(fuzzer, state, input, _stage_idx)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, I, R, S> ComposedByMutations<F, I, S> for StdScheduledMutator<F, I, R, S>
|
impl<I, R, S> ComposedByMutations<I, S> for StdScheduledMutator<I, R, S>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
S: HasRand<R>,
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mutation_by_idx(&self, index: usize) -> MutationFunction<F, I, Self, S> {
|
fn mutation_by_idx(&self, index: usize) -> MutationFunction<I, Self, S> {
|
||||||
self.mutations[index]
|
self.mutations[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,12 +93,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add_mutation(&mut self, mutation: MutationFunction<F, I, Self, S>) {
|
fn add_mutation(&mut self, mutation: MutationFunction<I, Self, S>) {
|
||||||
self.mutations.push(mutation)
|
self.mutations.push(mutation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, I, R, S> ScheduledMutator<F, I, S> for StdScheduledMutator<F, I, R, S>
|
impl<I, R, S> ScheduledMutator<I, S> for StdScheduledMutator<I, R, S>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
S: HasRand<R>,
|
S: HasRand<R>,
|
||||||
@ -128,7 +116,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, I, R, S> HasMaxSize for StdScheduledMutator<F, I, R, S>
|
impl<I, R, S> HasMaxSize for StdScheduledMutator<I, R, S>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
S: HasRand<R>,
|
S: HasRand<R>,
|
||||||
@ -145,7 +133,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, I, R, S> StdScheduledMutator<F, I, R, S>
|
impl<I, R, S> StdScheduledMutator<I, R, S>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
S: HasRand<R>,
|
S: HasRand<R>,
|
||||||
@ -161,7 +149,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new StdScheduledMutator instance specifying mutations
|
/// Create a new StdScheduledMutator instance specifying mutations
|
||||||
pub fn with_mutations(mutations: Vec<MutationFunction<F, I, Self, S>>) -> Self {
|
pub fn with_mutations(mutations: Vec<MutationFunction<I, Self, S>>) -> Self {
|
||||||
StdScheduledMutator {
|
StdScheduledMutator {
|
||||||
mutations: mutations,
|
mutations: mutations,
|
||||||
max_size: DEFAULT_MAX_SIZE,
|
max_size: DEFAULT_MAX_SIZE,
|
||||||
@ -172,35 +160,29 @@ where
|
|||||||
|
|
||||||
/// Schedule some selected byte level mutations given a ScheduledMutator type
|
/// Schedule some selected byte level mutations given a ScheduledMutator type
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct HavocBytesMutator<C, F, I, R, S, SM>
|
pub struct HavocBytesMutator<C, I, R, S, SM>
|
||||||
where
|
where
|
||||||
SM: ScheduledMutator<F, I, S> + HasMaxSize,
|
SM: ScheduledMutator<I, S> + HasMaxSize,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
scheduled: SM,
|
scheduled: SM,
|
||||||
phantom: PhantomData<(C, F, I, R, S)>,
|
phantom: PhantomData<(C, I, R, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, F, I, R, S, SM> Mutator<F, I, S> for HavocBytesMutator<C, F, I, R, S, SM>
|
impl<C, I, R, S, SM> Mutator<I, S> for HavocBytesMutator<C, I, R, S, SM>
|
||||||
where
|
where
|
||||||
SM: ScheduledMutator<F, I, S> + HasMaxSize,
|
SM: ScheduledMutator<I, S> + HasMaxSize,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
/// Mutate bytes
|
/// Mutate bytes
|
||||||
fn mutate(
|
fn mutate(&self, state: &mut S, input: &mut I, stage_idx: i32) -> Result<(), Error> {
|
||||||
&self,
|
self.scheduled.mutate(state, input, stage_idx)?;
|
||||||
fuzzer: &F,
|
|
||||||
state: &mut S,
|
|
||||||
input: &mut I,
|
|
||||||
stage_idx: i32,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.scheduled.mutate(fuzzer, state, input, stage_idx)?;
|
|
||||||
/*let num = self.scheduled.iterations(state, input);
|
/*let num = self.scheduled.iterations(state, input);
|
||||||
for _ in 0..num {
|
for _ in 0..num {
|
||||||
let idx = self.scheduled.schedule(14, state, input);
|
let idx = self.scheduled.schedule(14, state, input);
|
||||||
@ -226,9 +208,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, F, I, R, S, SM> HasMaxSize for HavocBytesMutator<C, F, I, R, S, SM>
|
impl<C, I, R, S, SM> HasMaxSize for HavocBytesMutator<C, I, R, S, SM>
|
||||||
where
|
where
|
||||||
SM: ScheduledMutator<F, I, S> + HasMaxSize,
|
SM: ScheduledMutator<I, S> + HasMaxSize,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
@ -245,9 +227,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, F, I, R, S, SM> HavocBytesMutator<C, F, I, R, S, SM>
|
impl<C, I, R, S, SM> HavocBytesMutator<C, I, R, S, SM>
|
||||||
where
|
where
|
||||||
SM: ScheduledMutator<F, I, S> + HasMaxSize,
|
SM: ScheduledMutator<I, S> + HasMaxSize,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
@ -264,7 +246,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, F, I, R, S> Default for HavocBytesMutator<C, F, I, R, S, StdScheduledMutator<F, I, R, S>>
|
impl<C, I, R, S> Default for HavocBytesMutator<C, I, R, S, StdScheduledMutator<I, R, S>>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
||||||
@ -273,7 +255,7 @@ where
|
|||||||
{
|
{
|
||||||
/// Create a new HavocBytesMutator instance wrapping StdScheduledMutator
|
/// Create a new HavocBytesMutator instance wrapping StdScheduledMutator
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let mut scheduled = StdScheduledMutator::<F, I, R, S>::new();
|
let mut scheduled = StdScheduledMutator::<I, R, S>::new();
|
||||||
scheduled.add_mutation(mutation_bitflip);
|
scheduled.add_mutation(mutation_bitflip);
|
||||||
scheduled.add_mutation(mutation_byteflip);
|
scheduled.add_mutation(mutation_byteflip);
|
||||||
scheduled.add_mutation(mutation_byteinc);
|
scheduled.add_mutation(mutation_byteinc);
|
||||||
|
@ -30,9 +30,8 @@ impl TokensMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a dictionary token
|
/// Insert a dictionary token
|
||||||
pub fn mutation_tokeninsert<F, I, M, R, S>(
|
pub fn mutation_tokeninsert<I, M, R, S>(
|
||||||
mutator: &M,
|
mutator: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
@ -77,9 +76,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Overwrite with a dictionary token
|
/// Overwrite with a dictionary token
|
||||||
pub fn mutation_tokenreplace<F, I, M, R, S>(
|
pub fn mutation_tokenreplace<I, M, R, S>(
|
||||||
_: &M,
|
_: &M,
|
||||||
_: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
pub mod mutational;
|
pub mod mutational;
|
||||||
pub use mutational::StdMutationalStage;
|
pub use mutational::StdMutationalStage;
|
||||||
|
|
||||||
use crate::{bolts::tuples::TupleList, Error};
|
use crate::{
|
||||||
|
bolts::tuples::TupleList, events::EventManager, executors::Executor, inputs::Input, Error,
|
||||||
|
};
|
||||||
|
|
||||||
/// A stage is one step in the fuzzing process.
|
/// A stage is one step in the fuzzing process.
|
||||||
/// Multiple stages will be scheduled one by one for each input.
|
/// Multiple stages will be scheduled one by one for each input.
|
||||||
pub trait Stage<E, EM, F, S> {
|
pub trait Stage<E, EM, I, S>
|
||||||
|
where
|
||||||
|
EM: EventManager<I, S>,
|
||||||
|
E: Executor<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
/// Run the stage
|
/// Run the stage
|
||||||
fn perform(
|
fn perform(
|
||||||
&self,
|
&self,
|
||||||
fuzzer: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
@ -17,10 +23,14 @@ pub trait Stage<E, EM, F, S> {
|
|||||||
) -> Result<(), Error>;
|
) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait StagesTuple<E, EM, F, S> {
|
pub trait StagesTuple<E, EM, I, S>
|
||||||
|
where
|
||||||
|
EM: EventManager<I, S>,
|
||||||
|
E: Executor<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
fn perform_all(
|
fn perform_all(
|
||||||
&self,
|
&self,
|
||||||
fuzzer: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
@ -28,28 +38,33 @@ pub trait StagesTuple<E, EM, F, S> {
|
|||||||
) -> Result<(), Error>;
|
) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EM, F, S> StagesTuple<E, EM, F, S> for () {
|
impl<E, EM, I, S> StagesTuple<E, EM, I, S> for ()
|
||||||
fn perform_all(&self, _: &F, _: &mut S, _: &mut E, _: &mut EM, _: usize) -> Result<(), Error> {
|
where
|
||||||
|
EM: EventManager<I, S>,
|
||||||
|
E: Executor<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
fn perform_all(&self, _: &mut S, _: &mut E, _: &mut EM, _: usize) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Head, Tail, E, EM, F, S> StagesTuple<E, EM, F, S> for (Head, Tail)
|
impl<Head, Tail, E, EM, I, S> StagesTuple<E, EM, I, S> for (Head, Tail)
|
||||||
where
|
where
|
||||||
Head: Stage<E, EM, F, S>,
|
Head: Stage<E, EM, I, S>,
|
||||||
Tail: StagesTuple<E, EM, F, S> + TupleList,
|
Tail: StagesTuple<E, EM, I, S> + TupleList,
|
||||||
|
EM: EventManager<I, S>,
|
||||||
|
E: Executor<I>,
|
||||||
|
I: Input,
|
||||||
{
|
{
|
||||||
fn perform_all(
|
fn perform_all(
|
||||||
&self,
|
&self,
|
||||||
fuzzer: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
corpus_idx: usize,
|
corpus_idx: usize,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.0
|
self.0.perform(state, executor, manager, corpus_idx)?;
|
||||||
.perform(fuzzer, state, executor, manager, corpus_idx)?;
|
self.1.perform_all(state, executor, manager, corpus_idx)
|
||||||
self.1
|
|
||||||
.perform_all(fuzzer, state, executor, manager, corpus_idx)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,9 @@ use crate::{
|
|||||||
/// A Mutational stage is the stage in a fuzzing run that mutates inputs.
|
/// A Mutational stage is the stage in a fuzzing run that mutates inputs.
|
||||||
/// Mutational stages will usually have a range of mutations that are
|
/// Mutational stages will usually have a range of mutations that are
|
||||||
/// being applied to the input one by one, between executions.
|
/// being applied to the input one by one, between executions.
|
||||||
pub trait MutationalStage<C, E, EM, F, I, M, OT, S>: Stage<E, EM, F, S>
|
pub trait MutationalStage<C, E, EM, I, M, OT, S>: Stage<E, EM, I, S>
|
||||||
where
|
where
|
||||||
M: Mutator<F, I, S>,
|
M: Mutator<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
S: HasCorpus<C, I> + Evaluator<I>,
|
S: HasCorpus<C, I> + Evaluator<I>,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
@ -40,7 +40,6 @@ where
|
|||||||
/// Runs this (mutational) stage for the given testcase
|
/// Runs this (mutational) stage for the given testcase
|
||||||
fn perform_mutational(
|
fn perform_mutational(
|
||||||
&self,
|
&self,
|
||||||
fuzzer: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
@ -54,12 +53,11 @@ where
|
|||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.load_input()?
|
.load_input()?
|
||||||
.clone();
|
.clone();
|
||||||
self.mutator()
|
self.mutator().mutate(state, &mut input_mut, i as i32)?;
|
||||||
.mutate(fuzzer, state, &mut input_mut, i as i32)?;
|
|
||||||
|
|
||||||
let fitness = state.evaluate_input(input_mut, executor, manager)?;
|
let fitness = state.evaluate_input(input_mut, executor, manager)?;
|
||||||
|
|
||||||
self.mutator().post_exec(fuzzer, state, fitness, i as i32)?;
|
self.mutator().post_exec(state, fitness, i as i32)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -69,9 +67,9 @@ pub static DEFAULT_MUTATIONAL_MAX_ITERATIONS: u64 = 128;
|
|||||||
|
|
||||||
/// The default mutational stage
|
/// The default mutational stage
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct StdMutationalStage<C, E, EM, F, I, M, OT, R, S>
|
pub struct StdMutationalStage<C, E, EM, I, M, OT, R, S>
|
||||||
where
|
where
|
||||||
M: Mutator<F, I, S>,
|
M: Mutator<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
S: HasCorpus<C, I> + Evaluator<I> + HasRand<R>,
|
S: HasCorpus<C, I> + Evaluator<I> + HasRand<R>,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
@ -81,13 +79,13 @@ where
|
|||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
mutator: M,
|
mutator: M,
|
||||||
phantom: PhantomData<(C, E, EM, F, I, OT, R, S)>,
|
phantom: PhantomData<(C, E, EM, I, OT, R, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, E, EM, F, I, M, OT, R, S> MutationalStage<C, E, EM, F, I, M, OT, S>
|
impl<C, E, EM, I, M, OT, R, S> MutationalStage<C, E, EM, I, M, OT, S>
|
||||||
for StdMutationalStage<C, E, EM, F, I, M, OT, R, S>
|
for StdMutationalStage<C, E, EM, I, M, OT, R, S>
|
||||||
where
|
where
|
||||||
M: Mutator<F, I, S>,
|
M: Mutator<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
S: HasCorpus<C, I> + Evaluator<I> + HasRand<R>,
|
S: HasCorpus<C, I> + Evaluator<I> + HasRand<R>,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
@ -114,10 +112,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, E, EM, F, I, M, OT, R, S> Stage<E, EM, F, S>
|
impl<C, E, EM, I, M, OT, R, S> Stage<E, EM, I, S> for StdMutationalStage<C, E, EM, I, M, OT, R, S>
|
||||||
for StdMutationalStage<C, E, EM, F, I, M, OT, R, S>
|
|
||||||
where
|
where
|
||||||
M: Mutator<F, I, S>,
|
M: Mutator<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
S: HasCorpus<C, I> + Evaluator<I> + HasRand<R>,
|
S: HasCorpus<C, I> + Evaluator<I> + HasRand<R>,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
@ -129,19 +126,18 @@ where
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn perform(
|
fn perform(
|
||||||
&self,
|
&self,
|
||||||
fuzzer: &F,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
corpus_idx: usize,
|
corpus_idx: usize,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.perform_mutational(fuzzer, state, executor, manager, corpus_idx)
|
self.perform_mutational(state, executor, manager, corpus_idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, E, EM, F, I, M, OT, R, S> StdMutationalStage<C, E, EM, F, I, M, OT, R, S>
|
impl<C, E, EM, I, M, OT, R, S> StdMutationalStage<C, E, EM, I, M, OT, R, S>
|
||||||
where
|
where
|
||||||
M: Mutator<F, I, S>,
|
M: Mutator<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
S: HasCorpus<C, I> + Evaluator<I> + HasRand<R>,
|
S: HasCorpus<C, I> + Evaluator<I> + HasRand<R>,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user