From 52d557aa8f81d11f3363e7b1e53d273a339378d5 Mon Sep 17 00:00:00 2001 From: "Dongjia \"toka\" Zhang" Date: Tue, 9 May 2023 16:45:20 +0200 Subject: [PATCH] Ecofuzz Fix 2 (#1262) * finally works * f --- fuzzers/libfuzzer_libpng/Makefile.toml | 2 +- libafl/src/schedulers/ecofuzz.rs | 63 ++++++++++++++++++++------ libafl/src/stages/power.rs | 8 +++- 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/fuzzers/libfuzzer_libpng/Makefile.toml b/fuzzers/libfuzzer_libpng/Makefile.toml index 50c66b2b63..84486be845 100644 --- a/fuzzers/libfuzzer_libpng/Makefile.toml +++ b/fuzzers/libfuzzer_libpng/Makefile.toml @@ -195,4 +195,4 @@ script=''' rm -f ./${FUZZER_NAME} make -C libpng-1.6.37 clean cargo clean -''' \ No newline at end of file +''' diff --git a/libafl/src/schedulers/ecofuzz.rs b/libafl/src/schedulers/ecofuzz.rs index c537a55ea0..800107367c 100644 --- a/libafl/src/schedulers/ecofuzz.rs +++ b/libafl/src/schedulers/ecofuzz.rs @@ -61,6 +61,7 @@ pub struct EcoMetadata { last_executions: usize, calculate_coe: u64, rate: f64, + regret: f64, } crate::impl_serdeany!(EcoMetadata); @@ -98,28 +99,22 @@ where fn handle_previous(id: CorpusId, state: &mut S) -> Result<(), Error> { let count = state.corpus().count(); - let (last_corpus_count, last_mutation_num) = { + let (last_corpus_count, last_mutation_num, regret) = { let m = state.metadata_mut::()?; - (m.last_corpus_count, m.last_mutation_num) + (m.last_corpus_count, m.last_mutation_num, m.regret) }; - let computed_score = { + { let mut testcase = state.testcase_mut(id)?; let tcmeta = testcase.metadata_mut::()?; + debug_assert!(tcmeta.mutation_num >= last_mutation_num); tcmeta.last_energy = tcmeta.mutation_num - last_mutation_num; tcmeta.found = count - last_corpus_count; // Set was_fuzzed for the old current - tcmeta.computed_score }; - let cur_exec = *state.executions(); let meta = state.metadata_mut::()?; - let mut regret = (cur_exec - meta.last_executions) as f64 / computed_score; - if regret == 0.0 { - regret = 1.1; - } - meta.rate = ((meta.rate * meta.calculate_coe as f64) + regret) / (meta.calculate_coe as f64 + 1.0); @@ -148,6 +143,8 @@ where /// Create a new alias table when the fuzzer finds a new corpus entry fn schedule(state: &mut S) -> Result { + // println!("{:#?}", state.metadata::()); + for id in state.corpus().ids() { let was_fuzzed = state.testcase(id)?.scheduled_count() > 0; if !was_fuzzed { @@ -201,6 +198,7 @@ where } } + // println!("selection_meta {:#?}", selection_meta); Ok(selection) } } @@ -218,6 +216,7 @@ where O: MapObserver, { /// Add an entry to the corpus and return its index + #[allow(clippy::cast_precision_loss)] fn on_add(&mut self, state: &mut S, idx: CorpusId) -> Result<(), Error> { let current_idx = *state.corpus().current(); @@ -229,7 +228,28 @@ where None => 0, }; - assert!(self.last_hash != 0); + // assert!(self.last_hash != 0); + + let cur_exec = *state.executions(); + let last_exec = state.metadata::()?.last_executions; + let last_energy = if let Some(parent_idx) = current_idx { + let e = state + .testcase(parent_idx)? + .metadata::()? + .last_energy; + if e == 0 { + (cur_exec - last_exec) as u64 + } else { + e + } + } else { + (cur_exec - last_exec) as u64 + }; + let mut regret = (cur_exec - last_exec) as f64 / last_energy as f64; + if regret == 0.0 { + regret = 1.1; + } + state.metadata_mut::()?.regret = regret; // Attach a `SchedulerTestcaseMetadata` to the queue entry. depth += 1; @@ -302,6 +322,8 @@ where .testcase_mut(id)? .metadata_mut::()? .exec_by_mutation += 1; + + // println!("{entry} {hash}"); } } @@ -322,13 +344,20 @@ where let count = state.corpus().count(); let executions = *state.executions(); + let last_mutation_num = state + .testcase(id)? + .metadata::()? + .mutation_num; let meta = state.metadata_mut::()?; meta.last_corpus_count = count; + meta.last_mutation_num = last_mutation_num; // TODO in theory it should be assigned at the beginning of the mutational stage // we must not count executions done in other stages meta.last_executions = executions; + // println!("scheduling {id}"); + Ok(id) } } @@ -352,6 +381,7 @@ where let (cur_state, rate, initial_corpus_count) = { let meta = state.metadata::()?; + // println!("{:#?}", meta); (meta.state, meta.rate, meta.initial_corpus_count) }; @@ -368,7 +398,7 @@ where } let meta = entry.metadata_mut::()?; - + // println!("{} {} {:#?}", meta.last_energy, average_cost, cur_state); if cur_state == EcoState::Exploitation { meta.state = EcoState::Exploitation; if meta.found == 0 { @@ -388,10 +418,15 @@ where energy = average_cost; } } - - let score = energy as f64 * rate; + let mut score = energy as f64 * rate; meta.computed_score = score; + // println!("{score}"); + + if score < 1.0 { + score = 1.0; + } + Ok(score) } } diff --git a/libafl/src/stages/power.rs b/libafl/src/stages/power.rs index 64981310e3..b25ef64f96 100644 --- a/libafl/src/stages/power.rs +++ b/libafl/src/stages/power.rs @@ -7,7 +7,9 @@ use crate::{ executors::{Executor, HasObservers}, fuzzer::Evaluator, mutators::Mutator, - schedulers::{testcase_score::CorpusPowerTestcaseScore, TestcaseScore}, + schedulers::{ + ecofuzz::EcoTestcaseScore, testcase_score::CorpusPowerTestcaseScore, TestcaseScore, + }, stages::{mutational::MutatedTransform, MutationalStage, Stage}, state::{HasClientPerfMonitor, HasCorpus, HasMetadata, HasRand, UsesState}, Error, @@ -122,3 +124,7 @@ where /// The standard powerscheduling stage pub type StdPowerMutationalStage = PowerMutationalStage::State>, EM, I, M, Z>; + +/// Ecofuzz scheduling stage +pub type EcoPowerMutationalStage = + PowerMutationalStage::State>, EM, I, M, Z>;