Fix fuzz_level related thing, separate on_replace/on_remove from Scheduler & various fixes (#1119)
* delete HasFuzzedCorpusId * more * fmt clp * aa * fixing * delete * a * append parent id when Objective * add HasCorpus inprocss executor * ecofuzz, delete was_fuzzed, update fuzz_level * fix * RemovableScheduler for Tunable, Queue, Weighted * clp * no std * import * on_execution * fix * win * fmt * fix * revert to on_evaluation and propogate in the accounting scheduler * fix --------- Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
This commit is contained in:
parent
2ed6583041
commit
4d778dd64d
@ -19,7 +19,7 @@ use crate::{
|
||||
corpus::Corpus,
|
||||
executors::{Executor, HasObservers},
|
||||
observers::{MapObserver, ObserversTuple},
|
||||
schedulers::{LenTimeMulTestcaseScore, Scheduler, TestcaseScore},
|
||||
schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore},
|
||||
state::{HasCorpus, HasMetadata, UsesState},
|
||||
Error, HasScheduler,
|
||||
};
|
||||
@ -41,7 +41,7 @@ where
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
CS: Scheduler<State = E::State>,
|
||||
CS: Scheduler<State = E::State> + RemovableScheduler, // schedulers that has on_remove/on_replace only!
|
||||
EM: UsesState<State = E::State>,
|
||||
Z: HasScheduler<Scheduler = CS, State = E::State>;
|
||||
}
|
||||
@ -100,7 +100,7 @@ where
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
CS: Scheduler<State = E::State>,
|
||||
CS: Scheduler<State = E::State> + RemovableScheduler,
|
||||
EM: UsesState<State = E::State>,
|
||||
Z: HasScheduler<Scheduler = CS, State = E::State>,
|
||||
{
|
||||
|
@ -34,9 +34,7 @@ where
|
||||
/// Number of executions done at discovery time
|
||||
executions: usize,
|
||||
/// Number of fuzzing iterations of this particular input updated in perform_mutational
|
||||
fuzz_level: usize,
|
||||
/// If it has been fuzzed
|
||||
fuzzed: bool,
|
||||
scheduled_count: usize,
|
||||
/// Parent [`CorpusId`], if known
|
||||
parent_id: Option<CorpusId>,
|
||||
}
|
||||
@ -160,28 +158,16 @@ where
|
||||
&mut self.executions
|
||||
}
|
||||
|
||||
/// Get the `fuzz_level`
|
||||
/// Get the `scheduled_count`
|
||||
#[inline]
|
||||
pub fn fuzz_level(&self) -> usize {
|
||||
self.fuzz_level
|
||||
pub fn scheduled_count(&self) -> usize {
|
||||
self.scheduled_count
|
||||
}
|
||||
|
||||
/// Set the `fuzz_level`
|
||||
/// Set the `scheduled_count`
|
||||
#[inline]
|
||||
pub fn set_fuzz_level(&mut self, fuzz_level: usize) {
|
||||
self.fuzz_level = fuzz_level;
|
||||
}
|
||||
|
||||
/// Get if it was fuzzed
|
||||
#[inline]
|
||||
pub fn fuzzed(&self) -> bool {
|
||||
self.fuzzed
|
||||
}
|
||||
|
||||
/// Set if it was fuzzed
|
||||
#[inline]
|
||||
pub fn set_fuzzed(&mut self, fuzzed: bool) {
|
||||
self.fuzzed = fuzzed;
|
||||
pub fn set_scheduled_count(&mut self, scheduled_count: usize) {
|
||||
self.scheduled_count = scheduled_count;
|
||||
}
|
||||
|
||||
/// Create a new Testcase instance given an input
|
||||
@ -257,9 +243,8 @@ where
|
||||
metadata: SerdeAnyMap::new(),
|
||||
exec_time: None,
|
||||
cached_len: None,
|
||||
fuzz_level: 0,
|
||||
scheduled_count: 0,
|
||||
executions: 0,
|
||||
fuzzed: false,
|
||||
parent_id: None,
|
||||
}
|
||||
}
|
||||
@ -486,13 +471,8 @@ pub mod pybind {
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn fuzz_level(&self) -> usize {
|
||||
self.inner.as_ref().fuzz_level()
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn fuzzed(&self) -> bool {
|
||||
self.inner.as_ref().fuzzed()
|
||||
fn scheduled_count(&self) -> usize {
|
||||
self.inner.as_ref().scheduled_count()
|
||||
}
|
||||
|
||||
fn metadata(&mut self) -> PyObject {
|
||||
|
@ -50,7 +50,7 @@ use crate::{
|
||||
fuzzer::HasObjective,
|
||||
inputs::UsesInput,
|
||||
observers::{ObserversTuple, UsesObservers},
|
||||
state::{HasClientPerfMonitor, HasFuzzedCorpusId, HasSolutions, UsesState},
|
||||
state::{HasClientPerfMonitor, HasCorpus, HasSolutions, UsesState},
|
||||
Error,
|
||||
};
|
||||
|
||||
@ -167,7 +167,7 @@ where
|
||||
H: FnMut(&<S as UsesInput>::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
OT: ObserversTuple<S>,
|
||||
S: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId,
|
||||
S: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
||||
{
|
||||
/// Create a new in mem executor.
|
||||
/// Caution: crash and restart in one of them will lead to odd behavior if multiple are used,
|
||||
@ -344,7 +344,7 @@ impl InProcessHandlers {
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
||||
Z: HasObjective<Objective = OF, State = E::State>,
|
||||
{
|
||||
#[cfg(unix)]
|
||||
@ -545,7 +545,7 @@ pub fn run_observers_and_save_state<E, EM, OF, Z>(
|
||||
E: HasObservers,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
||||
Z: HasObjective<Objective = OF, State = E::State>,
|
||||
{
|
||||
let observers = executor.observers_mut();
|
||||
@ -561,8 +561,8 @@ pub fn run_observers_and_save_state<E, EM, OF, Z>(
|
||||
|
||||
if interesting {
|
||||
let mut new_testcase = Testcase::new(input.clone());
|
||||
new_testcase.set_parent_id_optional(state.fuzzed_corpus_id());
|
||||
new_testcase.add_metadata(exitkind);
|
||||
new_testcase.set_parent_id_optional(*state.corpus().current());
|
||||
fuzzer
|
||||
.objective_mut()
|
||||
.append_metadata(state, observers, &mut new_testcase)
|
||||
@ -582,8 +582,6 @@ pub fn run_observers_and_save_state<E, EM, OF, Z>(
|
||||
}
|
||||
|
||||
// We will start mutators from scratch after restart.
|
||||
state.clear_fuzzed_corpus_id();
|
||||
|
||||
event_mgr.on_restart(state).unwrap();
|
||||
|
||||
log::info!("Waiting for broker...");
|
||||
@ -614,7 +612,7 @@ mod unix_signal_handler {
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::UsesInput,
|
||||
state::{HasClientPerfMonitor, HasFuzzedCorpusId, HasSolutions},
|
||||
state::{HasClientPerfMonitor, HasCorpus, HasSolutions},
|
||||
};
|
||||
|
||||
pub(crate) type HandlerFuncPtr =
|
||||
@ -673,7 +671,7 @@ mod unix_signal_handler {
|
||||
E: HasObservers,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
||||
Z: HasObjective<Objective = OF, State = E::State>,
|
||||
{
|
||||
let old_hook = panic::take_hook();
|
||||
@ -714,7 +712,7 @@ mod unix_signal_handler {
|
||||
E: HasObservers,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
||||
Z: HasObjective<Objective = OF, State = E::State>,
|
||||
{
|
||||
if !data.is_valid() {
|
||||
@ -757,7 +755,7 @@ mod unix_signal_handler {
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
||||
Z: HasObjective<Objective = OF, State = E::State>,
|
||||
{
|
||||
#[cfg(all(target_os = "android", target_arch = "aarch64"))]
|
||||
@ -865,7 +863,7 @@ pub mod windows_asan_handler {
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::UsesInput,
|
||||
state::{HasClientPerfMonitor, HasFuzzedCorpusId, HasSolutions},
|
||||
state::{HasClientPerfMonitor, HasCorpus, HasSolutions},
|
||||
};
|
||||
|
||||
/// # Safety
|
||||
@ -875,7 +873,7 @@ pub mod windows_asan_handler {
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
||||
Z: HasObjective<Objective = OF, State = E::State>,
|
||||
{
|
||||
let mut data = &mut GLOBAL_STATE;
|
||||
@ -974,7 +972,7 @@ mod windows_exception_handler {
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::UsesInput,
|
||||
state::{HasClientPerfMonitor, HasFuzzedCorpusId, HasSolutions},
|
||||
state::{HasClientPerfMonitor, HasCorpus, HasSolutions},
|
||||
};
|
||||
|
||||
pub(crate) type HandlerFuncPtr =
|
||||
@ -1013,7 +1011,7 @@ mod windows_exception_handler {
|
||||
E: HasObservers,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
||||
Z: HasObjective<Objective = OF, State = E::State>,
|
||||
{
|
||||
let old_hook = panic::take_hook();
|
||||
@ -1072,7 +1070,7 @@ mod windows_exception_handler {
|
||||
E: HasObservers,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
||||
Z: HasObjective<Objective = OF, State = E::State>,
|
||||
{
|
||||
let data: &mut InProcessExecutorHandlerData =
|
||||
@ -1133,7 +1131,7 @@ mod windows_exception_handler {
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
||||
Z: HasObjective<Objective = OF, State = E::State>,
|
||||
{
|
||||
// Have we set a timer_before?
|
||||
|
@ -14,9 +14,8 @@ use crate::{
|
||||
executors::ExitKind,
|
||||
feedbacks::Feedback,
|
||||
generators::NautilusContext,
|
||||
inputs::NautilusInput,
|
||||
inputs::{NautilusInput, UsesInput},
|
||||
observers::ObserversTuple,
|
||||
prelude::UsesInput,
|
||||
state::{HasClientPerfMonitor, HasMetadata},
|
||||
Error,
|
||||
};
|
||||
|
@ -23,10 +23,7 @@ use crate::{
|
||||
schedulers::Scheduler,
|
||||
stages::StagesTuple,
|
||||
start_timer,
|
||||
state::{
|
||||
HasClientPerfMonitor, HasCorpus, HasExecutions, HasFuzzedCorpusId, HasMetadata,
|
||||
HasSolutions, UsesState,
|
||||
},
|
||||
state::{HasClientPerfMonitor, HasCorpus, HasExecutions, HasMetadata, HasSolutions, UsesState},
|
||||
Error,
|
||||
};
|
||||
|
||||
@ -330,7 +327,7 @@ where
|
||||
F: Feedback<CS::State>,
|
||||
OF: Feedback<CS::State>,
|
||||
OT: ObserversTuple<CS::State> + Serialize + DeserializeOwned,
|
||||
CS::State: HasCorpus + HasSolutions + HasClientPerfMonitor + HasExecutions + HasFuzzedCorpusId,
|
||||
CS::State: HasCorpus + HasSolutions + HasClientPerfMonitor + HasExecutions,
|
||||
{
|
||||
/// Evaluate if a set of observation channels has an interesting state
|
||||
fn process_execution<EM>(
|
||||
@ -387,7 +384,6 @@ where
|
||||
|
||||
// Add the input to the main corpus
|
||||
let mut testcase = Testcase::with_executions(input.clone(), *state.executions());
|
||||
testcase.set_parent_id_optional(state.fuzzed_corpus_id());
|
||||
self.feedback_mut()
|
||||
.append_metadata(state, observers, &mut testcase)?;
|
||||
let idx = state.corpus_mut().add(testcase)?;
|
||||
@ -421,7 +417,7 @@ where
|
||||
|
||||
// The input is a solution, add it to the respective corpus
|
||||
let mut testcase = Testcase::with_executions(input, *state.executions());
|
||||
testcase.set_parent_id_optional(state.fuzzed_corpus_id());
|
||||
testcase.set_parent_id_optional(*state.corpus().current());
|
||||
self.objective_mut()
|
||||
.append_metadata(state, observers, &mut testcase)?;
|
||||
state.solutions_mut().add(testcase)?;
|
||||
@ -447,7 +443,7 @@ where
|
||||
OT: ObserversTuple<CS::State> + Serialize + DeserializeOwned,
|
||||
F: Feedback<CS::State>,
|
||||
OF: Feedback<CS::State>,
|
||||
CS::State: HasCorpus + HasSolutions + HasClientPerfMonitor + HasExecutions + HasFuzzedCorpusId,
|
||||
CS::State: HasCorpus + HasSolutions + HasClientPerfMonitor + HasExecutions,
|
||||
{
|
||||
/// Process one input, adding to the respective corpora if needed and firing the right events
|
||||
#[inline]
|
||||
@ -480,7 +476,7 @@ where
|
||||
F: Feedback<CS::State>,
|
||||
OF: Feedback<CS::State>,
|
||||
OT: ObserversTuple<CS::State> + Serialize + DeserializeOwned,
|
||||
CS::State: HasCorpus + HasSolutions + HasClientPerfMonitor + HasExecutions + HasFuzzedCorpusId,
|
||||
CS::State: HasCorpus + HasSolutions + HasClientPerfMonitor + HasExecutions,
|
||||
{
|
||||
/// Process one input, adding to the respective corpora if needed and firing the right events
|
||||
#[inline]
|
||||
@ -518,7 +514,6 @@ where
|
||||
|
||||
// Add the input to the main corpus
|
||||
let mut testcase = Testcase::with_executions(input.clone(), *state.executions());
|
||||
testcase.set_parent_id_optional(state.fuzzed_corpus_id());
|
||||
self.feedback_mut()
|
||||
.append_metadata(state, observers, &mut testcase)?;
|
||||
let idx = state.corpus_mut().add(testcase)?;
|
||||
@ -552,7 +547,7 @@ where
|
||||
EM: ProgressReporter + EventProcessor<E, Self, State = CS::State>,
|
||||
F: Feedback<CS::State>,
|
||||
OF: Feedback<CS::State>,
|
||||
CS::State: HasClientPerfMonitor + HasExecutions + HasMetadata + HasFuzzedCorpusId,
|
||||
CS::State: HasClientPerfMonitor + HasExecutions + HasMetadata,
|
||||
ST: StagesTuple<E, EM, CS::State, Self>,
|
||||
{
|
||||
fn fuzz_one(
|
||||
@ -577,15 +572,9 @@ where
|
||||
#[cfg(feature = "introspection")]
|
||||
state.introspection_monitor_mut().reset_stage_index();
|
||||
|
||||
// Set the parent id - all new testcases will have this id as parent in the following stages.
|
||||
state.set_fuzzed_corpus_id(idx);
|
||||
|
||||
// Execute all stages
|
||||
stages.perform_all(self, executor, state, manager, idx)?;
|
||||
|
||||
// Reset the parent id
|
||||
state.clear_fuzzed_corpus_id();
|
||||
|
||||
// Init timer for manager
|
||||
#[cfg(feature = "introspection")]
|
||||
state.introspection_monitor_mut().start_timer();
|
||||
|
@ -8,9 +8,10 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
bolts::{rands::Rand, AsMutSlice, AsSlice, HasLen, HasRefCnt},
|
||||
corpus::{Corpus, CorpusId, Testcase},
|
||||
corpus::{Corpus, CorpusId},
|
||||
feedbacks::MapIndexesMetadata,
|
||||
inputs::UsesInput,
|
||||
observers::ObserversTuple,
|
||||
schedulers::{
|
||||
minimizer::{IsFavoredMetadata, MinimizerScheduler, DEFAULT_SKIP_NON_FAVORED_PROB},
|
||||
LenTimeMulTestcaseScore, Scheduler,
|
||||
@ -130,22 +131,16 @@ where
|
||||
self.inner.on_add(state, idx)
|
||||
}
|
||||
|
||||
fn on_replace(
|
||||
fn on_evaluation<OT>(
|
||||
&mut self,
|
||||
state: &mut Self::State,
|
||||
idx: CorpusId,
|
||||
testcase: &Testcase<<Self::State as UsesInput>::Input>,
|
||||
) -> Result<(), Error> {
|
||||
self.inner.on_replace(state, idx, testcase)
|
||||
}
|
||||
|
||||
fn on_remove(
|
||||
&mut self,
|
||||
state: &mut Self::State,
|
||||
idx: CorpusId,
|
||||
testcase: &Option<Testcase<<Self::State as UsesInput>::Input>>,
|
||||
) -> Result<(), Error> {
|
||||
self.inner.on_remove(state, idx, testcase)
|
||||
input: &<Self::State as UsesInput>::Input,
|
||||
observers: &OT,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
OT: ObserversTuple<Self::State>,
|
||||
{
|
||||
self.inner.on_evaluation(state, input, observers)
|
||||
}
|
||||
|
||||
fn next(&mut self, state: &mut Self::State) -> Result<CorpusId, Error> {
|
||||
@ -170,8 +165,21 @@ where
|
||||
{
|
||||
idx = self.inner.base_mut().next(state)?;
|
||||
}
|
||||
|
||||
// Don't add corpus.curret(). The inner scheduler will take care of it
|
||||
|
||||
Ok(idx)
|
||||
}
|
||||
|
||||
/// Set current fuzzed corpus id and `scheduled_count`
|
||||
fn set_current_scheduled(
|
||||
&mut self,
|
||||
_state: &mut Self::State,
|
||||
_next_idx: Option<CorpusId>,
|
||||
) -> Result<(), Error> {
|
||||
// We do nothing here, the inner scheduler will take care of it
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, CS> CoverageAccountingScheduler<'a, CS>
|
||||
@ -271,7 +279,7 @@ where
|
||||
|
||||
for (_key, idx) in &top_rated.map {
|
||||
let mut entry = state.corpus().get(*idx)?.borrow_mut();
|
||||
if entry.fuzzed() {
|
||||
if entry.scheduled_count() > 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -282,7 +290,7 @@ where
|
||||
}
|
||||
|
||||
/// Creates a new [`CoverageAccountingScheduler`] that wraps a `base` [`Scheduler`]
|
||||
/// and has a default probability to skip non-faved [`Testcase`]s of [`DEFAULT_SKIP_NON_FAVORED_PROB`].
|
||||
/// and has a default probability to skip non-faved Testcases of [`DEFAULT_SKIP_NON_FAVORED_PROB`].
|
||||
pub fn new(state: &mut CS::State, base: CS, accounting_map: &'a [u32]) -> Self {
|
||||
match state.metadata().get::<TopAccountingMetadata>() {
|
||||
Some(meta) => {
|
||||
@ -302,7 +310,7 @@ where
|
||||
}
|
||||
|
||||
/// Creates a new [`CoverageAccountingScheduler`] that wraps a `base` [`Scheduler`]
|
||||
/// and has a non-default probability to skip non-faved [`Testcase`]s using (`skip_non_favored_prob`).
|
||||
/// and has a non-default probability to skip non-faved Testcases using (`skip_non_favored_prob`).
|
||||
pub fn with_skip_prob(
|
||||
state: &mut CS::State,
|
||||
base: CS,
|
||||
|
@ -47,7 +47,6 @@ pub struct EcoTestcaseMetadata {
|
||||
last_energy: u64,
|
||||
state: EcoState,
|
||||
serial: u64,
|
||||
was_fuzzed: bool,
|
||||
computed_score: f64,
|
||||
}
|
||||
|
||||
@ -117,7 +116,6 @@ where
|
||||
.get_mut::<EcoTestcaseMetadata>()
|
||||
.ok_or_else(|| Error::key_not_found("EcoTestcaseMetadata not found".to_string()))?;
|
||||
// Set was_fuzzed for the old current
|
||||
meta.was_fuzzed = true;
|
||||
meta.last_found = count - last_corpus_count;
|
||||
meta.last_energy = meta.mutation_num - last_mutation_num;
|
||||
meta.computed_score
|
||||
@ -165,29 +163,15 @@ where
|
||||
fn schedule(state: &mut S) -> Result<CorpusId, Error> {
|
||||
let mut selection = None;
|
||||
for id in state.corpus().ids() {
|
||||
let was_fuzzed = state
|
||||
.corpus()
|
||||
.get(id)?
|
||||
.borrow()
|
||||
.metadata()
|
||||
.get::<EcoTestcaseMetadata>()
|
||||
.ok_or_else(|| Error::key_not_found("EcoTestcaseMetadata not found".to_string()))?
|
||||
.was_fuzzed;
|
||||
if !was_fuzzed {
|
||||
let was_fuzzed = state.corpus().get(id)?.borrow().scheduled_count() > 0;
|
||||
if was_fuzzed {
|
||||
selection = Some(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for id in state.corpus().ids() {
|
||||
let was_fuzzed = state
|
||||
.corpus()
|
||||
.get(id)?
|
||||
.borrow()
|
||||
.metadata()
|
||||
.get::<EcoTestcaseMetadata>()
|
||||
.ok_or_else(|| Error::key_not_found("EcoTestcaseMetadata not found".to_string()))?
|
||||
.was_fuzzed;
|
||||
let was_fuzzed = state.corpus().get(id)?.borrow().scheduled_count() > 0;
|
||||
if was_fuzzed {
|
||||
state
|
||||
.metadata_mut()
|
||||
@ -301,10 +285,14 @@ where
|
||||
|
||||
// Attach a `SchedulerTestcaseMetaData` to the queue entry.
|
||||
depth += 1;
|
||||
state.corpus().get(idx)?.borrow_mut().add_metadata(
|
||||
SchedulerTestcaseMetaData::with_n_fuzz_entry(depth, self.last_hash),
|
||||
);
|
||||
|
||||
{
|
||||
let mut testcase = state.corpus().get(idx)?.borrow_mut();
|
||||
testcase.add_metadata(SchedulerTestcaseMetaData::with_n_fuzz_entry(
|
||||
depth,
|
||||
self.last_hash,
|
||||
));
|
||||
testcase.set_parent_id_optional(current_idx);
|
||||
}
|
||||
// Add the testcase metadata for this scheduler
|
||||
state
|
||||
.corpus()
|
||||
@ -324,25 +312,6 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_replace(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
idx: CorpusId,
|
||||
_testcase: &Testcase<S::Input>,
|
||||
) -> Result<(), Error> {
|
||||
self.on_add(state, idx)
|
||||
}
|
||||
|
||||
#[allow(clippy::unused_self)]
|
||||
fn on_remove(
|
||||
&mut self,
|
||||
_state: &mut S,
|
||||
_idx: CorpusId,
|
||||
_testcase: &Option<Testcase<S::Input>>,
|
||||
) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_evaluation<OT>(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
@ -414,7 +383,7 @@ where
|
||||
}
|
||||
|
||||
let id = Self::schedule(state)?;
|
||||
*state.corpus_mut().current_mut() = Some(id);
|
||||
self.set_current_scheduled(state, Some(id))?;
|
||||
|
||||
let mutation_num = state
|
||||
.corpus()
|
||||
@ -439,6 +408,26 @@ where
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
/// Set current fuzzed corpus id and `scheduled_count`
|
||||
fn set_current_scheduled(
|
||||
&mut self,
|
||||
state: &mut Self::State,
|
||||
next_idx: Option<CorpusId>,
|
||||
) -> Result<(), Error> {
|
||||
let current_idx = *state.corpus().current();
|
||||
|
||||
if let Some(idx) = current_idx {
|
||||
let mut testcase = state.corpus().get(idx)?.borrow_mut();
|
||||
let scheduled_count = testcase.scheduled_count();
|
||||
|
||||
// increase scheduled count, this was fuzz_level in afl
|
||||
testcase.set_scheduled_count(scheduled_count + 1);
|
||||
}
|
||||
|
||||
*state.corpus_mut().current_mut() = next_idx;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// The weight for each corpus entry
|
||||
|
@ -13,7 +13,7 @@ use crate::{
|
||||
feedbacks::MapIndexesMetadata,
|
||||
inputs::UsesInput,
|
||||
observers::ObserversTuple,
|
||||
schedulers::{LenTimeMulTestcaseScore, Scheduler, TestcaseScore},
|
||||
schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore},
|
||||
state::{HasCorpus, HasMetadata, HasRand, UsesState},
|
||||
Error,
|
||||
};
|
||||
@ -75,19 +75,13 @@ where
|
||||
type State = CS::State;
|
||||
}
|
||||
|
||||
impl<CS, F, M> Scheduler for MinimizerScheduler<CS, F, M>
|
||||
impl<CS, F, M> RemovableScheduler for MinimizerScheduler<CS, F, M>
|
||||
where
|
||||
CS: Scheduler,
|
||||
CS: RemovableScheduler,
|
||||
F: TestcaseScore<CS::State>,
|
||||
M: AsSlice<Entry = usize> + SerdeAny + HasRefCnt,
|
||||
CS::State: HasCorpus + HasMetadata + HasRand,
|
||||
{
|
||||
/// Add an entry to the corpus and return its index
|
||||
fn on_add(&mut self, state: &mut CS::State, idx: CorpusId) -> Result<(), Error> {
|
||||
self.base.on_add(state, idx)?;
|
||||
self.update_score(state, idx)
|
||||
}
|
||||
|
||||
/// Replaces the testcase at the given idx
|
||||
fn on_replace(
|
||||
&mut self,
|
||||
@ -162,6 +156,20 @@ where
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<CS, F, M> Scheduler for MinimizerScheduler<CS, F, M>
|
||||
where
|
||||
CS: Scheduler,
|
||||
F: TestcaseScore<CS::State>,
|
||||
M: AsSlice<Entry = usize> + SerdeAny + HasRefCnt,
|
||||
CS::State: HasCorpus + HasMetadata + HasRand,
|
||||
{
|
||||
/// Add an entry to the corpus and return its index
|
||||
fn on_add(&mut self, state: &mut CS::State, idx: CorpusId) -> Result<(), Error> {
|
||||
self.base.on_add(state, idx)?;
|
||||
self.update_score(state, idx)
|
||||
}
|
||||
|
||||
/// An input has been evaluated
|
||||
fn on_evaluation<OT>(
|
||||
@ -193,6 +201,16 @@ where
|
||||
}
|
||||
Ok(idx)
|
||||
}
|
||||
|
||||
/// Set current fuzzed corpus id and `scheduled_count`
|
||||
fn set_current_scheduled(
|
||||
&mut self,
|
||||
_state: &mut Self::State,
|
||||
_next_idx: Option<CorpusId>,
|
||||
) -> Result<(), Error> {
|
||||
// We do nothing here, the inner scheduler will take care of it
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<CS, F, M> MinimizerScheduler<CS, F, M>
|
||||
|
@ -42,11 +42,15 @@ use crate::{
|
||||
Error,
|
||||
};
|
||||
|
||||
/// The scheduler define how the fuzzer requests a testcase from the corpus.
|
||||
/// It has hooks to corpus add/replace/remove to allow complex scheduling algorithms to collect data.
|
||||
pub trait Scheduler: UsesState {
|
||||
/// Added an entry to the corpus at the given index
|
||||
fn on_add(&mut self, _state: &mut Self::State, _idx: CorpusId) -> Result<(), Error> {
|
||||
/// The scheduler also implemnts `on_remove` and `on_replace` if it implements this stage.
|
||||
pub trait RemovableScheduler: Scheduler {
|
||||
/// Removed the given entry from the corpus at the given index
|
||||
fn on_remove(
|
||||
&mut self,
|
||||
_state: &mut Self::State,
|
||||
_idx: CorpusId,
|
||||
_testcase: &Option<Testcase<<Self::State as UsesInput>::Input>>,
|
||||
) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -59,16 +63,14 @@ pub trait Scheduler: UsesState {
|
||||
) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Removed the given entry from the corpus at the given index
|
||||
fn on_remove(
|
||||
&mut self,
|
||||
_state: &mut Self::State,
|
||||
_idx: CorpusId,
|
||||
_testcase: &Option<Testcase<<Self::State as UsesInput>::Input>>,
|
||||
) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
/// The scheduler define how the fuzzer requests a testcase from the corpus.
|
||||
/// It has hooks to corpus add/replace/remove to allow complex scheduling algorithms to collect data.
|
||||
pub trait Scheduler: UsesState {
|
||||
/// Added an entry to the corpus at the given index
|
||||
fn on_add(&mut self, _state: &mut Self::State, _idx: CorpusId) -> Result<(), Error>;
|
||||
// Add parent_id here if it has no inner
|
||||
|
||||
/// An input has been evaluated
|
||||
fn on_evaluation<OT>(
|
||||
@ -85,6 +87,14 @@ pub trait Scheduler: UsesState {
|
||||
|
||||
/// Gets the next entry
|
||||
fn next(&mut self, state: &mut Self::State) -> Result<CorpusId, Error>;
|
||||
// Increment corpus.current() here if it has no inner
|
||||
|
||||
/// Set current fuzzed corpus id and `scheduled_count`
|
||||
fn set_current_scheduled(
|
||||
&mut self,
|
||||
state: &mut Self::State,
|
||||
next_idx: Option<CorpusId>,
|
||||
) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
/// Feed the fuzzer simply with a random testcase on request
|
||||
@ -104,16 +114,38 @@ impl<S> Scheduler for RandScheduler<S>
|
||||
where
|
||||
S: HasCorpus + HasRand,
|
||||
{
|
||||
fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
|
||||
// Set parent id
|
||||
let current_idx = *state.corpus().current();
|
||||
state
|
||||
.corpus()
|
||||
.get(idx)?
|
||||
.borrow_mut()
|
||||
.set_parent_id_optional(current_idx);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets the next entry at random
|
||||
fn next(&mut self, state: &mut Self::State) -> Result<CorpusId, Error> {
|
||||
if state.corpus().count() == 0 {
|
||||
Err(Error::empty("No entries in corpus".to_owned()))
|
||||
} else {
|
||||
let id = random_corpus_id!(state.corpus(), state.rand_mut());
|
||||
*state.corpus_mut().current_mut() = Some(id);
|
||||
self.set_current_scheduled(state, Some(id))?;
|
||||
Ok(id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Set current fuzzed corpus id and `scheduled_count`. You should call this from `next`
|
||||
fn set_current_scheduled(
|
||||
&mut self,
|
||||
state: &mut Self::State,
|
||||
next_idx: Option<CorpusId>,
|
||||
) -> Result<(), Error> {
|
||||
*state.corpus_mut().current_mut() = next_idx;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> RandScheduler<S> {
|
||||
|
@ -12,7 +12,7 @@ use crate::{
|
||||
corpus::{Corpus, CorpusId, SchedulerTestcaseMetaData, Testcase},
|
||||
inputs::UsesInput,
|
||||
observers::{MapObserver, ObserversTuple},
|
||||
schedulers::Scheduler,
|
||||
schedulers::{RemovableScheduler, Scheduler},
|
||||
state::{HasCorpus, HasMetadata, UsesState},
|
||||
Error,
|
||||
};
|
||||
@ -178,40 +178,11 @@ where
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<O, S> Scheduler for PowerQueueScheduler<O, S>
|
||||
impl<O, S> RemovableScheduler for PowerQueueScheduler<O, S>
|
||||
where
|
||||
S: HasCorpus + HasMetadata,
|
||||
O: MapObserver,
|
||||
{
|
||||
/// Add an entry to the corpus and return its index
|
||||
fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
|
||||
let current_idx = *state.corpus().current();
|
||||
|
||||
let mut depth = match current_idx {
|
||||
Some(parent_idx) => state
|
||||
.corpus()
|
||||
.get(parent_idx)?
|
||||
.borrow()
|
||||
.metadata()
|
||||
.get::<SchedulerTestcaseMetaData>()
|
||||
.ok_or_else(|| {
|
||||
Error::key_not_found("SchedulerTestcaseMetaData not found".to_string())
|
||||
})?
|
||||
.depth(),
|
||||
None => 0,
|
||||
};
|
||||
|
||||
// TODO increase perf_score when finding new things like in AFL
|
||||
// https://github.com/google/AFL/blob/master/afl-fuzz.c#L6547
|
||||
|
||||
// Attach a `SchedulerTestcaseMetaData` to the queue entry.
|
||||
depth += 1;
|
||||
state.corpus().get(idx)?.borrow_mut().add_metadata(
|
||||
SchedulerTestcaseMetaData::with_n_fuzz_entry(depth, self.last_hash),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_precision_loss)]
|
||||
fn on_replace(
|
||||
&mut self,
|
||||
@ -292,6 +263,44 @@ where
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<O, S> Scheduler for PowerQueueScheduler<O, S>
|
||||
where
|
||||
S: HasCorpus + HasMetadata,
|
||||
O: MapObserver,
|
||||
{
|
||||
/// Add an entry to the corpus and return its index
|
||||
fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
|
||||
let current_idx = *state.corpus().current();
|
||||
|
||||
let mut depth = match current_idx {
|
||||
Some(parent_idx) => state
|
||||
.corpus()
|
||||
.get(parent_idx)?
|
||||
.borrow()
|
||||
.metadata()
|
||||
.get::<SchedulerTestcaseMetaData>()
|
||||
.ok_or_else(|| {
|
||||
Error::key_not_found("SchedulerTestcaseMetaData not found".to_string())
|
||||
})?
|
||||
.depth(),
|
||||
None => 0,
|
||||
};
|
||||
|
||||
// TODO increase perf_score when finding new things like in AFL
|
||||
// https://github.com/google/AFL/blob/master/afl-fuzz.c#L6547
|
||||
|
||||
// Attach a `SchedulerTestcaseMetaData` to the queue entry.
|
||||
depth += 1;
|
||||
let mut testcase = state.corpus().get(idx)?.borrow_mut();
|
||||
testcase.add_metadata(SchedulerTestcaseMetaData::with_n_fuzz_entry(
|
||||
depth,
|
||||
self.last_hash,
|
||||
));
|
||||
testcase.set_parent_id_optional(current_idx);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_evaluation<OT>(
|
||||
&mut self,
|
||||
@ -343,10 +352,27 @@ where
|
||||
}
|
||||
None => state.corpus().first().unwrap(),
|
||||
};
|
||||
*state.corpus_mut().current_mut() = Some(id);
|
||||
self.set_current_scheduled(state, Some(id))?;
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Set current fuzzed corpus id and `scheduled_count`
|
||||
fn set_current_scheduled(
|
||||
&mut self,
|
||||
state: &mut Self::State,
|
||||
next_idx: Option<CorpusId>,
|
||||
) -> Result<(), Error> {
|
||||
let current_idx = *state.corpus().current();
|
||||
|
||||
if let Some(idx) = current_idx {
|
||||
let mut testcase = state.corpus().get(idx)?.borrow_mut();
|
||||
let scheduled_count = testcase.scheduled_count();
|
||||
|
||||
// increase scheduled count, this was fuzz_level in afl
|
||||
testcase.set_scheduled_count(scheduled_count + 1);
|
||||
|
||||
// Update the handicap
|
||||
let mut testcase = state.corpus().get(id)?.borrow_mut();
|
||||
let tcmeta = testcase
|
||||
.metadata_mut()
|
||||
.get_mut::<SchedulerTestcaseMetaData>()
|
||||
@ -359,9 +385,10 @@ where
|
||||
} else if tcmeta.handicap() > 0 {
|
||||
tcmeta.set_handicap(tcmeta.handicap() - 1);
|
||||
}
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
*state.corpus_mut().current_mut() = next_idx;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,6 +100,13 @@ where
|
||||
S: HasCorpus + HasMetadata + HasRand,
|
||||
{
|
||||
fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
|
||||
let current_idx = *state.corpus().current();
|
||||
state
|
||||
.corpus()
|
||||
.get(idx)?
|
||||
.borrow_mut()
|
||||
.set_parent_id_optional(current_idx);
|
||||
|
||||
if state.metadata().get::<ProbabilityMetadata>().is_none() {
|
||||
state.add_metadata(ProbabilityMetadata::new());
|
||||
}
|
||||
@ -124,10 +131,20 @@ where
|
||||
break;
|
||||
}
|
||||
}
|
||||
*state.corpus_mut().current_mut() = Some(ret);
|
||||
self.set_current_scheduled(state, Some(ret))?;
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
/// Set current fuzzed corpus id and `scheduled_count`
|
||||
fn set_current_scheduled(
|
||||
&mut self,
|
||||
state: &mut Self::State,
|
||||
next_idx: Option<CorpusId>,
|
||||
) -> Result<(), Error> {
|
||||
*state.corpus_mut().current_mut() = next_idx;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S> Default for ProbabilitySamplingScheduler<F, S>
|
||||
|
@ -6,7 +6,7 @@ use core::marker::PhantomData;
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId},
|
||||
inputs::UsesInput,
|
||||
schedulers::Scheduler,
|
||||
schedulers::{RemovableScheduler, Scheduler},
|
||||
state::{HasCorpus, UsesState},
|
||||
Error,
|
||||
};
|
||||
@ -24,10 +24,24 @@ where
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<S> RemovableScheduler for QueueScheduler<S> where S: HasCorpus {}
|
||||
|
||||
impl<S> Scheduler for QueueScheduler<S>
|
||||
where
|
||||
S: HasCorpus,
|
||||
{
|
||||
fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
|
||||
// Set parent id
|
||||
let current_idx = *state.corpus().current();
|
||||
state
|
||||
.corpus()
|
||||
.get(idx)?
|
||||
.borrow_mut()
|
||||
.set_parent_id_optional(current_idx);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets the next entry in the queue
|
||||
fn next(&mut self, state: &mut Self::State) -> Result<CorpusId, Error> {
|
||||
if state.corpus().count() == 0 {
|
||||
@ -39,10 +53,20 @@ where
|
||||
.map(|id| state.corpus().next(id))
|
||||
.flatten()
|
||||
.unwrap_or_else(|| state.corpus().first().unwrap());
|
||||
*state.corpus_mut().current_mut() = Some(id);
|
||||
self.set_current_scheduled(state, Some(id))?;
|
||||
Ok(id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Set current fuzzed corpus id and `scheduled_count`
|
||||
fn set_current_scheduled(
|
||||
&mut self,
|
||||
state: &mut Self::State,
|
||||
next_idx: Option<CorpusId>,
|
||||
) -> Result<(), Error> {
|
||||
*state.corpus_mut().current_mut() = next_idx;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> QueueScheduler<S> {
|
||||
|
@ -205,7 +205,7 @@ where
|
||||
}
|
||||
}
|
||||
PowerSchedule::FAST => {
|
||||
if entry.fuzz_level() != 0 {
|
||||
if entry.scheduled_count() != 0 {
|
||||
let lg = libm::log2(f64::from(psmeta.n_fuzz()[tcmeta.n_fuzz_entry()]));
|
||||
|
||||
match lg {
|
||||
@ -244,11 +244,11 @@ where
|
||||
}
|
||||
}
|
||||
PowerSchedule::LIN => {
|
||||
factor = (entry.fuzz_level() as f64)
|
||||
factor = (entry.scheduled_count() as f64)
|
||||
/ f64::from(psmeta.n_fuzz()[tcmeta.n_fuzz_entry()] + 1);
|
||||
}
|
||||
PowerSchedule::QUAD => {
|
||||
factor = ((entry.fuzz_level() * entry.fuzz_level()) as f64)
|
||||
factor = ((entry.scheduled_count() * entry.scheduled_count()) as f64)
|
||||
/ f64::from(psmeta.n_fuzz()[tcmeta.n_fuzz_entry()] + 1);
|
||||
}
|
||||
}
|
||||
@ -310,7 +310,7 @@ where
|
||||
// This means that this testcase has never gone through the calibration stage before1,
|
||||
// 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.scheduled_count() == 0 || psmeta.cycles() == 0 {
|
||||
return Ok(weight);
|
||||
}
|
||||
|
||||
@ -362,7 +362,7 @@ where
|
||||
}
|
||||
|
||||
// was it fuzzed before?
|
||||
if entry.fuzz_level() == 0 {
|
||||
if entry.scheduled_count() == 0 {
|
||||
weight *= 2.0;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ use core::marker::PhantomData;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::RemovableScheduler;
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId},
|
||||
impl_serdeany,
|
||||
@ -88,10 +89,24 @@ where
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<S> RemovableScheduler for TuneableScheduler<S> where S: HasCorpus + HasMetadata {}
|
||||
|
||||
impl<S> Scheduler for TuneableScheduler<S>
|
||||
where
|
||||
S: HasCorpus + HasMetadata,
|
||||
{
|
||||
fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
|
||||
// Set parent id
|
||||
let current_idx = *state.corpus().current();
|
||||
state
|
||||
.corpus()
|
||||
.get(idx)?
|
||||
.borrow_mut()
|
||||
.set_parent_id_optional(current_idx);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets the next entry in the queue
|
||||
fn next(&mut self, state: &mut Self::State) -> Result<CorpusId, Error> {
|
||||
if state.corpus().count() == 0 {
|
||||
@ -105,7 +120,17 @@ where
|
||||
} else {
|
||||
state.corpus().first().unwrap()
|
||||
};
|
||||
*state.corpus_mut().current_mut() = Some(id);
|
||||
self.set_current_scheduled(state, Some(id))?;
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
/// Set current fuzzed corpus id and `scheduled_count`
|
||||
fn set_current_scheduled(
|
||||
&mut self,
|
||||
state: &mut Self::State,
|
||||
next_idx: Option<CorpusId>,
|
||||
) -> Result<(), Error> {
|
||||
*state.corpus_mut().current_mut() = next_idx;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -9,14 +9,14 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
bolts::rands::Rand,
|
||||
corpus::{Corpus, CorpusId, SchedulerTestcaseMetaData, Testcase},
|
||||
corpus::{Corpus, CorpusId, SchedulerTestcaseMetaData},
|
||||
inputs::UsesInput,
|
||||
observers::{MapObserver, ObserversTuple},
|
||||
random_corpus_id,
|
||||
schedulers::{
|
||||
powersched::{PowerSchedule, SchedulerMetadata},
|
||||
testcase_score::{CorpusWeightTestcaseScore, TestcaseScore},
|
||||
Scheduler,
|
||||
RemovableScheduler, Scheduler,
|
||||
},
|
||||
state::{HasCorpus, HasMetadata, HasRand, UsesState},
|
||||
Error,
|
||||
@ -229,6 +229,94 @@ where
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<F, O, S> RemovableScheduler for WeightedScheduler<F, O, S>
|
||||
where
|
||||
F: TestcaseScore<S>,
|
||||
O: MapObserver,
|
||||
S: HasCorpus + HasMetadata + HasRand,
|
||||
{
|
||||
#[allow(clippy::cast_precision_loss)]
|
||||
fn on_remove(
|
||||
&mut self,
|
||||
state: &mut Self::State,
|
||||
_idx: CorpusId,
|
||||
prev: &Option<crate::corpus::Testcase<<Self::State as UsesInput>::Input>>,
|
||||
) -> Result<(), Error> {
|
||||
let prev = prev.as_ref().ok_or_else(|| {
|
||||
Error::illegal_argument(
|
||||
"Power schedulers must be aware of the removed corpus entry for reweighting.",
|
||||
)
|
||||
})?;
|
||||
|
||||
let prev_meta = prev
|
||||
.metadata()
|
||||
.get::<SchedulerTestcaseMetaData>()
|
||||
.ok_or_else(|| {
|
||||
Error::key_not_found("SchedulerTestcaseMetaData not found".to_string())
|
||||
})?;
|
||||
|
||||
// Use these to adjust `SchedulerMetadata`
|
||||
let (prev_total_time, prev_cycles) = prev_meta.cycle_and_time();
|
||||
let prev_bitmap_size = prev_meta.bitmap_size();
|
||||
let prev_bitmap_size_log = libm::log2(prev_bitmap_size as f64);
|
||||
|
||||
let psmeta = state
|
||||
.metadata_mut()
|
||||
.get_mut::<SchedulerMetadata>()
|
||||
.ok_or_else(|| Error::key_not_found("SchedulerMetadata not found".to_string()))?;
|
||||
|
||||
psmeta.set_exec_time(psmeta.exec_time() - prev_total_time);
|
||||
psmeta.set_cycles(psmeta.cycles() - (prev_cycles as u64));
|
||||
psmeta.set_bitmap_size(psmeta.bitmap_size() - prev_bitmap_size);
|
||||
psmeta.set_bitmap_size_log(psmeta.bitmap_size_log() - prev_bitmap_size_log);
|
||||
psmeta.set_bitmap_entries(psmeta.bitmap_entries() - 1);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_precision_loss)]
|
||||
fn on_replace(
|
||||
&mut self,
|
||||
state: &mut Self::State,
|
||||
idx: CorpusId,
|
||||
prev: &crate::corpus::Testcase<<Self::State as UsesInput>::Input>,
|
||||
) -> Result<(), Error> {
|
||||
let prev_meta = prev
|
||||
.metadata()
|
||||
.get::<SchedulerTestcaseMetaData>()
|
||||
.ok_or_else(|| {
|
||||
Error::key_not_found("SchedulerTestcaseMetaData not found".to_string())
|
||||
})?;
|
||||
|
||||
// Next depth is + 1
|
||||
let prev_depth = prev_meta.depth() + 1;
|
||||
|
||||
// Use these to adjust `SchedulerMetadata`
|
||||
let (prev_total_time, prev_cycles) = prev_meta.cycle_and_time();
|
||||
let prev_bitmap_size = prev_meta.bitmap_size();
|
||||
let prev_bitmap_size_log = libm::log2(prev_bitmap_size as f64);
|
||||
|
||||
let psmeta = state
|
||||
.metadata_mut()
|
||||
.get_mut::<SchedulerMetadata>()
|
||||
.ok_or_else(|| Error::key_not_found("SchedulerMetadata not found".to_string()))?;
|
||||
|
||||
// We won't add new one because it'll get added when it gets executed in calirbation next time.
|
||||
psmeta.set_exec_time(psmeta.exec_time() - prev_total_time);
|
||||
psmeta.set_cycles(psmeta.cycles() - (prev_cycles as u64));
|
||||
psmeta.set_bitmap_size(psmeta.bitmap_size() - prev_bitmap_size);
|
||||
psmeta.set_bitmap_size_log(psmeta.bitmap_size_log() - prev_bitmap_size_log);
|
||||
psmeta.set_bitmap_entries(psmeta.bitmap_entries() - 1);
|
||||
|
||||
state
|
||||
.corpus()
|
||||
.get(idx)?
|
||||
.borrow_mut()
|
||||
.add_metadata(SchedulerTestcaseMetaData::new(prev_depth));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, O, S> Scheduler for WeightedScheduler<F, O, S>
|
||||
where
|
||||
F: TestcaseScore<S>,
|
||||
@ -255,9 +343,14 @@ where
|
||||
|
||||
// Attach a `SchedulerTestcaseMetaData` to the queue entry.
|
||||
depth += 1;
|
||||
state.corpus().get(idx)?.borrow_mut().add_metadata(
|
||||
SchedulerTestcaseMetaData::with_n_fuzz_entry(depth, self.last_hash),
|
||||
);
|
||||
{
|
||||
let mut testcase = state.corpus().get(idx)?.borrow_mut();
|
||||
testcase.add_metadata(SchedulerTestcaseMetaData::with_n_fuzz_entry(
|
||||
depth,
|
||||
self.last_hash,
|
||||
));
|
||||
testcase.set_parent_id_optional(current_idx);
|
||||
}
|
||||
|
||||
// TODO increase perf_score when finding new things like in AFL
|
||||
// https://github.com/google/AFL/blob/master/afl-fuzz.c#L6547
|
||||
@ -267,27 +360,6 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_replace(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
idx: CorpusId,
|
||||
_testcase: &Testcase<S::Input>,
|
||||
) -> Result<(), Error> {
|
||||
// Recreate the alias table
|
||||
self.on_add(state, idx)
|
||||
}
|
||||
|
||||
fn on_remove(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
_idx: CorpusId,
|
||||
_testcase: &Option<Testcase<S::Input>>,
|
||||
) -> Result<(), Error> {
|
||||
// Recreate the alias table
|
||||
self.create_alias_table(state)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_evaluation<OT>(
|
||||
&mut self,
|
||||
state: &mut Self::State,
|
||||
@ -360,10 +432,27 @@ where
|
||||
})?;
|
||||
psmeta.set_queue_cycles(psmeta.queue_cycles() + 1);
|
||||
}
|
||||
*state.corpus_mut().current_mut() = Some(idx);
|
||||
|
||||
// Update the handicap
|
||||
self.set_current_scheduled(state, Some(idx))?;
|
||||
Ok(idx)
|
||||
}
|
||||
}
|
||||
|
||||
/// Set current fuzzed corpus id and `scheduled_count`
|
||||
fn set_current_scheduled(
|
||||
&mut self,
|
||||
state: &mut Self::State,
|
||||
next_idx: Option<CorpusId>,
|
||||
) -> Result<(), Error> {
|
||||
let current_idx = *state.corpus().current();
|
||||
|
||||
if let Some(idx) = current_idx {
|
||||
let mut testcase = state.corpus().get(idx)?.borrow_mut();
|
||||
let scheduled_count = testcase.scheduled_count();
|
||||
|
||||
// increase scheduled count, this was fuzz_level in afl
|
||||
testcase.set_scheduled_count(scheduled_count + 1);
|
||||
|
||||
let tcmeta = testcase
|
||||
.metadata_mut()
|
||||
.get_mut::<SchedulerTestcaseMetaData>()
|
||||
@ -376,8 +465,10 @@ where
|
||||
} else if tcmeta.handicap() > 0 {
|
||||
tcmeta.set_handicap(tcmeta.handicap() - 1);
|
||||
}
|
||||
Ok(idx)
|
||||
}
|
||||
|
||||
*state.corpus_mut().current_mut() = next_idx;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,9 @@ where
|
||||
// Run this stage only once for each corpus entry and only if we haven't already inspected it
|
||||
{
|
||||
let corpus = state.corpus().get(corpus_idx)?.borrow();
|
||||
if corpus.fuzz_level() > 0 {
|
||||
// println!("calibration; corpus.scheduled_count() : {}", corpus.scheduled_count());
|
||||
|
||||
if corpus.scheduled_count() > 0 {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@ -269,10 +271,10 @@ where
|
||||
psmeta.set_bitmap_entries(psmeta.bitmap_entries() + 1);
|
||||
|
||||
let mut testcase = state.corpus().get(corpus_idx)?.borrow_mut();
|
||||
let fuzz_level = testcase.fuzz_level();
|
||||
let scheduled_count = testcase.scheduled_count();
|
||||
|
||||
testcase.set_exec_time(total_time / (iter as u32));
|
||||
testcase.set_fuzz_level(fuzz_level + 1);
|
||||
testcase.set_scheduled_count(scheduled_count + 1);
|
||||
// log::trace!("time: {:#?}", testcase.exec_time());
|
||||
|
||||
let data = testcase
|
||||
|
@ -21,9 +21,7 @@ use crate::{
|
||||
observers::ObserversTuple,
|
||||
schedulers::Scheduler,
|
||||
start_timer,
|
||||
state::{
|
||||
HasClientPerfMonitor, HasCorpus, HasExecutions, HasFuzzedCorpusId, HasMetadata, HasRand,
|
||||
},
|
||||
state::{HasClientPerfMonitor, HasCorpus, HasExecutions, HasMetadata, HasRand},
|
||||
Error, EvaluatorObservers, ExecutionProcessor, HasScheduler,
|
||||
};
|
||||
|
||||
@ -90,14 +88,8 @@ where
|
||||
EM: EventFirer<State = CS::State> + EventRestarter + HasEventManagerId + ProgressReporter,
|
||||
M: Mutator<CS::Input, CS::State>,
|
||||
OT: ObserversTuple<CS::State>,
|
||||
CS::State: HasFuzzedCorpusId
|
||||
+ HasClientPerfMonitor
|
||||
+ HasCorpus
|
||||
+ HasRand
|
||||
+ HasExecutions
|
||||
+ HasMetadata
|
||||
+ Clone
|
||||
+ Debug,
|
||||
CS::State:
|
||||
HasClientPerfMonitor + HasCorpus + HasRand + HasExecutions + HasMetadata + Clone + Debug,
|
||||
Z: ExecutionProcessor<OT, State = CS::State>
|
||||
+ EvaluatorObservers<OT>
|
||||
+ HasScheduler<Scheduler = CS>,
|
||||
@ -144,8 +136,6 @@ where
|
||||
return None;
|
||||
}
|
||||
|
||||
let idx = self.current_corpus_idx.unwrap();
|
||||
state.set_fuzzed_corpus_id(idx);
|
||||
start_timer!(state);
|
||||
let mut input = state
|
||||
.corpus()
|
||||
@ -188,7 +178,6 @@ where
|
||||
.post_exec(state, self.stage_idx, self.current_corpus_idx)?;
|
||||
mark_feature_time!(state, PerfFeature::MutatePostExec);
|
||||
self.testcases_done += 1;
|
||||
state.clear_fuzzed_corpus_id();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -212,14 +201,8 @@ where
|
||||
EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter<State = CS::State>,
|
||||
M: Mutator<CS::Input, CS::State>,
|
||||
OT: ObserversTuple<CS::State>,
|
||||
CS::State: HasClientPerfMonitor
|
||||
+ HasCorpus
|
||||
+ HasRand
|
||||
+ HasExecutions
|
||||
+ HasMetadata
|
||||
+ Clone
|
||||
+ Debug
|
||||
+ HasFuzzedCorpusId,
|
||||
CS::State:
|
||||
HasClientPerfMonitor + HasCorpus + HasRand + HasExecutions + HasMetadata + Clone + Debug,
|
||||
Z: ExecutionProcessor<OT, State = CS::State>
|
||||
+ EvaluatorObservers<OT>
|
||||
+ HasScheduler<Scheduler = CS>,
|
||||
|
@ -21,7 +21,7 @@ use crate::{
|
||||
mark_feature_time,
|
||||
mutators::Mutator,
|
||||
observers::{MapObserver, ObserversTuple},
|
||||
schedulers::Scheduler,
|
||||
schedulers::{RemovableScheduler, Scheduler},
|
||||
stages::Stage,
|
||||
start_timer,
|
||||
state::{HasClientPerfMonitor, HasCorpus, HasExecutions, HasMaxSize, HasSolutions, UsesState},
|
||||
@ -36,7 +36,7 @@ pub trait TMinMutationalStage<CS, E, EM, F1, F2, M, OT, Z>:
|
||||
where
|
||||
Self::State: HasCorpus + HasSolutions + HasExecutions + HasMaxSize + HasClientPerfMonitor,
|
||||
<Self::State as UsesInput>::Input: HasLen + Hash,
|
||||
CS: Scheduler<State = Self::State>,
|
||||
CS: Scheduler<State = Self::State> + RemovableScheduler,
|
||||
E: Executor<EM, Z> + HasObservers<Observers = OT, State = Self::State>,
|
||||
EM: EventFirer<State = Self::State>,
|
||||
F1: Feedback<Self::State>,
|
||||
@ -204,7 +204,7 @@ where
|
||||
impl<CS, E, EM, F1, F2, FF, M, OT, Z> Stage<E, EM, Z>
|
||||
for StdTMinMutationalStage<CS, E, EM, F1, F2, FF, M, OT, Z>
|
||||
where
|
||||
CS: Scheduler,
|
||||
CS: Scheduler + RemovableScheduler,
|
||||
CS::State: HasCorpus + HasSolutions + HasExecutions + HasMaxSize + HasClientPerfMonitor,
|
||||
<CS::State as UsesInput>::Input: HasLen + Hash,
|
||||
E: Executor<EM, Z> + HasObservers<Observers = OT, State = CS::State>,
|
||||
@ -252,7 +252,7 @@ where
|
||||
impl<CS, E, EM, F1, F2, FF, M, OT, Z> TMinMutationalStage<CS, E, EM, F1, F2, M, OT, Z>
|
||||
for StdTMinMutationalStage<CS, E, EM, F1, F2, FF, M, OT, Z>
|
||||
where
|
||||
CS: Scheduler,
|
||||
CS: Scheduler + RemovableScheduler,
|
||||
E: HasObservers<Observers = OT, State = CS::State> + Executor<EM, Z>,
|
||||
EM: EventFirer<State = CS::State>,
|
||||
F1: Feedback<CS::State>,
|
||||
|
@ -60,21 +60,6 @@ pub trait HasCorpus: UsesInput {
|
||||
fn corpus_mut(&mut self) -> &mut Self::Corpus;
|
||||
}
|
||||
|
||||
/// Trait for a state that has information about which [`CorpusId`]
|
||||
/// is currently being fuzzed.
|
||||
/// When a new interesting input was found, this value becomes the `parent_id`.
|
||||
pub trait HasFuzzedCorpusId {
|
||||
/// The currently fuzzed [`CorpusId`], if known.
|
||||
/// If a new interesting testcase was found, this should usually become the `parent_id`.
|
||||
fn fuzzed_corpus_id(&self) -> Option<CorpusId>;
|
||||
|
||||
/// Sets the currently fuzzed [`CorpusId`].
|
||||
fn set_fuzzed_corpus_id(&mut self, corpus_id: CorpusId);
|
||||
|
||||
/// Resets the currently fuzzed [`CorpusId`].
|
||||
fn clear_fuzzed_corpus_id(&mut self);
|
||||
}
|
||||
|
||||
/// Interact with the maximum size
|
||||
pub trait HasMaxSize {
|
||||
/// The maximum size hint for items and mutations returned
|
||||
@ -207,8 +192,6 @@ pub struct StdState<I, C, R, SC> {
|
||||
named_metadata: NamedSerdeAnyMap,
|
||||
/// MaxSize testcase size for mutators that appreciate it
|
||||
max_size: usize,
|
||||
/// The [`CorpusId`] of the testcase we're currently fuzzing.
|
||||
fuzzed_corpus_id: Option<CorpusId>,
|
||||
/// Performance statistics for this fuzzer
|
||||
#[cfg(feature = "introspection")]
|
||||
introspection_monitor: ClientPerfMonitor,
|
||||
@ -274,20 +257,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, C, R, SC> HasFuzzedCorpusId for StdState<I, C, R, SC> {
|
||||
fn fuzzed_corpus_id(&self) -> Option<CorpusId> {
|
||||
self.fuzzed_corpus_id
|
||||
}
|
||||
|
||||
fn set_fuzzed_corpus_id(&mut self, fuzzed_corpus_id: CorpusId) {
|
||||
self.fuzzed_corpus_id = Some(fuzzed_corpus_id);
|
||||
}
|
||||
|
||||
fn clear_fuzzed_corpus_id(&mut self) {
|
||||
self.fuzzed_corpus_id = None;
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, C, R, SC> HasSolutions for StdState<I, C, R, SC>
|
||||
where
|
||||
I: Input,
|
||||
@ -725,7 +694,6 @@ where
|
||||
corpus,
|
||||
solutions,
|
||||
max_size: DEFAULT_MAX_SIZE,
|
||||
fuzzed_corpus_id: None,
|
||||
#[cfg(feature = "introspection")]
|
||||
introspection_monitor: ClientPerfMonitor::new(),
|
||||
#[cfg(feature = "std")]
|
||||
|
@ -8,7 +8,7 @@ use frida_gum::{
|
||||
#[cfg(windows)]
|
||||
use libafl::{
|
||||
executors::inprocess::{HasInProcessHandlers, InProcessHandlers},
|
||||
state::{HasClientPerfMonitor, HasFuzzedCorpusId, HasSolutions},
|
||||
state::{HasClientPerfMonitor, HasCorpus, HasSolutions},
|
||||
};
|
||||
use libafl::{
|
||||
executors::{Executor, ExitKind, HasObservers, InProcessExecutor},
|
||||
@ -200,7 +200,7 @@ impl<'a, 'b, 'c, H, OT, RT, S> HasInProcessHandlers
|
||||
for FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
S: UsesInput + HasClientPerfMonitor + HasSolutions + HasFuzzedCorpusId,
|
||||
S: UsesInput + HasClientPerfMonitor + HasSolutions + HasCorpus,
|
||||
S::Input: HasTargetBytes,
|
||||
OT: ObserversTuple<S>,
|
||||
RT: FridaRuntimeTuple,
|
||||
|
@ -13,10 +13,7 @@ use libafl::{
|
||||
fuzzer::HasObjective,
|
||||
inputs::UsesInput,
|
||||
observers::{ObserversTuple, UsesObservers},
|
||||
state::{
|
||||
HasClientPerfMonitor, HasCorpus, HasExecutions, HasFuzzedCorpusId, HasSolutions, State,
|
||||
UsesState,
|
||||
},
|
||||
state::{HasClientPerfMonitor, HasCorpus, HasExecutions, HasSolutions, State, UsesState},
|
||||
Error,
|
||||
};
|
||||
|
||||
@ -67,12 +64,7 @@ where
|
||||
where
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<S>,
|
||||
S: State
|
||||
+ HasExecutions
|
||||
+ HasCorpus
|
||||
+ HasSolutions
|
||||
+ HasClientPerfMonitor
|
||||
+ HasFuzzedCorpusId,
|
||||
S: State + HasExecutions + HasCorpus + HasSolutions + HasClientPerfMonitor,
|
||||
Z: HasObjective<Objective = OF, State = S>,
|
||||
{
|
||||
Ok(Self {
|
||||
|
@ -4,7 +4,7 @@ use libafl::{
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{inprocess::windows_asan_handler::asan_death_handler, Executor, HasObservers},
|
||||
feedbacks::Feedback,
|
||||
state::{HasClientPerfMonitor, HasFuzzedCorpusId, HasSolutions},
|
||||
state::{HasClientPerfMonitor, HasCorpus, HasSolutions},
|
||||
HasObjective,
|
||||
};
|
||||
|
||||
@ -32,7 +32,7 @@ where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId,
|
||||
E::State: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
||||
Z: HasObjective<Objective = OF, State = E::State>,
|
||||
{
|
||||
__sanitizer_set_death_callback(asan_death_handler::<E, EM, OF, Z>);
|
||||
|
Loading…
x
Reference in New Issue
Block a user