diff --git a/libafl/src/schedulers/ecofuzz.rs b/libafl/src/schedulers/ecofuzz.rs index aac6084592..c537a55ea0 100644 --- a/libafl/src/schedulers/ecofuzz.rs +++ b/libafl/src/schedulers/ecofuzz.rs @@ -42,8 +42,7 @@ pub struct EcoTestcaseMetadata { mutation_num: u64, exec_num: u64, exec_by_mutation: u64, - last_found: usize, - line: u64, + found: usize, last_energy: u64, state: EcoState, serial: u64, @@ -60,7 +59,6 @@ pub struct EcoMetadata { last_mutation_num: u64, last_corpus_count: usize, last_executions: usize, - last_find_iteration: usize, calculate_coe: u64, rate: f64, } @@ -100,25 +98,24 @@ where fn handle_previous(id: CorpusId, state: &mut S) -> Result<(), Error> { let count = state.corpus().count(); - let (last_mutation_num, last_corpus_count) = { - let meta = state.metadata::()?; - (meta.last_mutation_num, meta.last_corpus_count) + let (last_corpus_count, last_mutation_num) = { + let m = state.metadata_mut::()?; + (m.last_corpus_count, m.last_mutation_num) }; let computed_score = { let mut testcase = state.testcase_mut(id)?; - let meta = testcase.metadata_mut::()?; - + let tcmeta = testcase.metadata_mut::()?; + tcmeta.last_energy = tcmeta.mutation_num - last_mutation_num; + tcmeta.found = count - last_corpus_count; // Set was_fuzzed for the old current - meta.last_found = count - last_corpus_count; - meta.last_energy = meta.mutation_num - last_mutation_num; - meta.computed_score + tcmeta.computed_score }; - + let cur_exec = *state.executions(); let meta = state.metadata_mut::()?; - let mut regret = meta.last_find_iteration as f64 / computed_score; + let mut regret = (cur_exec - meta.last_executions) as f64 / computed_score; if regret == 0.0 { regret = 1.1; } @@ -151,18 +148,10 @@ where /// Create a new alias table when the fuzzer finds a new corpus entry fn schedule(state: &mut S) -> Result { - let mut selection = None; for id in state.corpus().ids() { let was_fuzzed = state.testcase(id)?.scheduled_count() > 0; - if was_fuzzed { - selection = Some(id); - break; - } - } - - for id in state.corpus().ids() { - let was_fuzzed = state.testcase(id)?.scheduled_count() > 0; - if was_fuzzed { + if !was_fuzzed { + let selection = Some(id); state.metadata_mut::()?.state = EcoState::Exploration; return Ok(selection.expect("Error in the algorithm, this cannot be None")); } @@ -240,6 +229,8 @@ where None => 0, }; + assert!(self.last_hash != 0); + // Attach a `SchedulerTestcaseMetadata` to the queue entry. depth += 1; { @@ -255,12 +246,23 @@ where .testcase_mut(idx)? .add_metadata(EcoTestcaseMetadata::default()); - let executions = *state.executions(); - let meta = state.metadata_mut::()?; + let mut exec_num = 0; + for id in state.corpus().ids() { + let entry = state + .testcase(id)? + .metadata::()? + .n_fuzz_entry(); - let last_find_iteration = executions - meta.last_executions + 1; - meta.last_find_iteration = last_find_iteration; + if entry == self.last_hash { + exec_num += 1; + } + } + let mut tc = state.testcase_mut(idx)?; + let tcmeta = tc.metadata_mut::()?; + + tcmeta.exec_num = exec_num; + tcmeta.serial = state.corpus().count() as u64 + 1; Ok(()) } @@ -318,15 +320,10 @@ where let id = Self::schedule(state)?; self.set_current_scheduled(state, Some(id))?; - let mutation_num = state - .testcase_mut(id)? - .metadata_mut::()? - .mutation_num; let count = state.corpus().count(); let executions = *state.executions(); let meta = state.metadata_mut::()?; - meta.last_mutation_num = mutation_num; meta.last_corpus_count = count; // TODO in theory it should be assigned at the beginning of the mutational stage // we must not count executions done in other stages @@ -352,28 +349,37 @@ where fn compute(state: &S, entry: &mut Testcase) -> Result { // subtract # initial inputs to the corpus count let mut energy = 0; - let mut average_cost = (state.corpus().count() / state.executions()) as u64; + + let (cur_state, rate, initial_corpus_count) = { + let meta = state.metadata::()?; + (meta.state, meta.rate, meta.initial_corpus_count) + }; + + let initial = initial_corpus_count.unwrap_or(0); + + let mut average_cost: u64 = if state.corpus().count() == initial { + *state.executions() as u64 / state.corpus().count() as u64 + } else { + *state.executions() as u64 / (state.corpus().count() - initial) as u64 + }; + if average_cost == 0 { average_cost = 1024; } - let (cur_state, rate) = { - let meta = state.metadata::()?; - (meta.state, meta.rate) - }; - let meta = entry.metadata_mut::()?; if cur_state == EcoState::Exploitation { meta.state = EcoState::Exploitation; - if meta.last_found == 0 { + if meta.found == 0 { energy = core::cmp::min(2 * meta.last_energy, 16 * average_cost); } else { energy = core::cmp::min(meta.last_energy, 16 * average_cost); } } - if energy == 0 { + if cur_state == EcoState::Exploitation && energy == 0 || cur_state != EcoState::Exploitation + { if meta.exec_num > average_cost { energy = average_cost / 4; } else if meta.exec_num > average_cost / 2 {