Make weigthed scheduler independent of powersheduler stage (#599)

* rename & add metadata in scheduler, not stage

* Update testcase_score

* rename

* fix

* update handicap in scheduler

* fmt

* update fuzzers

* doc

* fmt

* fix

* fmt

* more

* fix

* fix

* fix

* fmt
This commit is contained in:
Dongjia Zhang 2022-05-08 23:43:02 +09:00 committed by GitHub
parent 92196cc9be
commit 283ceaac9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 235 additions and 225 deletions

View File

@ -313,11 +313,11 @@ fn fuzz(
5, 5,
)?; )?;
let power = let power = StdPowerMutationalStage::new(mutator, &edges_observer);
StdPowerMutationalStage::new(&mut state, mutator, &edges_observer, PowerSchedule::FAST);
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerScheduler::new(PowerQueueScheduler::new()); let scheduler =
IndexesLenTimeMinimizerScheduler::new(PowerQueueScheduler::new(PowerSchedule::FAST));
// A fuzzer with feedbacks and a corpus scheduler // A fuzzer with feedbacks and a corpus scheduler
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);

View File

@ -284,11 +284,11 @@ fn fuzz(
5, 5,
)?; )?;
let power = let power = StdPowerMutationalStage::new(mutator, &edges_observer);
StdPowerMutationalStage::new(&mut state, mutator, &edges_observer, PowerSchedule::FAST);
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerScheduler::new(PowerQueueScheduler::new()); let scheduler =
IndexesLenTimeMinimizerScheduler::new(PowerQueueScheduler::new(PowerSchedule::FAST));
// A fuzzer with feedbacks and a corpus scheduler // A fuzzer with feedbacks and a corpus scheduler
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);

View File

@ -297,11 +297,11 @@ fn fuzz(
5, 5,
)?; )?;
let power = let power = StdPowerMutationalStage::new(mutator, &edges_observer);
StdPowerMutationalStage::new(&mut state, mutator, &edges_observer, PowerSchedule::FAST);
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerScheduler::new(PowerQueueScheduler::new()); let scheduler =
IndexesLenTimeMinimizerScheduler::new(PowerQueueScheduler::new(PowerSchedule::FAST));
// A fuzzer with feedbacks and a corpus scheduler // A fuzzer with feedbacks and a corpus scheduler
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);

View File

@ -374,11 +374,11 @@ fn fuzz_binary(
5, 5,
)?; )?;
let power = let power = StdPowerMutationalStage::new(mutator, &edges_observer);
StdPowerMutationalStage::new(&mut state, mutator, &edges_observer, PowerSchedule::FAST);
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerScheduler::new(PowerQueueScheduler::new()); let scheduler =
IndexesLenTimeMinimizerScheduler::new(PowerQueueScheduler::new(PowerSchedule::FAST));
// A fuzzer with feedbacks and a corpus scheduler // A fuzzer with feedbacks and a corpus scheduler
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
@ -584,8 +584,7 @@ fn fuzz_text(
5, 5,
)?; )?;
let power = let power = StdPowerMutationalStage::new(mutator, &edges_observer);
StdPowerMutationalStage::new(&mut state, mutator, &edges_observer, PowerSchedule::FAST);
let grimoire_mutator = StdScheduledMutator::with_max_stack_pow( let grimoire_mutator = StdScheduledMutator::with_max_stack_pow(
tuple_list!( tuple_list!(
@ -601,7 +600,8 @@ fn fuzz_text(
let grimoire = StdMutationalStage::new(grimoire_mutator); let grimoire = StdMutationalStage::new(grimoire_mutator);
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerScheduler::new(PowerQueueScheduler::new()); let scheduler =
IndexesLenTimeMinimizerScheduler::new(PowerQueueScheduler::new(PowerSchedule::FAST));
// A fuzzer with feedbacks and a corpus scheduler // A fuzzer with feedbacks and a corpus scheduler
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);

View File

@ -313,8 +313,7 @@ fn fuzz(
5, 5,
)?; )?;
let power = let power = StdMutationalStage::new(mutator);
StdPowerMutationalStage::new(&mut state, mutator, &edges_observer, PowerSchedule::RAND);
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerScheduler::new(StdWeightedScheduler::new()); let scheduler = IndexesLenTimeMinimizerScheduler::new(StdWeightedScheduler::new());

View File

@ -132,8 +132,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations())); let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations()));
let calibration = CalibrationStage::new(&edges_observer); let calibration = CalibrationStage::new(&edges_observer);
let power = let power = StdPowerMutationalStage::new(mutator, &edges_observer);
StdPowerMutationalStage::new(&mut state, mutator, &edges_observer, PowerSchedule::COE);
let mut stages = tuple_list!(calibration, power); let mut stages = tuple_list!(calibration, power);

View File

@ -40,7 +40,7 @@ use libafl::{
}, },
StdMapObserver, TimeObserver, StdMapObserver, TimeObserver,
}, },
schedulers::{IndexesLenTimeMinimizerScheduler, PowerQueueScheduler}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler},
stages::{ stages::{
ConcolicTracingStage, ShadowTracingStage, SimpleConcolicMutationalStage, ConcolicTracingStage, ShadowTracingStage, SimpleConcolicMutationalStage,
StdMutationalStage, TracingStage, StdMutationalStage, TracingStage,
@ -150,7 +150,7 @@ fn fuzz(
println!("We're a client, let's fuzz :)"); println!("We're a client, let's fuzz :)");
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerScheduler::new(PowerQueueScheduler::new()); let scheduler = IndexesLenTimeMinimizerScheduler::new(QueueScheduler::new());
// A fuzzer with feedbacks and a corpus scheduler // A fuzzer with feedbacks and a corpus scheduler
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);

View File

@ -126,13 +126,12 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
let mutator = LainMutator::new(); let mutator = LainMutator::new();
let calibration = CalibrationStage::new(&edges_observer); let calibration = CalibrationStage::new(&edges_observer);
let power = let power = StdPowerMutationalStage::new(mutator, &edges_observer);
StdPowerMutationalStage::new(&mut state, mutator, &edges_observer, PowerSchedule::FAST);
let mut stages = tuple_list!(calibration, power); let mut stages = tuple_list!(calibration, power);
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
let scheduler = PacketLenMinimizerScheduler::new(PowerQueueScheduler::new()); let scheduler = PacketLenMinimizerScheduler::new(PowerQueueScheduler::new(PowerSchedule::FAST));
// A fuzzer with feedbacks and a corpus scheduler // A fuzzer with feedbacks and a corpus scheduler
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);

View File

@ -1,7 +1,7 @@
//! Corpuses contain the testcases, either in memory, on disk, or somewhere else. //! Corpuses contain the testcases, either in memory, on disk, or somewhere else.
pub mod testcase; pub mod testcase;
pub use testcase::{PowerScheduleTestcaseMetaData, Testcase}; pub use testcase::{SchedulerTestcaseMetaData, Testcase};
pub mod inmemory; pub mod inmemory;
pub use inmemory::InMemoryCorpus; pub use inmemory::InMemoryCorpus;

View File

@ -276,7 +276,7 @@ where
/// The Metadata for each testcase used in power schedules. /// The Metadata for each testcase used in power schedules.
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct PowerScheduleTestcaseMetaData { pub struct SchedulerTestcaseMetaData {
/// Number of bits set in bitmap, updated in calibrate_case /// Number of bits set in bitmap, updated in calibrate_case
bitmap_size: u64, bitmap_size: u64,
/// Number of queue cycles behind /// Number of queue cycles behind
@ -287,8 +287,8 @@ pub struct PowerScheduleTestcaseMetaData {
n_fuzz_entry: usize, n_fuzz_entry: usize,
} }
impl PowerScheduleTestcaseMetaData { impl SchedulerTestcaseMetaData {
/// Create new [`struct@PowerScheduleTestcaseMetaData`] /// Create new [`struct@SchedulerTestcaseMetaData`]
#[must_use] #[must_use]
pub fn new(depth: u64) -> Self { pub fn new(depth: u64) -> Self {
Self { Self {
@ -344,4 +344,4 @@ impl PowerScheduleTestcaseMetaData {
} }
} }
crate::impl_serdeany!(PowerScheduleTestcaseMetaData); crate::impl_serdeany!(SchedulerTestcaseMetaData);

View File

@ -6,7 +6,7 @@ use alloc::{
}; };
use crate::{ use crate::{
corpus::{Corpus, PowerScheduleTestcaseMetaData}, corpus::{Corpus, SchedulerTestcaseMetaData},
inputs::Input, inputs::Input,
schedulers::Scheduler, schedulers::Scheduler,
state::{HasCorpus, HasMetadata}, state::{HasCorpus, HasMetadata},
@ -17,13 +17,13 @@ use serde::{Deserialize, Serialize};
/// The n fuzz size /// The n fuzz size
pub const N_FUZZ_SIZE: usize = 1 << 21; pub const N_FUZZ_SIZE: usize = 1 << 21;
crate::impl_serdeany!(PowerScheduleMetadata); crate::impl_serdeany!(SchedulerMetadata);
/// The metadata used for power schedules /// The metadata used for power schedules
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct PowerScheduleMetadata { pub struct SchedulerMetadata {
/// Powerschedule strategy /// Powerschedule strategy
strat: PowerSchedule, strat: Option<PowerSchedule>,
/// Measured exec time during calibration /// Measured exec time during calibration
exec_time: Duration, exec_time: Duration,
/// Calibration cycles /// Calibration cycles
@ -39,10 +39,10 @@ pub struct PowerScheduleMetadata {
} }
/// The metadata for runs in the calibration stage. /// The metadata for runs in the calibration stage.
impl PowerScheduleMetadata { impl SchedulerMetadata {
/// Creates a new [`struct@PowerScheduleMetadata`] /// Creates a new [`struct@SchedulerMetadata`]
#[must_use] #[must_use]
pub fn new(strat: PowerSchedule) -> Self { pub fn new(strat: Option<PowerSchedule>) -> Self {
Self { Self {
strat, strat,
exec_time: Duration::from_millis(0), exec_time: Duration::from_millis(0),
@ -56,7 +56,7 @@ impl PowerScheduleMetadata {
/// The powerschedule strategy /// The powerschedule strategy
#[must_use] #[must_use]
pub fn strat(&self) -> PowerSchedule { pub fn strat(&self) -> Option<PowerSchedule> {
self.strat self.strat
} }
@ -132,7 +132,6 @@ impl PowerScheduleMetadata {
#[allow(missing_docs)] #[allow(missing_docs)]
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq)] #[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq)]
pub enum PowerSchedule { pub enum PowerSchedule {
RAND,
EXPLORE, EXPLORE,
EXPLOIT, EXPLOIT,
FAST, FAST,
@ -143,12 +142,8 @@ pub enum PowerSchedule {
/// A corpus scheduler using power schedules /// A corpus scheduler using power schedules
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct PowerQueueScheduler; pub struct PowerQueueScheduler {
strat: PowerSchedule,
impl Default for PowerQueueScheduler {
fn default() -> Self {
Self::new()
}
} }
impl<I, S> Scheduler<I, S> for PowerQueueScheduler impl<I, S> Scheduler<I, S> for PowerQueueScheduler
@ -158,6 +153,10 @@ where
{ {
/// Add an entry to the corpus and return its index /// Add an entry to the corpus and return its index
fn on_add(&self, state: &mut S, idx: usize) -> Result<(), Error> { fn on_add(&self, state: &mut S, idx: usize) -> Result<(), Error> {
if !state.has_metadata::<SchedulerMetadata>() {
state.add_metadata::<SchedulerMetadata>(SchedulerMetadata::new(Some(self.strat)));
}
let current_idx = *state.corpus().current(); let current_idx = *state.corpus().current();
let mut depth = match current_idx { let mut depth = match current_idx {
@ -166,19 +165,21 @@ where
.get(parent_idx)? .get(parent_idx)?
.borrow_mut() .borrow_mut()
.metadata_mut() .metadata_mut()
.get_mut::<PowerScheduleTestcaseMetaData>() .get_mut::<SchedulerTestcaseMetaData>()
.ok_or_else(|| Error::key_not_found("PowerScheduleTestData not found".to_string()))? .ok_or_else(|| {
Error::key_not_found("SchedulerTestcaseMetaData not found".to_string())
})?
.depth(), .depth(),
None => 0, None => 0,
}; };
// Attach a `PowerScheduleTestData` to the queue entry. // Attach a `SchedulerTestcaseMetaData` to the queue entry.
depth += 1; depth += 1;
state state
.corpus() .corpus()
.get(idx)? .get(idx)?
.borrow_mut() .borrow_mut()
.add_metadata(PowerScheduleTestcaseMetaData::new(depth)); .add_metadata(SchedulerTestcaseMetaData::new(depth));
Ok(()) Ok(())
} }
@ -191,9 +192,9 @@ where
if *cur + 1 >= state.corpus().count() { if *cur + 1 >= state.corpus().count() {
let psmeta = state let psmeta = state
.metadata_mut() .metadata_mut()
.get_mut::<PowerScheduleMetadata>() .get_mut::<SchedulerMetadata>()
.ok_or_else(|| { .ok_or_else(|| {
Error::key_not_found("PowerScheduleMetadata not found".to_string()) Error::key_not_found("SchedulerMetadata not found".to_string())
})?; })?;
psmeta.set_queue_cycles(psmeta.queue_cycles() + 1); psmeta.set_queue_cycles(psmeta.queue_cycles() + 1);
0 0
@ -204,6 +205,22 @@ where
None => 0, None => 0,
}; };
*state.corpus_mut().current_mut() = Some(id); *state.corpus_mut().current_mut() = Some(id);
// Update the handicap
let mut testcase = state.corpus().get(id)?.borrow_mut();
let tcmeta = testcase
.metadata_mut()
.get_mut::<SchedulerTestcaseMetaData>()
.ok_or_else(|| {
Error::key_not_found("SchedulerTestcaseMetaData not found".to_string())
})?;
if tcmeta.handicap() >= 4 {
tcmeta.set_handicap(tcmeta.handicap() - 4);
} else if tcmeta.handicap() > 0 {
tcmeta.set_handicap(tcmeta.handicap() - 1);
}
Ok(id) Ok(id)
} }
} }
@ -212,7 +229,7 @@ where
impl PowerQueueScheduler { impl PowerQueueScheduler {
/// Create a new [`PowerQueueScheduler`] /// Create a new [`PowerQueueScheduler`]
#[must_use] #[must_use]
pub fn new() -> Self { pub fn new(strat: PowerSchedule) -> Self {
Self PowerQueueScheduler { strat }
} }
} }

View File

@ -1,12 +1,12 @@
//! The `TestcaseScore` is an evaluator providing scores of corpus items. //! The `TestcaseScore` is an evaluator providing scores of corpus items.
use crate::{ use crate::{
bolts::{HasLen, HasRefCnt}, bolts::{HasLen, HasRefCnt},
corpus::{Corpus, PowerScheduleTestcaseMetaData, Testcase}, corpus::{Corpus, SchedulerTestcaseMetaData, Testcase},
feedbacks::MapIndexesMetadata, feedbacks::MapIndexesMetadata,
inputs::Input, inputs::Input,
schedulers::{ schedulers::{
minimizer::{IsFavoredMetadata, TopRatedsMetadata}, minimizer::{IsFavoredMetadata, TopRatedsMetadata},
powersched::{PowerSchedule, PowerScheduleMetadata}, powersched::{PowerSchedule, SchedulerMetadata},
}, },
state::{HasCorpus, HasMetadata}, state::{HasCorpus, HasMetadata},
Error, Error,
@ -79,10 +79,11 @@ where
fn compute(entry: &mut Testcase<I>, state: &S) -> Result<f64, Error> { fn compute(entry: &mut Testcase<I>, state: &S) -> Result<f64, Error> {
let psmeta = state let psmeta = state
.metadata() .metadata()
.get::<PowerScheduleMetadata>() .get::<SchedulerMetadata>()
.ok_or_else(|| Error::key_not_found("PowerScheduleMetadata not found".to_string()))?; .ok_or_else(|| Error::key_not_found("SchedulerMetadata not found".to_string()))?;
let fuzz_mu = if psmeta.strat() == PowerSchedule::COE { let fuzz_mu = if let Some(strat) = psmeta.strat() {
if strat == PowerSchedule::COE {
let corpus = state.corpus(); let corpus = state.corpus();
let mut n_paths = 0; let mut n_paths = 0;
let mut v = 0.0; let mut v = 0.0;
@ -91,9 +92,11 @@ where
let n_fuzz_entry = if cur_index == idx { let n_fuzz_entry = if cur_index == idx {
entry entry
.metadata() .metadata()
.get::<PowerScheduleTestcaseMetaData>() .get::<SchedulerTestcaseMetaData>()
.ok_or_else(|| { .ok_or_else(|| {
Error::key_not_found("PowerScheduleTestData not found".to_string()) Error::key_not_found(
"SchedulerTestcaseMetaData not found".to_string(),
)
})? })?
.n_fuzz_entry() .n_fuzz_entry()
} else { } else {
@ -101,9 +104,11 @@ where
.get(idx)? .get(idx)?
.borrow() .borrow()
.metadata() .metadata()
.get::<PowerScheduleTestcaseMetaData>() .get::<SchedulerTestcaseMetaData>()
.ok_or_else(|| { .ok_or_else(|| {
Error::key_not_found("PowerScheduleTestData not found".to_string()) Error::key_not_found(
"SchedulerTestcaseMetaData not found".to_string(),
)
})? })?
.n_fuzz_entry() .n_fuzz_entry()
}; };
@ -119,6 +124,9 @@ where
v v
} else { } else {
0.0 0.0
}
} else {
0.0
}; };
let mut perf_score = 100.0; let mut perf_score = 100.0;
@ -133,9 +141,9 @@ where
let favored = entry.has_metadata::<IsFavoredMetadata>(); let favored = entry.has_metadata::<IsFavoredMetadata>();
let tcmeta = entry let tcmeta = entry
.metadata() .metadata()
.get::<PowerScheduleTestcaseMetaData>() .get::<SchedulerTestcaseMetaData>()
.ok_or_else(|| { .ok_or_else(|| {
Error::key_not_found("PowerScheduleTestcaseMetaData not found".to_string()) Error::key_not_found("SchedulerTestcaseMetaData not found".to_string())
})?; })?;
if q_exec_us * 0.1 > avg_exec_us { if q_exec_us * 0.1 > avg_exec_us {
@ -191,8 +199,9 @@ where
// COE and Fast schedule are fairly different from what are described in the original thesis, // COE and Fast schedule are fairly different from what are described in the original thesis,
// This implementation follows the changes made in this pull request https://github.com/AFLplusplus/AFLplusplus/pull/568 // This implementation follows the changes made in this pull request https://github.com/AFLplusplus/AFLplusplus/pull/568
match psmeta.strat() { if let Some(strat) = psmeta.strat() {
PowerSchedule::EXPLORE | PowerSchedule::RAND => { match strat {
PowerSchedule::EXPLORE => {
// Nothing happens in EXPLORE // Nothing happens in EXPLORE
} }
PowerSchedule::EXPLOIT => { PowerSchedule::EXPLOIT => {
@ -254,19 +263,24 @@ where
/ f64::from(psmeta.n_fuzz()[tcmeta.n_fuzz_entry()] + 1); / f64::from(psmeta.n_fuzz()[tcmeta.n_fuzz_entry()] + 1);
} }
} }
}
if psmeta.strat() != PowerSchedule::EXPLORE { if let Some(strat) = psmeta.strat() {
if strat == PowerSchedule::EXPLORE {
if factor > MAX_FACTOR { if factor > MAX_FACTOR {
factor = MAX_FACTOR; factor = MAX_FACTOR;
} }
perf_score *= factor / POWER_BETA; perf_score *= factor / POWER_BETA;
} }
}
// Lower bound if the strat is not COE. // Lower bound if the strat is not COE.
if psmeta.strat() == PowerSchedule::COE && perf_score < 1.0 { if let Some(strat) = psmeta.strat() {
if strat == PowerSchedule::COE && perf_score < 1.0 {
perf_score = 1.0; perf_score = 1.0;
} }
}
// Upper bound // Upper bound
if perf_score > HAVOC_MAX_MULT * 100.0 { if perf_score > HAVOC_MAX_MULT * 100.0 {
@ -299,16 +313,19 @@ where
let mut weight = 1.0; let mut weight = 1.0;
let psmeta = state let psmeta = state
.metadata() .metadata()
.get::<PowerScheduleMetadata>() .get::<SchedulerMetadata>()
.ok_or_else(|| Error::key_not_found("PowerScheduleMetadata not found".to_string()))?; .ok_or_else(|| Error::key_not_found("SchedulerMetadata not found".to_string()))?;
let tcmeta = entry let tcmeta = entry
.metadata() .metadata()
.get::<PowerScheduleTestcaseMetaData>() .get::<SchedulerTestcaseMetaData>()
.ok_or_else(|| Error::key_not_found("PowerScheduleTestData not found".to_string()))?; .ok_or_else(|| {
Error::key_not_found("SchedulerTestcaseMetaData not found".to_string())
})?;
// This means that this testcase has never gone through the calibration stage before1, // This means that this testcase has never gone through the calibration stage before1,
// In this case we'll just return the default weight // In this case we'll just return the default weight
// This methoud is called in corpus's on_add() method. Fuzz_level is zero at that time.
if entry.fuzz_level() == 0 || psmeta.cycles() == 0 { if entry.fuzz_level() == 0 || psmeta.cycles() == 0 {
return Ok(weight); return Ok(weight);
} }
@ -324,8 +341,12 @@ where
let q_bitmap_size = tcmeta.bitmap_size() as f64; let q_bitmap_size = tcmeta.bitmap_size() as f64;
match psmeta.strat() { if let Some(strat) = psmeta.strat() {
PowerSchedule::FAST | PowerSchedule::COE | PowerSchedule::LIN | PowerSchedule::QUAD => { match strat {
PowerSchedule::FAST
| PowerSchedule::COE
| PowerSchedule::LIN
| PowerSchedule::QUAD => {
let hits = psmeta.n_fuzz()[tcmeta.n_fuzz_entry()]; let hits = psmeta.n_fuzz()[tcmeta.n_fuzz_entry()];
if hits > 0 { if hits > 0 {
weight *= libm::log10(f64::from(hits)) + 1.0; weight *= libm::log10(f64::from(hits)) + 1.0;
@ -334,6 +355,7 @@ where
// EXPLORE and EXPLOIT fall into this // EXPLORE and EXPLOIT fall into this
_ => {} _ => {}
} }
}
weight *= avg_exec_us / q_exec_us; weight *= avg_exec_us / q_exec_us;
weight *= libm::log2(q_bitmap_size) / (avg_bitmap_size as f64); weight *= libm::log2(q_bitmap_size) / (avg_bitmap_size as f64);

View File

@ -1,5 +1,5 @@
//! The queue corpus scheduler with weighted queue item selection from aflpp (`https://github.com/AFLplusplus/AFLplusplus/blob/1d4f1e48797c064ee71441ba555b29fc3f467983/src/afl-fuzz-queue.c#L32`) //! The queue corpus scheduler with weighted queue item selection from aflpp (`https://github.com/AFLplusplus/AFLplusplus/blob/1d4f1e48797c064ee71441ba555b29fc3f467983/src/afl-fuzz-queue.c#L32`)
//! This queue corpus scheduler needs calibration stage and the power schedule stage. //! This queue corpus scheduler needs calibration stage.
use alloc::{ use alloc::{
string::{String, ToString}, string::{String, ToString},
@ -8,10 +8,10 @@ use alloc::{
use crate::{ use crate::{
bolts::rands::Rand, bolts::rands::Rand,
corpus::{Corpus, PowerScheduleTestcaseMetaData}, corpus::{Corpus, SchedulerTestcaseMetaData},
inputs::Input, inputs::Input,
schedulers::{ schedulers::{
powersched::PowerScheduleMetadata, powersched::SchedulerMetadata,
testcase_score::{CorpusWeightTestcaseScore, TestcaseScore}, testcase_score::{CorpusWeightTestcaseScore, TestcaseScore},
Scheduler, Scheduler,
}, },
@ -215,6 +215,10 @@ where
{ {
/// Add an entry to the corpus and return its index /// Add an entry to the corpus and return its index
fn on_add(&self, state: &mut S, idx: usize) -> Result<(), Error> { fn on_add(&self, state: &mut S, idx: usize) -> Result<(), Error> {
if !state.has_metadata::<SchedulerMetadata>() {
state.add_metadata(SchedulerMetadata::new(None));
}
if !state.has_metadata::<WeightedScheduleMetadata>() { if !state.has_metadata::<WeightedScheduleMetadata>() {
state.add_metadata(WeightedScheduleMetadata::new()); state.add_metadata(WeightedScheduleMetadata::new());
} }
@ -227,21 +231,23 @@ where
.get(parent_idx)? .get(parent_idx)?
.borrow_mut() .borrow_mut()
.metadata_mut() .metadata_mut()
.get_mut::<PowerScheduleTestcaseMetaData>() .get_mut::<SchedulerTestcaseMetaData>()
.ok_or_else(|| Error::key_not_found("PowerScheduleTestData not found".to_string()))? .ok_or_else(|| {
Error::key_not_found("SchedulerTestcaseMetaData not found".to_string())
})?
.depth(), .depth(),
None => 0, None => 0,
}; };
// Attach a `PowerScheduleTestData` to the queue entry. // Attach a `SchedulerTestcaseMetaData` to the queue entry.
depth += 1; depth += 1;
state state
.corpus() .corpus()
.get(idx)? .get(idx)?
.borrow_mut() .borrow_mut()
.add_metadata(PowerScheduleTestcaseMetaData::new(depth)); .add_metadata(SchedulerTestcaseMetaData::new(depth));
// Recrate the alias table // Recreate the alias table
self.create_alias_table(state)?; self.create_alias_table(state)?;
Ok(()) Ok(())
} }
@ -281,9 +287,9 @@ where
if current_cycles > corpus_counts { if current_cycles > corpus_counts {
let psmeta = state let psmeta = state
.metadata_mut() .metadata_mut()
.get_mut::<PowerScheduleMetadata>() .get_mut::<SchedulerMetadata>()
.ok_or_else(|| { .ok_or_else(|| {
Error::key_not_found("PowerScheduleMetadata not found".to_string()) Error::key_not_found("SchedulerMetadata not found".to_string())
})?; })?;
psmeta.set_queue_cycles(psmeta.queue_cycles() + 1); psmeta.set_queue_cycles(psmeta.queue_cycles() + 1);
} }

View File

@ -3,14 +3,14 @@
use crate::{ use crate::{
bolts::current_time, bolts::current_time,
bolts::tuples::MatchName, bolts::tuples::MatchName,
corpus::{Corpus, PowerScheduleTestcaseMetaData}, corpus::{Corpus, SchedulerTestcaseMetaData},
events::{EventFirer, LogSeverity}, events::{EventFirer, LogSeverity},
executors::{Executor, ExitKind, HasObservers}, executors::{Executor, ExitKind, HasObservers},
feedbacks::MapFeedbackState, feedbacks::MapFeedbackState,
fuzzer::Evaluator, fuzzer::Evaluator,
inputs::Input, inputs::Input,
observers::{MapObserver, ObserversTuple}, observers::{MapObserver, ObserversTuple},
schedulers::powersched::PowerScheduleMetadata, schedulers::powersched::SchedulerMetadata,
stages::Stage, stages::Stage,
state::{HasClientPerfMonitor, HasCorpus, HasFeedbackStates, HasMetadata}, state::{HasClientPerfMonitor, HasCorpus, HasFeedbackStates, HasMetadata},
Error, Error,
@ -160,13 +160,13 @@ where
} }
}; };
// If power schedule is used, update it // If weighted scheduler or powerscheduler is used, update it
let use_powerschedule = state.has_metadata::<PowerScheduleMetadata>() let use_powerschedule = state.has_metadata::<SchedulerMetadata>()
&& state && state
.corpus() .corpus()
.get(corpus_idx)? .get(corpus_idx)?
.borrow() .borrow()
.has_metadata::<PowerScheduleTestcaseMetaData>(); .has_metadata::<SchedulerTestcaseMetaData>();
if use_powerschedule { if use_powerschedule {
let map = executor let map = executor
@ -176,10 +176,7 @@ where
let bitmap_size = map.count_bytes(); let bitmap_size = map.count_bytes();
let psmeta = state let psmeta = state.metadata_mut().get_mut::<SchedulerMetadata>().unwrap();
.metadata_mut()
.get_mut::<PowerScheduleMetadata>()
.unwrap();
let handicap = psmeta.queue_cycles(); let handicap = psmeta.queue_cycles();
psmeta.set_exec_time(psmeta.exec_time() + total_time); psmeta.set_exec_time(psmeta.exec_time() + total_time);
@ -196,9 +193,9 @@ where
let data = testcase let data = testcase
.metadata_mut() .metadata_mut()
.get_mut::<PowerScheduleTestcaseMetaData>() .get_mut::<SchedulerTestcaseMetaData>()
.ok_or_else(|| { .ok_or_else(|| {
Error::key_not_found("PowerScheduleTestData not found".to_string()) Error::key_not_found("SchedulerTestcaseMetaData not found".to_string())
})?; })?;
data.set_bitmap_size(bitmap_size); data.set_bitmap_size(bitmap_size);

View File

@ -4,17 +4,14 @@ use alloc::string::{String, ToString};
use core::{fmt::Debug, marker::PhantomData}; use core::{fmt::Debug, marker::PhantomData};
use crate::{ use crate::{
bolts::rands::Rand, corpus::{Corpus, SchedulerTestcaseMetaData},
corpus::{Corpus, PowerScheduleTestcaseMetaData},
executors::{Executor, HasObservers}, executors::{Executor, HasObservers},
fuzzer::Evaluator, fuzzer::Evaluator,
inputs::Input, inputs::Input,
mutators::Mutator, mutators::Mutator,
observers::{MapObserver, ObserversTuple}, observers::{MapObserver, ObserversTuple},
schedulers::{ schedulers::{
powersched::{PowerSchedule, PowerScheduleMetadata}, powersched::SchedulerMetadata, testcase_score::CorpusPowerTestcaseScore, TestcaseScore,
testcase_score::CorpusPowerTestcaseScore,
TestcaseScore,
}, },
stages::{MutationalStage, Stage}, stages::{MutationalStage, Stage},
state::{HasClientPerfMonitor, HasCorpus, HasMetadata, HasRand}, state::{HasClientPerfMonitor, HasCorpus, HasMetadata, HasRand},
@ -67,29 +64,8 @@ where
#[allow(clippy::cast_sign_loss)] #[allow(clippy::cast_sign_loss)]
fn iterations(&self, state: &mut S, corpus_idx: usize) -> Result<usize, Error> { fn iterations(&self, state: &mut S, corpus_idx: usize) -> Result<usize, Error> {
// Update handicap // Update handicap
let use_random = state
.metadata_mut()
.get_mut::<PowerScheduleMetadata>()
.ok_or_else(|| Error::key_not_found("PowerScheduleMetadata not found".to_string()))?
.strat()
== PowerSchedule::RAND;
if use_random {
return Ok(1 + state.rand_mut().below(128) as usize);
}
let mut testcase = state.corpus().get(corpus_idx)?.borrow_mut(); let mut testcase = state.corpus().get(corpus_idx)?.borrow_mut();
let score = F::compute(&mut *testcase, state)? as usize; let score = F::compute(&mut *testcase, state)? as usize;
let tcmeta = testcase
.metadata_mut()
.get_mut::<PowerScheduleTestcaseMetaData>()
.ok_or_else(|| {
Error::key_not_found("PowerScheduleTestcaseMetaData not found".to_string())
})?;
if tcmeta.handicap() >= 4 {
tcmeta.set_handicap(tcmeta.handicap() - 4);
} else if tcmeta.handicap() > 0 {
tcmeta.set_handicap(tcmeta.handicap() - 1);
}
Ok(score) Ok(score)
} }
@ -126,10 +102,8 @@ where
let psmeta = state let psmeta = state
.metadata_mut() .metadata_mut()
.get_mut::<PowerScheduleMetadata>() .get_mut::<SchedulerMetadata>()
.ok_or_else(|| { .ok_or_else(|| Error::key_not_found("SchedulerMetadata not found".to_string()))?;
Error::key_not_found("PowerScheduleMetadata not found".to_string())
})?;
hash %= psmeta.n_fuzz().len(); hash %= psmeta.n_fuzz().len();
// Update the path frequency // Update the path frequency
@ -141,9 +115,9 @@ where
.get(idx)? .get(idx)?
.borrow_mut() .borrow_mut()
.metadata_mut() .metadata_mut()
.get_mut::<PowerScheduleTestcaseMetaData>() .get_mut::<SchedulerTestcaseMetaData>()
.ok_or_else(|| { .ok_or_else(|| {
Error::key_not_found("PowerScheduleTestData not found".to_string()) Error::key_not_found("SchedulerTestcaseMetaData not found".to_string())
})? })?
.set_n_fuzz_entry(hash); .set_n_fuzz_entry(hash);
} }
@ -194,10 +168,7 @@ where
Z: Evaluator<E, EM, I, S>, Z: Evaluator<E, EM, I, S>,
{ {
/// Creates a new [`PowerMutationalStage`] /// Creates a new [`PowerMutationalStage`]
pub fn new(state: &mut S, mutator: M, map_observer_name: &O, strat: PowerSchedule) -> Self { pub fn new(mutator: M, map_observer_name: &O) -> Self {
if !state.has_metadata::<PowerScheduleMetadata>() {
state.add_metadata::<PowerScheduleMetadata>(PowerScheduleMetadata::new(strat));
}
Self { Self {
map_observer_name: map_observer_name.name().to_string(), map_observer_name: map_observer_name.name().to_string(),
mutator, mutator,