Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eco fuzz fix #1253

Merged
merged 6 commits into from
May 9, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 46 additions & 40 deletions libafl/src/schedulers/ecofuzz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
}
Expand Down Expand Up @@ -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::<EcoMetadata>()?;
(meta.last_mutation_num, meta.last_corpus_count)
let (last_corpus_count, last_mutation_num) = {
let m = state.metadata_mut::<EcoMetadata>()?;
(m.last_corpus_count, m.last_mutation_num)
};

let computed_score = {
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
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::<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 {
regret = 1.1;
}
Expand Down Expand Up @@ -151,18 +148,10 @@ where

/// Create a new alias table when the fuzzer finds a new corpus entry
fn schedule(state: &mut S) -> Result<CorpusId, Error> {
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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok makes more sense, i coded it in one day

let selection = Some(id);
state.metadata_mut::<EcoMetadata>()?.state = EcoState::Exploration;
return Ok(selection.expect("Error in the algorithm, this cannot be None"));
}
Expand Down Expand Up @@ -240,6 +229,8 @@ where
None => 0,
};

assert!(self.last_hash != 0);

// Attach a `SchedulerTestcaseMetadata` to the queue entry.
depth += 1;
{
Expand All @@ -255,12 +246,23 @@ where
.testcase_mut(idx)?
.add_metadata(EcoTestcaseMetadata::default());

let executions = *state.executions();
let meta = state.metadata_mut::<EcoMetadata>()?;
let mut exec_num = 0;
for id in state.corpus().ids() {
let entry = state
.testcase(id)?
.metadata::<SchedulerTestcaseMetadata>()?
.n_fuzz_entry();

if entry == self.last_hash {
exec_num += 1;
}
}

let last_find_iteration = executions - meta.last_executions + 1;
meta.last_find_iteration = last_find_iteration;
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(())
}

Expand Down Expand Up @@ -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::<EcoTestcaseMetadata>()?
.mutation_num;
let count = state.corpus().count();
let executions = *state.executions();

let meta = state.metadata_mut::<EcoMetadata>()?;
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
Expand All @@ -352,28 +349,37 @@ where
fn compute(state: &S, entry: &mut Testcase<S::Input>) -> Result<f64, Error> {
// subtract # initial inputs to the corpus count
let mut energy = 0;
let mut average_cost = (state.corpus().count() / state.executions()) as u64;
if average_cost == 0 {
average_cost = 1024;
}

let (cur_state, rate) = {
let (cur_state, rate, initial_corpus_count) = {
let meta = state.metadata::<EcoMetadata>()?;
(meta.state, meta.rate)
(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 meta = entry.metadata_mut::<EcoTestcaseMetadata>()?;

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 {
Expand Down
Loading