Eco fuzz fix (#1253)

* f

* more fix

* aaaaa

* f

* fix

---------

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
This commit is contained in:
Dongjia "toka" Zhang 2023-05-09 12:56:23 +02:00 committed by GitHub
parent 721c02cd2c
commit fe8c06dd8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

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