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:
Dongjia "toka" Zhang 2023-03-09 03:43:32 +09:00 committed by GitHub
parent 2ed6583041
commit 4d778dd64d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 445 additions and 303 deletions

View File

@ -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>,
{

View File

@ -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 {

View File

@ -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?

View File

@ -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,
};

View File

@ -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();

View File

@ -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,

View File

@ -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

View File

@ -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>

View File

@ -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> {

View File

@ -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(())
}
}

View File

@ -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>

View File

@ -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> {

View File

@ -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;
}

View File

@ -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(())
}
}

View File

@ -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(())
}
}

View File

@ -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

View File

@ -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>,

View File

@ -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>,

View File

@ -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")]

View File

@ -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,

View File

@ -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 {

View File

@ -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>);