Skippable stage, generator wrapper for Grimoire (#748)
* Skippable stage, generator wrapper for Grimoire * more fancy wrapper
This commit is contained in:
parent
0859c3ace2
commit
6c50f55cd2
@ -5,7 +5,7 @@ use core::{cmp::min, marker::PhantomData};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::rands::Rand,
|
bolts::rands::Rand,
|
||||||
inputs::{bytes::BytesInput, Input},
|
inputs::{bytes::BytesInput, GeneralizedInput, Input},
|
||||||
state::HasRand,
|
state::HasRand,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
@ -33,6 +33,51 @@ where
|
|||||||
fn generate_dummy(&self, state: &mut S) -> I;
|
fn generate_dummy(&self, state: &mut S) -> I;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A Generator that produces [`GeneralizedInput`]s from a wrapped [`BytesInput`] generator
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct GeneralizedInputBytesGenerator<G, S> {
|
||||||
|
bytes_generator: G,
|
||||||
|
phantom: PhantomData<S>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G, S> GeneralizedInputBytesGenerator<G, S>
|
||||||
|
where
|
||||||
|
S: HasRand,
|
||||||
|
G: Generator<BytesInput, S>,
|
||||||
|
{
|
||||||
|
/// Creates a new [`GeneralizedInputBytesGenerator`] by wrapping a bytes generator.
|
||||||
|
pub fn new(bytes_generator: G) -> Self {
|
||||||
|
Self {
|
||||||
|
bytes_generator,
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G, S> From<G> for GeneralizedInputBytesGenerator<G, S>
|
||||||
|
where
|
||||||
|
S: HasRand,
|
||||||
|
G: Generator<BytesInput, S>,
|
||||||
|
{
|
||||||
|
fn from(bytes_generator: G) -> Self {
|
||||||
|
Self::new(bytes_generator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G, S> Generator<GeneralizedInput, S> for GeneralizedInputBytesGenerator<G, S>
|
||||||
|
where
|
||||||
|
S: HasRand,
|
||||||
|
G: Generator<BytesInput, S>,
|
||||||
|
{
|
||||||
|
fn generate(&mut self, state: &mut S) -> Result<GeneralizedInput, Error> {
|
||||||
|
Ok(self.bytes_generator.generate(state)?.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_dummy(&self, state: &mut S) -> GeneralizedInput {
|
||||||
|
self.bytes_generator.generate_dummy(state).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
/// Generates random bytes
|
/// Generates random bytes
|
||||||
pub struct RandBytesGenerator<S>
|
pub struct RandBytesGenerator<S>
|
||||||
|
@ -20,7 +20,7 @@ use crate::{
|
|||||||
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, Hash)]
|
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||||
pub struct BytesInput {
|
pub struct BytesInput {
|
||||||
/// The raw input bytes
|
/// The raw input bytes
|
||||||
bytes: Vec<u8>,
|
pub(crate) bytes: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Input for BytesInput {
|
impl Input for BytesInput {
|
||||||
|
@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use crate::Error;
|
use crate::Error;
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::{ownedref::OwnedSlice, HasLen},
|
bolts::{ownedref::OwnedSlice, HasLen},
|
||||||
inputs::{HasBytesVec, HasTargetBytes, Input},
|
inputs::{BytesInput, HasBytesVec, HasTargetBytes, Input},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// An item of the generalized input
|
/// An item of the generalized input
|
||||||
@ -122,6 +122,18 @@ impl From<&[u8]> for GeneralizedInput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<BytesInput> for GeneralizedInput {
|
||||||
|
fn from(bytes_input: BytesInput) -> Self {
|
||||||
|
Self::new(bytes_input.bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&BytesInput> for GeneralizedInput {
|
||||||
|
fn from(bytes_input: &BytesInput) -> Self {
|
||||||
|
bytes_input.bytes().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl GeneralizedInput {
|
impl GeneralizedInput {
|
||||||
/// Creates a new bytes input using the given bytes
|
/// Creates a new bytes input using the given bytes
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -260,6 +260,77 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The decision if the [`SkippableStage`] should be skipped
|
||||||
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||||
|
pub enum SkippableStageDecision {
|
||||||
|
/// Return to indicate that this [`Stage`] should be executed
|
||||||
|
Perform,
|
||||||
|
/// Return to indicate that this [`Stage`] should be skipped
|
||||||
|
Skip,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<bool> for SkippableStageDecision {
|
||||||
|
fn from(b: bool) -> SkippableStageDecision {
|
||||||
|
if b {
|
||||||
|
SkippableStageDecision::Perform
|
||||||
|
} else {
|
||||||
|
SkippableStageDecision::Skip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The [`SkippableStage`] wraps any [`Stage`] so that it can be skipped, according to a condition.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct SkippableStage<CD, E, EM, S, ST, Z>
|
||||||
|
where
|
||||||
|
CD: FnMut(&mut S) -> SkippableStageDecision,
|
||||||
|
ST: Stage<E, EM, S, Z>,
|
||||||
|
{
|
||||||
|
wrapped_stage: ST,
|
||||||
|
condition: CD,
|
||||||
|
phantom: PhantomData<(E, EM, S, Z)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CD, E, EM, S, ST, Z> SkippableStage<CD, E, EM, S, ST, Z>
|
||||||
|
where
|
||||||
|
CD: FnMut(&mut S) -> SkippableStageDecision,
|
||||||
|
ST: Stage<E, EM, S, Z>,
|
||||||
|
{
|
||||||
|
/// Create a new [`SkippableStage`]
|
||||||
|
pub fn new(wrapped_stage: ST, condition: CD) -> Self {
|
||||||
|
Self {
|
||||||
|
wrapped_stage,
|
||||||
|
condition,
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CD, E, EM, S, ST, Z> Stage<E, EM, S, Z> for SkippableStage<CD, E, EM, S, ST, Z>
|
||||||
|
where
|
||||||
|
CD: FnMut(&mut S) -> SkippableStageDecision,
|
||||||
|
ST: Stage<E, EM, S, Z>,
|
||||||
|
{
|
||||||
|
/// Run the stage
|
||||||
|
#[inline]
|
||||||
|
fn perform(
|
||||||
|
&mut self,
|
||||||
|
fuzzer: &mut Z,
|
||||||
|
executor: &mut E,
|
||||||
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
|
corpus_idx: usize,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let condition = &mut self.condition;
|
||||||
|
if condition(state) == SkippableStageDecision::Perform {
|
||||||
|
self.wrapped_stage
|
||||||
|
.perform(fuzzer, executor, state, manager, corpus_idx)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// `Stage` Python bindings
|
/// `Stage` Python bindings
|
||||||
#[cfg(feature = "python")]
|
#[cfg(feature = "python")]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user