Merge branch 'main' into fix-default-prng

This commit is contained in:
Evan Richter 2021-02-25 15:50:30 -06:00 committed by GitHub
commit 00da3b975a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 200 additions and 284 deletions

44
.github/workflows/build_and_test.yml vendored Normal file
View File

@ -0,0 +1,44 @@
name: Build and Test
on: [push]
env:
CARGO_TERM_COLOR: always
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
run: cd libafl && cargo build --verbose
build-all:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
run: cd libafl &&cargo build --no-default-features --features runtime --features std --features anymapdbg --verbose
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Test
run: cd libafl && cargo test --verbose
build-no-std:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
run: cd libafl && cargo build --no-default-features --verbose
test-no-std:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Test
run: cd libafl && cargo test --no-default-features --verbose
docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Test
run: cd libafl && cargo doc

View File

@ -1,11 +1,13 @@
# LibAFL, the fuzzer library.
Advanced Fuzzing Library - Slot your own Fuzzers together and extend their features, using Rust.
Advanced Fuzzing Library - Slot your own fuzzers together and extend their features using Rust.
LibAFL is written and maintained by Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <mail@dmnk.co>.
It is released as Free and Open Source Software under the GNU Lesser General Public License V3.
## Example usages
We collect example fuzzers in `./fuzzers`.
@ -14,6 +16,10 @@ The best-tested fuzzer is `./fuzzers/libfuzzer_libpng`, a clone of libfuzzer usi
If you want to get a quick overview, run `cargo doc`.
Feel free to open issues or contact us directly. Thank you for your support. <3
## The Core Concepts
We're still working on the documentation. In the meantime, you can watch the Video from last year's Rc3, here:
[![Video explaining libAFL's core concepts](http://img.youtube.com/vi/3RWkT1Q5IV0/0.jpg)](http://www.youtube.com/watch?v=3RWkT1Q5IV0 "Fuzzers Like LEGO")
## Roadmap for release
+ Minset corpus scheduler

View File

@ -1,3 +1,4 @@
//! Poor-rust-man's downcasts for stuff we send over the wire (or shared maps)
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use alloc::boxed::Box;

View File

@ -1,3 +1,5 @@
//! Compiletime lists used throughout the libafl universe
pub use tuple_list::{tuple_list, tuple_list_type, TupleList};
use core::any::TypeId;

View File

@ -1,7 +1,7 @@
//! Eventmanager manages all events that go to other instances of the fuzzer.
pub mod logger;
pub use logger::*;
pub mod simple;
pub use simple::*;
pub mod llmp;
pub use llmp::*;

View File

@ -1,3 +1,4 @@
//! A very simple event manager, that just supports log outputs, but no multiprocessing
use alloc::{string::ToString, vec::Vec};
use core::marker::PhantomData;
@ -12,7 +13,7 @@ use crate::{
/// A simple, single-threaded event manager that just logs
#[derive(Clone, Debug)]
pub struct LoggerEventManager<I, S, ST>
pub struct SimpleEventManager<I, S, ST>
where
I: Input,
ST: Stats, //CE: CustomEvent<I, OT>,
@ -24,7 +25,7 @@ where
phantom: PhantomData<S>,
}
impl<I, S, ST> EventManager<I, S> for LoggerEventManager<I, S, ST>
impl<I, S, ST> EventManager<I, S> for SimpleEventManager<I, S, ST>
where
I: Input,
ST: Stats, //CE: CustomEvent<I, OT>,
@ -51,7 +52,7 @@ where
}
}
impl<I, S, ST> LoggerEventManager<I, S, ST>
impl<I, S, ST> SimpleEventManager<I, S, ST>
where
I: Input,
ST: Stats, //TODO CE: CustomEvent,

View File

@ -38,7 +38,7 @@ pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard(guard: &u32) {
//*trace_byte = (*trace_byte).wrapping_add(1);
}
/// Called when the targetprogram starts
/// Called when the target program starts
#[no_mangle]
#[inline]
pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard_init(mut start: *mut u32, stop: *mut u32) {

View File

@ -117,7 +117,6 @@ impl From<ParseIntError> for Error {
}
}
/*
// TODO: no_std test
#[cfg(feature = "std")]
#[cfg(test)]
@ -125,7 +124,7 @@ mod tests {
use crate::{
bolts::tuples::tuple_list,
corpus::{Corpus, InMemoryCorpus, Testcase},
corpus::{Corpus, InMemoryCorpus, RandCorpusScheduler, Testcase},
executors::{Executor, ExitKind, InProcessExecutor},
inputs::{BytesInput, Input},
mutators::{mutation_bitflip, ComposedByMutations, StdScheduledMutator},
@ -137,7 +136,7 @@ mod tests {
};
#[cfg(feature = "std")]
use crate::events::LoggerEventManager;
use crate::events::SimpleEventManager;
fn harness<E: Executor<I>, I: Input>(_executor: &E, _buf: &[u8]) -> ExitKind {
ExitKind::Ok
@ -145,23 +144,24 @@ mod tests {
#[test]
fn test_fuzzer() {
let mut rand = StdRand::new(0);
let rand = StdRand::new(0);
let mut corpus = InMemoryCorpus::<BytesInput, StdRand>::new();
let mut corpus = InMemoryCorpus::<BytesInput>::new();
let testcase = Testcase::new(vec![0; 4]).into();
corpus.add(testcase);
corpus.add(testcase).unwrap();
let mut state = State::new(
rand,
corpus,
tuple_list!(),
InMemoryCorpus::<BytesInput, StdRand>::new(),
InMemoryCorpus::<BytesInput>::new(),
tuple_list!(),
);
let stats = SimpleStats::new(|s| {
println!("{}", s);
});
let mut event_manager = LoggerEventManager::new(stats);
let mut event_manager = SimpleEventManager::new(stats);
let mut executor = InProcessExecutor::new(
"main",
@ -175,29 +175,28 @@ mod tests {
let mut mutator = StdScheduledMutator::new();
mutator.add_mutation(mutation_bitflip);
let stage = StdMutationalStage::new(mutator);
let mut fuzzer = StdFuzzer::new(tuple_list!(stage));
let fuzzer = StdFuzzer::new(RandCorpusScheduler::new(), tuple_list!(stage));
for i in 0..1000 {
fuzzer
.fuzz_one(&mut rand, &mut executor, &mut state, &mut event_manager)
.fuzz_one(&mut state, &mut executor, &mut event_manager)
.expect(&format!("Error in iter {}", i));
}
let state_serialized = postcard::to_allocvec(&state).unwrap();
let state_deserialized: State<
InMemoryCorpus<BytesInput, _>,
InMemoryCorpus<BytesInput>,
(),
BytesInput,
InMemoryCorpus<BytesInput, _>,
(),
StdRand,
InMemoryCorpus<BytesInput>,
> = postcard::from_bytes(state_serialized.as_slice()).unwrap();
assert_eq!(state.executions(), state_deserialized.executions());
assert_eq!(state.corpus().count(), state_deserialized.corpus().count());
let corpus_serialized = postcard::to_allocvec(state.corpus()).unwrap();
let corpus_deserialized: InMemoryCorpus<BytesInput, StdRand> =
let corpus_deserialized: InMemoryCorpus<BytesInput> =
postcard::from_bytes(corpus_serialized.as_slice()).unwrap();
assert_eq!(state.corpus().count(), corpus_deserialized.count());
}
}
*/

View File

@ -31,14 +31,3 @@ where
Ok(())
}
}
/// The maximum size of a testcase
pub const DEFAULT_MAX_SIZE: usize = 1048576;
/// Interact with the maximum size
pub trait HasMaxSize {
/// The maximum size of the contents returned
fn max_size(&self) -> usize;
/// Sets the maximum size of the contents returned
fn set_max_size(&mut self, max_size: usize);
}

View File

@ -1,8 +1,9 @@
//! A wide variety of mutations used during fuzzing.
use crate::{
corpus::Corpus,
inputs::{HasBytesVec, Input},
mutators::*,
state::{HasCorpus, HasRand},
state::{HasCorpus, HasMaxSize, HasRand},
utils::Rand,
Error,
};
@ -27,20 +28,20 @@ pub enum MutationResult {
// TODO maybe the mutator arg is not needed
/// The generic function type that identifies mutations
pub type MutationFunction<I, M, S> = fn(&M, &mut S, &mut I) -> Result<MutationResult, Error>;
pub type MutationFunction<I, S> = fn(&mut S, &mut I) -> Result<MutationResult, Error>;
pub trait ComposedByMutations<I, S>
where
I: Input,
{
/// Get a mutation by index
fn mutation_by_idx(&self, index: usize) -> MutationFunction<I, Self, S>;
fn mutation_by_idx(&self, index: usize) -> MutationFunction<I, S>;
/// Get the number of mutations
fn mutations_count(&self) -> usize;
/// Add a mutation
fn add_mutation(&mut self, mutation: MutationFunction<I, Self, S>);
fn add_mutation(&mut self, mutation: MutationFunction<I, S>);
}
/// Mem move in the own vec
@ -123,15 +124,10 @@ const INTERESTING_32: [i32; 27] = [
];
/// Bitflip mutation for inputs with a bytes vector
pub fn mutation_bitflip<I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_bitflip<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
I: Input + HasBytesVec,
S: HasRand<R>,
S: HasRand<R> + HasMaxSize,
R: Rand,
{
if input.bytes().len() == 0 {
@ -146,12 +142,7 @@ where
}
}
pub fn mutation_byteflip<I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_byteflip<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
I: Input + HasBytesVec,
S: HasRand<R>,
@ -169,12 +160,7 @@ where
}
}
pub fn mutation_byteinc<I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_byteinc<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
I: Input + HasBytesVec,
S: HasRand<R>,
@ -193,12 +179,7 @@ where
}
}
pub fn mutation_bytedec<I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_bytedec<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
I: Input + HasBytesVec,
S: HasRand<R>,
@ -217,12 +198,7 @@ where
}
}
pub fn mutation_byteneg<I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_byteneg<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
I: Input + HasBytesVec,
S: HasRand<R>,
@ -240,12 +216,7 @@ where
}
}
pub fn mutation_byterand<I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_byterand<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
I: Input + HasBytesVec,
S: HasRand<R>,
@ -263,12 +234,7 @@ where
}
}
pub fn mutation_byteadd<I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_byteadd<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
I: Input + HasBytesVec,
S: HasRand<R>,
@ -291,12 +257,7 @@ where
}
}
pub fn mutation_wordadd<I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_wordadd<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
I: Input + HasBytesVec,
S: HasRand<R>,
@ -321,12 +282,7 @@ where
}
}
pub fn mutation_dwordadd<I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_dwordadd<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
I: Input + HasBytesVec,
S: HasRand<R>,
@ -351,12 +307,7 @@ where
}
}
pub fn mutation_qwordadd<I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_qwordadd<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
I: Input + HasBytesVec,
S: HasRand<R>,
@ -381,9 +332,7 @@ where
}
}
pub fn mutation_byteinteresting<I, M, R, S>(
_: &M,
pub fn mutation_byteinteresting<I, R, S>(
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
@ -405,9 +354,7 @@ where
}
}
pub fn mutation_wordinteresting<I, M, R, S>(
_: &M,
pub fn mutation_wordinteresting<I, R, S>(
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
@ -435,9 +382,7 @@ where
}
}
pub fn mutation_dwordinteresting<I, M, R, S>(
_: &M,
pub fn mutation_dwordinteresting<I, R, S>(
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
@ -465,12 +410,7 @@ where
}
}
pub fn mutation_bytesdelete<I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_bytesdelete<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
I: Input + HasBytesVec,
S: HasRand<R>,
@ -488,25 +428,20 @@ where
Ok(MutationResult::Mutated)
}
pub fn mutation_bytesexpand<I, M, R, S>(
mutator: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_bytesexpand<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
M: HasMaxSize,
I: Input + HasBytesVec,
S: HasRand<R>,
S: HasRand<R> + HasMaxSize,
R: Rand,
{
let max_size = state.max_size();
let size = input.bytes().len();
let off = state.rand_mut().below((size + 1) as u64) as usize;
let mut len = 1 + state.rand_mut().below(16) as usize;
if size + len > mutator.max_size() {
if mutator.max_size() > size {
len = mutator.max_size() - size;
if size + len > max_size {
if max_size > size {
len = max_size - size;
} else {
return Ok(MutationResult::Skipped);
}
@ -518,25 +453,23 @@ where
Ok(MutationResult::Mutated)
}
pub fn mutation_bytesinsert<I, M, R, S>(
mutator: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_bytesinsert<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
M: HasMaxSize,
I: Input + HasBytesVec,
S: HasRand<R>,
S: HasRand<R> + HasMaxSize,
R: Rand,
{
let max_size = state.max_size();
let size = input.bytes().len();
if size == 0 {
return Ok(MutationResult::Skipped);
}
let off = state.rand_mut().below((size + 1) as u64) as usize;
let mut len = 1 + state.rand_mut().below(16) as usize;
if size + len > mutator.max_size() {
if mutator.max_size() > size {
len = mutator.max_size() - size;
if size + len > max_size {
if max_size > size {
len = max_size - size;
} else {
return Ok(MutationResult::Skipped);
}
@ -551,25 +484,23 @@ where
Ok(MutationResult::Mutated)
}
pub fn mutation_bytesrandinsert<I, M, R, S>(
mutator: &M,
pub fn mutation_bytesrandinsert<I, R, S>(
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where
M: HasMaxSize,
I: Input + HasBytesVec,
S: HasRand<R>,
S: HasRand<R> + HasMaxSize,
R: Rand,
{
let max_size = state.max_size();
let size = input.bytes().len();
let off = state.rand_mut().below((size + 1) as u64) as usize;
let mut len = 1 + state.rand_mut().below(16) as usize;
if size + len > mutator.max_size() {
if mutator.max_size() > size {
len = mutator.max_size() - size;
if size + len > max_size {
if max_size > size {
len = max_size - size;
} else {
return Ok(MutationResult::Skipped);
}
@ -584,12 +515,7 @@ where
Ok(MutationResult::Mutated)
}
pub fn mutation_bytesset<I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_bytesset<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
I: Input + HasBytesVec,
S: HasRand<R>,
@ -609,12 +535,7 @@ where
Ok(MutationResult::Mutated)
}
pub fn mutation_bytesrandset<I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_bytesrandset<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
I: Input + HasBytesVec,
S: HasRand<R>,
@ -634,12 +555,7 @@ where
Ok(MutationResult::Mutated)
}
pub fn mutation_bytescopy<I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_bytescopy<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
I: Input + HasBytesVec,
S: HasRand<R>,
@ -659,12 +575,7 @@ where
Ok(MutationResult::Mutated)
}
pub fn mutation_bytesswap<I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_bytesswap<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
I: Input + HasBytesVec,
S: HasRand<R>,
@ -687,18 +598,15 @@ where
}
/// Crossover insert mutation
pub fn mutation_crossover_insert<C, I, M, R, S>(
mutator: &M,
pub fn mutation_crossover_insert<C, I, R, S>(
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where
M: HasMaxSize,
C: Corpus<I>,
I: Input + HasBytesVec,
R: Rand,
S: HasRand<R> + HasCorpus<C, I>,
S: HasRand<R> + HasCorpus<C, I> + HasMaxSize,
{
let size = input.bytes().len();
@ -722,6 +630,7 @@ where
return Ok(MutationResult::Skipped);
}
let max_size = state.max_size();
let from = state.rand_mut().below(other_size as u64) as usize;
let to = state.rand_mut().below(size as u64) as usize;
let mut len = state.rand_mut().below((other_size - from) as u64) as usize;
@ -729,9 +638,9 @@ where
let mut other_testcase = state.corpus().get(idx)?.borrow_mut();
let other = other_testcase.load_input()?;
if size + len > mutator.max_size() {
if mutator.max_size() > size {
len = mutator.max_size() - size;
if size + len > max_size {
if max_size > size {
len = max_size - size;
} else {
return Ok(MutationResult::Skipped);
}
@ -745,9 +654,7 @@ where
}
/// Crossover replace mutation
pub fn mutation_crossover_replace<C, I, M, R, S>(
_: &M,
pub fn mutation_crossover_replace<C, I, R, S>(
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
@ -808,12 +715,7 @@ fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) {
}
/// Splicing mutation from AFL
pub fn mutation_splice<C, I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_splice<C, I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
C: Corpus<I>,
I: Input + HasBytesVec,
@ -970,7 +872,6 @@ pub fn read_tokens_file(f: &str, tokens: &mut Vec<Vec<u8>>) -> Result<u32, Error
Ok(entries)
}
/*
#[cfg(test)]
mod tests {
#[cfg(feature = "std")]
@ -1007,17 +908,6 @@ token2="B"
let _ = fs::remove_file("test.tkns");
}
struct WithMaxSize {}
impl HasMaxSize for WithMaxSize {
fn max_size(&self) -> usize {
16000 as usize
}
fn set_max_size(&mut self, _max_size: usize) {
todo!("Not needed");
}
}
#[test]
fn test_mutators() {
let mut inputs = vec![
@ -1030,16 +920,16 @@ token2="B"
BytesInput::new(vec![1; 4]),
];
let mut mutator = WithMaxSize {};
let rand = StdRand::new(1337);
let mut corpus = InMemoryCorpus::new();
let mut rand = StdRand::new(1337);
let mut corpus: InMemoryCorpus<_, StdRand> = InMemoryCorpus::new();
corpus
.add(BytesInput::new(vec![0x42; 0x1337]).into())
.unwrap();
corpus.add(BytesInput::new(vec![0x42; 0x1337]).into());
let mut state = State::new(rand, corpus, (), InMemoryCorpus::new(), ());
let mut state = State::new(corpus, (), InMemoryCorpus::new(), ());
let mut mutations: Vec<MutationFunction<BytesInput, WithMaxSize, StdRand, _>> = vec![];
let mut mutations: Vec<MutationFunction<_, _>> = vec![];
mutations.push(mutation_bitflip);
mutations.push(mutation_byteflip);
@ -1072,7 +962,7 @@ token2="B"
for mutation in &mutations {
for input in inputs.iter() {
let mut mutant = input.clone();
match mutation(&mut mutator, &mut rand, &mut state, &mut mutant).unwrap() {
match mutation(&mut state, &mut mutant).unwrap() {
MutationResult::Mutated => new_testcases.push(mutant),
MutationResult::Skipped => (),
};
@ -1087,4 +977,3 @@ token2="B"
*/
}
}
*/

View File

@ -1,13 +1,15 @@
use crate::inputs::HasBytesVec;
use alloc::vec::Vec;
use core::{default::Default, fmt, marker::PhantomData};
use fmt::Debug;
use core::{
default::Default,
fmt::{self, Debug},
marker::PhantomData,
};
use crate::{
corpus::Corpus,
inputs::Input,
mutators::{HasMaxSize, Mutator, DEFAULT_MAX_SIZE},
state::{HasCorpus, HasMetadata, HasRand},
inputs::{HasBytesVec, Input},
mutators::Mutator,
state::{HasCorpus, HasMaxSize, HasMetadata, HasRand},
utils::Rand,
Error,
};
@ -31,7 +33,7 @@ where
let num = self.iterations(state, input);
for _ in 0..num {
let idx = self.schedule(self.mutations_count(), state, input);
self.mutation_by_idx(idx)(self, state, input)?;
self.mutation_by_idx(idx)(state, input)?;
}
Ok(())
}
@ -43,8 +45,7 @@ where
S: HasRand<R>,
R: Rand,
{
mutations: Vec<MutationFunction<I, Self, S>>,
max_size: usize,
mutations: Vec<MutationFunction<I, S>>,
phantom: PhantomData<R>,
}
@ -57,9 +58,8 @@ where
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"StdScheduledMutator with {} Mutations, max_size: {}, for Input type {}",
"StdScheduledMutator with {} Mutations for Input type {}",
self.mutations.len(),
self.max_size,
core::any::type_name::<I>()
)
}
@ -83,7 +83,7 @@ where
R: Rand,
{
#[inline]
fn mutation_by_idx(&self, index: usize) -> MutationFunction<I, Self, S> {
fn mutation_by_idx(&self, index: usize) -> MutationFunction<I, S> {
self.mutations[index]
}
@ -93,7 +93,7 @@ where
}
#[inline]
fn add_mutation(&mut self, mutation: MutationFunction<I, Self, S>) {
fn add_mutation(&mut self, mutation: MutationFunction<I, S>) {
self.mutations.push(mutation)
}
}
@ -116,23 +116,6 @@ where
}
}
impl<I, R, S> HasMaxSize for StdScheduledMutator<I, R, S>
where
I: Input,
S: HasRand<R>,
R: Rand,
{
#[inline]
fn max_size(&self) -> usize {
self.max_size
}
#[inline]
fn set_max_size(&mut self, max_size: usize) {
self.max_size = max_size;
}
}
impl<I, R, S> StdScheduledMutator<I, R, S>
where
I: Input,
@ -143,16 +126,14 @@ where
pub fn new() -> Self {
Self {
mutations: vec![],
max_size: DEFAULT_MAX_SIZE,
phantom: PhantomData,
}
}
/// Create a new StdScheduledMutator instance specifying mutations
pub fn with_mutations(mutations: Vec<MutationFunction<I, Self, S>>) -> Self {
pub fn with_mutations(mutations: Vec<MutationFunction<I, S>>) -> Self {
StdScheduledMutator {
mutations: mutations,
max_size: DEFAULT_MAX_SIZE,
phantom: PhantomData,
}
}
@ -162,9 +143,9 @@ where
#[derive(Clone, Debug)]
pub struct HavocBytesMutator<C, I, R, S, SM>
where
SM: ScheduledMutator<I, S> + HasMaxSize,
SM: ScheduledMutator<I, S>,
I: Input + HasBytesVec,
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
S: HasRand<R> + HasCorpus<C, I> + HasMetadata + HasMaxSize,
C: Corpus<I>,
R: Rand,
{
@ -174,9 +155,9 @@ where
impl<C, I, R, S, SM> Mutator<I, S> for HavocBytesMutator<C, I, R, S, SM>
where
SM: ScheduledMutator<I, S> + HasMaxSize,
SM: ScheduledMutator<I, S>,
I: Input + HasBytesVec,
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
S: HasRand<R> + HasCorpus<C, I> + HasMetadata + HasMaxSize,
C: Corpus<I>,
R: Rand,
{
@ -208,30 +189,11 @@ where
}
}
impl<C, I, R, S, SM> HasMaxSize for HavocBytesMutator<C, I, R, S, SM>
where
SM: ScheduledMutator<I, S> + HasMaxSize,
I: Input + HasBytesVec,
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
C: Corpus<I>,
R: Rand,
{
#[inline]
fn max_size(&self) -> usize {
self.scheduled.max_size()
}
#[inline]
fn set_max_size(&mut self, max_size: usize) {
self.scheduled.set_max_size(max_size);
}
}
impl<C, I, R, S, SM> HavocBytesMutator<C, I, R, S, SM>
where
SM: ScheduledMutator<I, S> + HasMaxSize,
SM: ScheduledMutator<I, S>,
I: Input + HasBytesVec,
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
S: HasRand<R> + HasCorpus<C, I> + HasMetadata + HasMaxSize,
C: Corpus<I>,
R: Rand,
{
@ -249,7 +211,7 @@ where
impl<C, I, R, S> Default for HavocBytesMutator<C, I, R, S, StdScheduledMutator<I, R, S>>
where
I: Input + HasBytesVec,
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
S: HasRand<R> + HasCorpus<C, I> + HasMetadata + HasMaxSize,
C: Corpus<I>,
R: Rand,
{

View File

@ -4,7 +4,7 @@
use crate::{
inputs::{HasBytesVec, Input},
mutators::*,
state::{HasMetadata, HasRand},
state::{HasMaxSize, HasMetadata, HasRand},
utils::Rand,
Error,
};
@ -30,17 +30,13 @@ impl TokensMetadata {
}
/// Insert a dictionary token
pub fn mutation_tokeninsert<I, M, R, S>(
mutator: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_tokeninsert<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
M: HasMaxSize,
I: Input + HasBytesVec,
S: HasMetadata + HasRand<R>,
S: HasMetadata + HasRand<R> + HasMaxSize,
R: Rand,
{
let max_size = state.max_size();
let tokens_len = {
let meta = state.metadata().get::<TokensMetadata>();
if meta.is_none() {
@ -60,9 +56,9 @@ where
let token = &meta.tokens[token_idx];
let mut len = token.len();
if size + len > mutator.max_size() {
if mutator.max_size() > size {
len = mutator.max_size() - size;
if size + len > max_size {
if max_size > size {
len = max_size - size;
} else {
return Ok(MutationResult::Skipped);
}
@ -76,13 +72,8 @@ where
}
/// Overwrite with a dictionary token
pub fn mutation_tokenreplace<I, M, R, S>(
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
pub fn mutation_tokenreplace<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
M: HasMaxSize,
I: Input + HasBytesVec,
S: HasMetadata + HasRand<R>,
R: Rand,

View File

@ -24,6 +24,9 @@ use crate::{
#[cfg(feature = "std")]
use crate::inputs::bytes::BytesInput;
/// The maximum size of a testcase
pub const DEFAULT_MAX_SIZE: usize = 1048576;
/// Trait for elements offering a corpus
pub trait HasCorpus<C, I>
where
@ -36,6 +39,14 @@ where
fn corpus_mut(&mut self) -> &mut C;
}
/// Interact with the maximum size
pub trait HasMaxSize {
/// The maximum size hint for items and mutations returned
fn max_size(&self) -> usize;
/// Sets the maximum size hint for the items and mutations
fn set_max_size(&mut self, max_size: usize);
}
/// Trait for elements offering a corpus of solutions
pub trait HasSolutions<C, I>
where
@ -204,6 +215,8 @@ where
objectives: OFT,
/// Metadata stored for this state by one of the components
metadata: SerdeAnyMap,
/// MaxSize testcase size for mutators that appreciate it
max_size: usize,
phantom: PhantomData<I>,
}
@ -362,6 +375,24 @@ where
}
}
impl<C, FT, I, OFT, R, SC> HasMaxSize for State<C, FT, I, OFT, R, SC>
where
C: Corpus<I>,
I: Input,
R: Rand,
FT: FeedbacksTuple<I>,
SC: Corpus<I>,
OFT: FeedbacksTuple<I>,
{
fn max_size(&self) -> usize {
self.max_size
}
fn set_max_size(&mut self, max_size: usize) {
self.max_size = max_size
}
}
impl<C, FT, I, OFT, R, SC> HasStartTime for State<C, FT, I, OFT, R, SC>
where
C: Corpus<I>,
@ -638,6 +669,7 @@ where
feedbacks,
solutions,
objectives,
max_size: DEFAULT_MAX_SIZE,
phantom: PhantomData,
}
}