pub mod mutational;
pub use mutational::{MutationalStage, StdMutationalStage};
pub mod tmin;
pub use tmin::{
MapEqualityFactory, MapEqualityFeedback, StdTMinMutationalStage, TMinMutationalStage,
};
pub mod push;
pub mod tracing;
pub use tracing::{ShadowTracingStage, TracingStage};
pub mod calibrate;
pub use calibrate::CalibrationStage;
pub mod power;
pub use power::{PowerMutationalStage, StdPowerMutationalStage};
pub mod generalization;
pub use generalization::GeneralizationStage;
pub mod owned;
pub use owned::StagesOwnedList;
pub mod tuneable;
pub use tuneable::*;
#[cfg(feature = "std")]
pub mod concolic;
#[cfg(feature = "std")]
pub use concolic::ConcolicTracingStage;
#[cfg(feature = "std")]
pub use concolic::SimpleConcolicMutationalStage;
#[cfg(feature = "std")]
pub mod sync;
#[cfg(feature = "std")]
pub use sync::*;
#[cfg(feature = "std")]
pub mod dump;
use core::{convert::From, marker::PhantomData};
#[cfg(feature = "std")]
pub use dump::*;
use self::push::PushStage;
use crate::{
corpus::CorpusId,
events::{EventFirer, EventRestarter, HasEventManagerId, ProgressReporter},
executors::{Executor, HasObservers},
inputs::UsesInput,
observers::ObserversTuple,
schedulers::Scheduler,
state::{HasClientPerfMonitor, HasExecutions, HasMetadata, HasRand, UsesState},
Error, EvaluatorObservers, ExecutesInput, ExecutionProcessor, HasScheduler,
};
pub trait Stage<E, EM, Z>: UsesState
where
E: UsesState<State = Self::State>,
EM: UsesState<State = Self::State>,
Z: UsesState<State = Self::State>,
{
fn perform(
&mut self,
fuzzer: &mut Z,
executor: &mut E,
state: &mut Self::State,
manager: &mut EM,
corpus_idx: CorpusId,
) -> Result<(), Error>;
}
pub trait StagesTuple<E, EM, S, Z>
where
E: UsesState<State = S>,
EM: UsesState<State = S>,
Z: UsesState<State = S>,
S: UsesInput,
{
fn perform_all(
&mut self,
fuzzer: &mut Z,
executor: &mut E,
state: &mut S,
manager: &mut EM,
corpus_idx: CorpusId,
) -> Result<(), Error>;
}
impl<E, EM, S, Z> StagesTuple<E, EM, S, Z> for ()
where
E: UsesState<State = S>,
EM: UsesState<State = S>,
Z: UsesState<State = S>,
S: UsesInput,
{
fn perform_all(
&mut self,
_: &mut Z,
_: &mut E,
_: &mut S,
_: &mut EM,
_: CorpusId,
) -> Result<(), Error> {
Ok(())
}
}
impl<Head, Tail, E, EM, Z> StagesTuple<E, EM, Head::State, Z> for (Head, Tail)
where
Head: Stage<E, EM, Z>,
Tail: StagesTuple<E, EM, Head::State, Z>,
E: UsesState<State = Head::State>,
EM: UsesState<State = Head::State>,
Z: UsesState<State = Head::State>,
{
fn perform_all(
&mut self,
fuzzer: &mut Z,
executor: &mut E,
state: &mut Head::State,
manager: &mut EM,
corpus_idx: CorpusId,
) -> Result<(), Error> {
self.0
.perform(fuzzer, executor, state, manager, corpus_idx)?;
self.1
.perform_all(fuzzer, executor, state, manager, corpus_idx)
}
}
#[derive(Debug)]
pub struct ClosureStage<CB, E, EM, Z>
where
CB: FnMut(&mut Z, &mut E, &mut E::State, &mut EM, CorpusId) -> Result<(), Error>,
E: UsesState,
{
closure: CB,
phantom: PhantomData<(E, EM, Z)>,
}
impl<CB, E, EM, Z> UsesState for ClosureStage<CB, E, EM, Z>
where
CB: FnMut(&mut Z, &mut E, &mut E::State, &mut EM, CorpusId) -> Result<(), Error>,
E: UsesState,
{
type State = E::State;
}
impl<CB, E, EM, Z> Stage<E, EM, Z> for ClosureStage<CB, E, EM, Z>
where
CB: FnMut(&mut Z, &mut E, &mut E::State, &mut EM, CorpusId) -> Result<(), Error>,
E: UsesState,
EM: UsesState<State = E::State>,
Z: UsesState<State = E::State>,
{
fn perform(
&mut self,
fuzzer: &mut Z,
executor: &mut E,
state: &mut E::State,
manager: &mut EM,
corpus_idx: CorpusId,
) -> Result<(), Error> {
(self.closure)(fuzzer, executor, state, manager, corpus_idx)
}
}
impl<CB, E, EM, Z> ClosureStage<CB, E, EM, Z>
where
CB: FnMut(&mut Z, &mut E, &mut E::State, &mut EM, CorpusId) -> Result<(), Error>,
E: UsesState,
{
#[must_use]
pub fn new(closure: CB) -> Self {
Self {
closure,
phantom: PhantomData,
}
}
}
impl<CB, E, EM, Z> From<CB> for ClosureStage<CB, E, EM, Z>
where
CB: FnMut(&mut Z, &mut E, &mut E::State, &mut EM, CorpusId) -> Result<(), Error>,
E: UsesState,
{
#[must_use]
fn from(closure: CB) -> Self {
Self::new(closure)
}
}
#[allow(clippy::type_complexity)]
#[derive(Debug)]
pub struct PushStageAdapter<CS, EM, OT, PS, Z> {
push_stage: PS,
phantom: PhantomData<(CS, EM, OT, Z)>,
}
impl<CS, EM, OT, PS, Z> PushStageAdapter<CS, EM, OT, PS, Z> {
#[must_use]
pub fn new(push_stage: PS) -> Self {
Self {
push_stage,
phantom: PhantomData,
}
}
}
impl<CS, EM, OT, PS, Z> UsesState for PushStageAdapter<CS, EM, OT, PS, Z>
where
CS: UsesState,
{
type State = CS::State;
}
impl<CS, E, EM, OT, PS, Z> Stage<E, EM, Z> for PushStageAdapter<CS, EM, OT, PS, Z>
where
CS: Scheduler,
CS::State: HasClientPerfMonitor + HasExecutions + HasMetadata + HasRand,
E: Executor<EM, Z> + HasObservers<Observers = OT, State = CS::State>,
EM: EventFirer<State = CS::State>
+ EventRestarter
+ HasEventManagerId
+ ProgressReporter<State = CS::State>,
OT: ObserversTuple<CS::State>,
PS: PushStage<CS, EM, OT, Z>,
Z: ExecutesInput<E, EM, State = CS::State>
+ ExecutionProcessor<OT, State = CS::State>
+ EvaluatorObservers<OT>
+ HasScheduler<Scheduler = CS>,
{
fn perform(
&mut self,
fuzzer: &mut Z,
executor: &mut E,
state: &mut CS::State,
event_mgr: &mut EM,
corpus_idx: CorpusId,
) -> Result<(), Error> {
let push_stage = &mut self.push_stage;
push_stage.set_current_corpus_idx(corpus_idx);
push_stage.init(fuzzer, state, event_mgr, executor.observers_mut())?;
loop {
let input =
match push_stage.pre_exec(fuzzer, state, event_mgr, executor.observers_mut()) {
Some(Ok(next_input)) => next_input,
Some(Err(err)) => return Err(err),
None => break,
};
let exit_kind = fuzzer.execute_input(state, executor, event_mgr, &input)?;
push_stage.post_exec(
fuzzer,
state,
event_mgr,
executor.observers_mut(),
input,
exit_kind,
)?;
}
self.push_stage
.deinit(fuzzer, state, event_mgr, executor.observers_mut())
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum SkippableStageDecision {
Perform,
Skip,
}
impl From<bool> for SkippableStageDecision {
fn from(b: bool) -> SkippableStageDecision {
if b {
SkippableStageDecision::Perform
} else {
SkippableStageDecision::Skip
}
}
}
#[derive(Debug, Clone)]
pub struct SkippableStage<CD, E, EM, ST, Z> {
wrapped_stage: ST,
condition: CD,
phantom: PhantomData<(E, EM, Z)>,
}
impl<CD, E, EM, ST, Z> SkippableStage<CD, E, EM, ST, Z>
where
CD: FnMut(&mut ST::State) -> SkippableStageDecision,
ST: Stage<E, EM, Z>,
E: UsesState<State = ST::State>,
EM: UsesState<State = ST::State>,
Z: UsesState<State = ST::State>,
{
pub fn new(wrapped_stage: ST, condition: CD) -> Self {
Self {
wrapped_stage,
condition,
phantom: PhantomData,
}
}
}
impl<CD, E, EM, ST, Z> UsesState for SkippableStage<CD, E, EM, ST, Z>
where
CD: FnMut(&mut ST::State) -> SkippableStageDecision,
ST: Stage<E, EM, Z>,
E: UsesState<State = ST::State>,
EM: UsesState<State = ST::State>,
Z: UsesState<State = ST::State>,
{
type State = ST::State;
}
impl<CD, E, EM, ST, Z> Stage<E, EM, Z> for SkippableStage<CD, E, EM, ST, Z>
where
CD: FnMut(&mut ST::State) -> SkippableStageDecision,
ST: Stage<E, EM, Z>,
E: UsesState<State = ST::State>,
EM: UsesState<State = ST::State>,
Z: UsesState<State = ST::State>,
{
#[inline]
fn perform(
&mut self,
fuzzer: &mut Z,
executor: &mut E,
state: &mut ST::State,
manager: &mut EM,
corpus_idx: CorpusId,
) -> Result<(), Error> {
let condition = &mut self.condition;
if condition(state) == SkippableStageDecision::Perform {
self.wrapped_stage
.perform(fuzzer, executor, state, manager, corpus_idx)
} else {
Ok(())
}
}
}
#[cfg(feature = "python")]
#[allow(missing_docs)]
pub mod pybind {
use alloc::vec::Vec;
use pyo3::prelude::*;
use crate::{
corpus::CorpusId,
events::pybind::PythonEventManager,
executors::pybind::PythonExecutor,
fuzzer::pybind::{PythonStdFuzzer, PythonStdFuzzerWrapper},
stages::{mutational::pybind::PythonStdMutationalStage, Stage, StagesTuple},
state::{
pybind::{PythonStdState, PythonStdStateWrapper},
UsesState,
},
Error,
};
#[derive(Clone, Debug)]
pub struct PyObjectStage {
inner: PyObject,
}
impl PyObjectStage {
#[must_use]
pub fn new(obj: PyObject) -> Self {
PyObjectStage { inner: obj }
}
}
impl UsesState for PyObjectStage {
type State = PythonStdState;
}
impl Stage<PythonExecutor, PythonEventManager, PythonStdFuzzer> for PyObjectStage {
#[inline]
fn perform(
&mut self,
fuzzer: &mut PythonStdFuzzer,
executor: &mut PythonExecutor,
state: &mut PythonStdState,
manager: &mut PythonEventManager,
corpus_idx: CorpusId,
) -> Result<(), Error> {
Python::with_gil(|py| -> PyResult<()> {
self.inner.call_method1(
py,
"perform",
(
PythonStdFuzzerWrapper::wrap(fuzzer),
executor.clone(),
PythonStdStateWrapper::wrap(state),
manager.clone(),
corpus_idx.0,
),
)?;
Ok(())
})?;
Ok(())
}
}
#[derive(Clone, Debug)]
pub enum PythonStageWrapper {
StdMutational(Py<PythonStdMutationalStage>),
Python(PyObjectStage),
}
#[pyclass(unsendable, name = "Stage")]
#[derive(Clone, Debug)]
pub struct PythonStage {
wrapper: PythonStageWrapper,
}
macro_rules! unwrap_me_mut {
($wrapper:expr, $name:ident, $body:block) => {
crate::unwrap_me_mut_body!($wrapper, $name, $body, PythonStageWrapper,
{ StdMutational },
{
Python(py_wrapper) => {
let $name = py_wrapper;
$body
}
}
)
};
}
#[pymethods]
impl PythonStage {
#[staticmethod]
#[must_use]
pub fn new_std_mutational(
py_std_havoc_mutations_stage: Py<PythonStdMutationalStage>,
) -> Self {
Self {
wrapper: PythonStageWrapper::StdMutational(py_std_havoc_mutations_stage),
}
}
#[staticmethod]
#[must_use]
pub fn new_py(obj: PyObject) -> Self {
Self {
wrapper: PythonStageWrapper::Python(PyObjectStage::new(obj)),
}
}
#[must_use]
pub fn unwrap_py(&self) -> Option<PyObject> {
match &self.wrapper {
PythonStageWrapper::Python(pyo) => Some(pyo.inner.clone()),
PythonStageWrapper::StdMutational(_) => None,
}
}
}
impl UsesState for PythonStage {
type State = PythonStdState;
}
impl Stage<PythonExecutor, PythonEventManager, PythonStdFuzzer> for PythonStage {
#[inline]
#[allow(clippy::let_and_return)]
fn perform(
&mut self,
fuzzer: &mut PythonStdFuzzer,
executor: &mut PythonExecutor,
state: &mut PythonStdState,
manager: &mut PythonEventManager,
corpus_idx: CorpusId,
) -> Result<(), Error> {
unwrap_me_mut!(self.wrapper, s, {
s.perform(fuzzer, executor, state, manager, corpus_idx)
})
}
}
#[derive(Clone, Debug)]
#[pyclass(unsendable, name = "StagesTuple")]
pub struct PythonStagesTuple {
list: Vec<PythonStage>,
}
#[pymethods]
impl PythonStagesTuple {
#[new]
fn new(list: Vec<PythonStage>) -> Self {
Self { list }
}
fn len(&self) -> usize {
self.list.len()
}
fn __getitem__(&self, idx: usize) -> PythonStage {
self.list[idx].clone()
}
}
impl StagesTuple<PythonExecutor, PythonEventManager, PythonStdState, PythonStdFuzzer>
for PythonStagesTuple
{
fn perform_all(
&mut self,
fuzzer: &mut PythonStdFuzzer,
executor: &mut PythonExecutor,
state: &mut PythonStdState,
manager: &mut PythonEventManager,
corpus_idx: CorpusId,
) -> Result<(), Error> {
for s in &mut self.list {
s.perform(fuzzer, executor, state, manager, corpus_idx)?;
}
Ok(())
}
}
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<PythonStage>()?;
m.add_class::<PythonStagesTuple>()?;
Ok(())
}
}