diff --git a/.gitignore b/.gitignore index 7e1a3ce3ad..29ff1c7418 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ Cargo.lock *.dll *.exe +callgrind.out.* perf.data perf.data.old diff --git a/afl/Cargo.toml b/afl/Cargo.toml index 81e5d8741c..a82accaa86 100644 --- a/afl/Cargo.toml +++ b/afl/Cargo.toml @@ -21,8 +21,6 @@ harness = false name = "hash_speeds" harness = false - - [features] default = ["std"] std = [] @@ -34,4 +32,8 @@ num = "*" xxhash-rust = { version = "0.8.0", features = ["xxh3"] } # xxh3 hashing for rust serde = { version = "1.0", default-features = false, features = ["alloc"] } # serialization lib erased-serde = "0.3.12" -postcard = { version = "0.5.1", features = ["alloc"] } # no_std compatible serde serialization fromat \ No newline at end of file +postcard = { version = "0.5.1", features = ["alloc"] } # no_std compatible serde serialization fromat + +[profile.release] +lto = true +opt-level = 3 diff --git a/afl/src/mutators/scheduled.rs b/afl/src/mutators/scheduled.rs index b59ea17652..3b0200db36 100644 --- a/afl/src/mutators/scheduled.rs +++ b/afl/src/mutators/scheduled.rs @@ -20,20 +20,15 @@ where } /// Get the next mutation to apply + #[inline] fn schedule( &mut self, + mutations_count: usize, rand: &mut R, _input: &I, - ) -> Result, AflError> { - let count = self.mutations_count() as u64; - if count == 0 { - return Err(AflError::Empty("no mutations".into())); - } - let idx; - { - idx = rand.below(count) as usize; - } - Ok(self.mutation_by_idx(idx)) + ) -> usize { + debug_assert!(mutations_count > 0); + rand.below(mutations_count as u64) as usize } /// New default implementation for mutate @@ -47,7 +42,8 @@ where ) -> Result<(), AflError> { let num = self.iterations(rand, input); for _ in 0..num { - self.schedule(rand, input)?(self, rand, corpus, input)?; + let idx = self.schedule(self.mutations_count(), rand, input); + self.mutation_by_idx(idx)(self, rand, corpus, input)?; } Ok(()) } @@ -86,14 +82,17 @@ where I: Input, R: Rand, { + #[inline] fn mutation_by_idx(&self, index: usize) -> MutationFunction { self.mutations[index] } + #[inline] fn mutations_count(&self) -> usize { self.mutations.len() } + #[inline] fn add_mutation(&mut self, mutation: MutationFunction) { self.mutations.push(mutation) } @@ -151,7 +150,7 @@ where /// Schedule some selected byte level mutations given a ScheduledMutator type pub struct HavocBytesMutator where - SM: ScheduledMutator, + SM: ScheduledMutator + HasMaxSize, C: Corpus, I: Input + HasBytesVec, R: Rand, @@ -162,7 +161,7 @@ where impl Mutator for HavocBytesMutator where - SM: ScheduledMutator, + SM: ScheduledMutator + HasMaxSize, C: Corpus, I: Input + HasBytesVec, R: Rand, @@ -173,15 +172,55 @@ where rand: &mut R, corpus: &C, input: &mut I, - stage_idx: i32, + _stage_idx: i32, ) -> Result<(), AflError> { - self.scheduled.mutate(rand, corpus, input, stage_idx) + //self.scheduled.mutate(rand, corpus, input, stage_idx); + let num = self.scheduled.iterations(rand, input); + for _ in 0..num { + let idx = self.scheduled.schedule(13, rand, input); + match idx { + 0=> mutation_bitflip(self, rand, corpus, input)?, + 1=> mutation_byteflip(self, rand, corpus, input)?, + 2=> mutation_byteinc(self, rand, corpus, input)?, + 3=> mutation_bytedec(self, rand, corpus, input)?, + 4=> mutation_byteneg(self, rand, corpus, input)?, + 5=> mutation_byterand(self, rand, corpus, input)?, + + 6=> mutation_byteadd(self, rand, corpus, input)?, + 7=> mutation_wordadd(self, rand, corpus, input)?, + 8=> mutation_dwordadd(self, rand, corpus, input)?, + 9=> mutation_byteinteresting(self, rand, corpus, input)?, + 10=> mutation_wordinteresting(self, rand, corpus, input)?, + 11=> mutation_dwordinteresting(self, rand, corpus, input)?, + + _=> mutation_splice(self, rand, corpus, input)?, + }; + } + Ok(()) + } +} + +impl HasMaxSize for HavocBytesMutator +where + SM: ScheduledMutator + HasMaxSize, + C: Corpus, + I: Input + HasBytesVec, + 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 HavocBytesMutator where - SM: ScheduledMutator, + SM: ScheduledMutator + HasMaxSize, C: Corpus, I: Input + HasBytesVec, R: Rand, @@ -239,6 +278,7 @@ where scheduled.add_mutation(mutation_bitflip);*/ scheduled.add_mutation(mutation_splice); + HavocBytesMutator { scheduled: scheduled, phantom: PhantomData, diff --git a/afl/src/serde_anymap.rs b/afl/src/serde_anymap.rs index 521dac36bf..1864e44efa 100644 --- a/afl/src/serde_anymap.rs +++ b/afl/src/serde_anymap.rs @@ -156,6 +156,7 @@ macro_rules! create_serde_registry_for_trait { } impl SerdeAnyMap { + #[inline] pub fn get(&self) -> Option<&T> where T: $trait_name, @@ -165,6 +166,7 @@ macro_rules! create_serde_registry_for_trait { .map(|x| x.as_ref().as_any().downcast_ref::().unwrap()) } + #[inline] pub fn get_mut(&mut self) -> Option<&mut T> where T: $trait_name, @@ -174,6 +176,7 @@ macro_rules! create_serde_registry_for_trait { .map(|x| x.as_mut().as_any_mut().downcast_mut::().unwrap()) } + #[inline] pub fn insert(&mut self, t: T) where T: $trait_name, @@ -182,10 +185,12 @@ macro_rules! create_serde_registry_for_trait { .insert(unpack_type_id(TypeId::of::()), Box::new(t)); } + #[inline] pub fn len(&self) -> usize { self.map.len() } + #[inline] pub fn contains(&self) -> bool where T: $trait_name, @@ -212,6 +217,7 @@ macro_rules! create_serde_registry_for_trait { } impl NamedSerdeAnyMap { + #[inline] pub fn get(&self, name: &String) -> Option<&T> where T: Any, @@ -224,6 +230,7 @@ macro_rules! create_serde_registry_for_trait { } } + #[inline] pub fn by_typeid( &self, name: &String, @@ -237,6 +244,7 @@ macro_rules! create_serde_registry_for_trait { } } + #[inline] pub fn get_mut(&mut self, name: &String) -> Option<&mut T> where T: Any, @@ -249,6 +257,7 @@ macro_rules! create_serde_registry_for_trait { } } + #[inline] pub fn by_typeid_mut( &mut self, name: &String, @@ -262,6 +271,7 @@ macro_rules! create_serde_registry_for_trait { } } + #[inline] pub fn get_all( &self, ) -> Option< @@ -281,6 +291,7 @@ macro_rules! create_serde_registry_for_trait { } } + #[inline] pub fn all_by_typeid( &self, typeid: &TypeId, @@ -296,6 +307,7 @@ macro_rules! create_serde_registry_for_trait { } } + #[inline] pub fn get_all_mut( &mut self, ) -> Option< @@ -316,6 +328,7 @@ macro_rules! create_serde_registry_for_trait { } } + #[inline] pub fn all_by_typeid_mut( &mut self, typeid: &TypeId, @@ -331,6 +344,7 @@ macro_rules! create_serde_registry_for_trait { } } + #[inline] pub fn all_typeids( &self, ) -> core::iter::Map< @@ -340,6 +354,7 @@ macro_rules! create_serde_registry_for_trait { self.map.keys().map(|x| pack_type_id(*x)) } + #[inline] pub fn for_each( &self, func: fn(&TypeId, &Box) -> Result<(), AflError>, @@ -352,6 +367,7 @@ macro_rules! create_serde_registry_for_trait { Ok(()) } + #[inline] pub fn for_each_mut( &mut self, func: fn(&TypeId, &mut Box) -> Result<(), AflError>, @@ -364,6 +380,7 @@ macro_rules! create_serde_registry_for_trait { Ok(()) } + #[inline] pub fn insert(&mut self, val: Box, name: &String) { let id = unpack_type_id((*val).type_id()); if !self.map.contains_key(&id) { @@ -375,10 +392,12 @@ macro_rules! create_serde_registry_for_trait { .insert(xxhash_rust::xxh3::xxh3_64(name.as_bytes()), val); } + #[inline] pub fn len(&self) -> usize { self.map.len() } + #[inline] pub fn contains_type(&self) -> bool where T: Any, @@ -386,6 +405,7 @@ macro_rules! create_serde_registry_for_trait { self.map.contains_key(&unpack_type_id(TypeId::of::())) } + #[inline] pub fn contains(&self, name: &String) -> bool where T: Any, diff --git a/fuzzers/libfuzzer/Cargo.toml b/fuzzers/libfuzzer/Cargo.toml index 25079d3ca2..1cd11fcbaa 100644 --- a/fuzzers/libfuzzer/Cargo.toml +++ b/fuzzers/libfuzzer/Cargo.toml @@ -15,3 +15,8 @@ afl = { path = "../../afl/" } [lib] crate-type = ["staticlib", "cdylib"] + +[profile.release] +lto = true +opt-level = 3 + diff --git a/fuzzers/libfuzzer/src/lib.rs b/fuzzers/libfuzzer/src/lib.rs index 662311784b..b1a1e8adc9 100644 --- a/fuzzers/libfuzzer/src/lib.rs +++ b/fuzzers/libfuzzer/src/lib.rs @@ -18,6 +18,7 @@ use afl::executors::{Executor, ExitKind}; use afl::feedbacks::MaxMapFeedback; use afl::generators::RandPrintablesGenerator; use afl::mutators::scheduled::HavocBytesMutator; +use afl::mutators::HasMaxSize; use afl::observers::StdMapObserver; use afl::stages::mutational::StdMutationalStage; use afl::utils::StdRand; @@ -66,7 +67,8 @@ pub extern "C" fn afl_libfuzzer_main() { state.add_feedback(Box::new(edges_feedback)); let mut engine = Engine::new(executor); - let mutator = HavocBytesMutator::new_default(); + let mut mutator = HavocBytesMutator::new_default(); + mutator.set_max_size(4096); let stage = StdMutationalStage::new(mutator); diff --git a/fuzzers/libfuzzer/test.sh b/fuzzers/libfuzzer/test.sh index 9e4fa62dce..f88f80aefa 100755 --- a/fuzzers/libfuzzer/test.sh +++ b/fuzzers/libfuzzer/test.sh @@ -3,8 +3,9 @@ cargo build --release make -C runtime -./compiler test/test.c -o test_fuzz.elf +./compiler -flto=thin -c test/test.c -o test_fuzz.o +./compiler -flto=thin -fuse-ld=lld test_fuzz.o -o test_fuzz.elf RUST_BACKTRACE=1 ./test_fuzz.elf -rm ./test_fuzz.elf +#rm ./test_fuzz.elf