CustomBuf Events to exchange any data between fuzzers (#672)

* custom buf events

* clippy, nits

* nostd

* testcase

* maturin build

* fmt

* pybind imports cleanup

* remove unneded lifetime annotation

* docs
This commit is contained in:
Dominik Maier 2022-06-14 11:10:08 +02:00 committed by GitHub
parent a2388d4400
commit f7c997ec65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 306 additions and 132 deletions

View File

@ -1,4 +1,5 @@
use libafl;
#[cfg(target_os = "linux")]
use libafl_qemu;
use libafl_sugar;
use pyo3::prelude::*;
@ -92,10 +93,14 @@ pub fn python_module(py: Python, m: &PyModule) -> PyResult<()> {
modules.set_item("pylibafl.sugar", sugar_module)?;
#[cfg(target_os = "linux")]
let qemu_module = PyModule::new(py, "qemu")?;
#[cfg(target_os = "linux")]
libafl_qemu::python_module(py, qemu_module)?;
#[cfg(target_os = "linux")]
m.add_submodule(qemu_module)?;
#[cfg(target_os = "linux")]
modules.set_item("pylibafl.qemu", qemu_module)?;
let libafl_module = PyModule::new(py, "libafl")?;

View File

@ -137,9 +137,7 @@ where
/// ``CachedOnDiskCorpus`` Python bindings
#[cfg(feature = "python")]
pub mod pybind {
use crate::corpus::pybind::PythonCorpus;
use crate::corpus::CachedOnDiskCorpus;
use crate::inputs::BytesInput;
use crate::{corpus::pybind::PythonCorpus, corpus::CachedOnDiskCorpus, inputs::BytesInput};
use alloc::string::String;
use pyo3::prelude::*;
use serde::{Deserialize, Serialize};

View File

@ -91,9 +91,10 @@ where
/// `InMemoryCorpus` Python bindings
#[cfg(feature = "python")]
pub mod pybind {
use crate::corpus::pybind::PythonCorpus;
use crate::corpus::InMemoryCorpus;
use crate::inputs::BytesInput;
use crate::{
corpus::{pybind::PythonCorpus, InMemoryCorpus},
inputs::BytesInput,
};
use pyo3::prelude::*;
use serde::{Deserialize, Serialize};

View File

@ -56,18 +56,19 @@ where
#[cfg(feature = "python")]
#[allow(missing_docs)]
pub mod pybind {
use crate::corpus::inmemory::pybind::PythonInMemoryCorpus;
use crate::corpus::testcase::pybind::PythonTestcaseWrapper;
use crate::corpus::{Corpus, Testcase};
use crate::inputs::BytesInput;
use crate::Error;
use crate::{
corpus::{
cached::pybind::PythonCachedOnDiskCorpus, inmemory::pybind::PythonInMemoryCorpus,
ondisk::pybind::PythonOnDiskCorpus, testcase::pybind::PythonTestcaseWrapper, Corpus,
Testcase,
},
inputs::BytesInput,
Error,
};
use pyo3::prelude::*;
use serde::{Deserialize, Serialize};
use std::cell::RefCell;
use super::cached::pybind::PythonCachedOnDiskCorpus;
use super::ondisk::pybind::PythonOnDiskCorpus;
#[derive(Serialize, Deserialize, Debug, Clone)]
enum PythonCorpusWrapper {
InMemory(Py<PythonInMemoryCorpus>),

View File

@ -208,9 +208,10 @@ where
#[cfg(feature = "python")]
/// `OnDiskCorpus` Python bindings
pub mod pybind {
use crate::corpus::pybind::PythonCorpus;
use crate::corpus::OnDiskCorpus;
use crate::inputs::BytesInput;
use crate::{
corpus::{pybind::PythonCorpus, OnDiskCorpus},
inputs::BytesInput,
};
use alloc::string::String;
use pyo3::prelude::*;
use serde::{Deserialize, Serialize};

View File

@ -351,12 +351,13 @@ crate::impl_serdeany!(SchedulerTestcaseMetaData);
/// `Testcase` Python bindings
pub mod pybind {
use super::{HasMetadata, Testcase};
use crate::bolts::ownedref::OwnedPtrMut;
use crate::inputs::{BytesInput, HasBytesVec};
use crate::pybind::PythonMetadata;
use crate::{
bolts::ownedref::OwnedPtrMut,
inputs::{BytesInput, HasBytesVec},
pybind::PythonMetadata,
};
use alloc::{boxed::Box, vec::Vec};
use pyo3::prelude::*;
use pyo3::types::PyDict;
use pyo3::{prelude::*, types::PyDict};
/// `PythonTestcase` with fixed generics
pub type PythonTestcase = Testcase<BytesInput>;

View File

@ -20,7 +20,7 @@ use crate::{
},
events::{
BrokerEventResult, Event, EventConfig, EventFirer, EventManager, EventManagerId,
EventProcessor, EventRestarter, HasEventManagerId, ProgressReporter,
EventProcessor, EventRestarter, HasCustomBufHandlers, HasEventManagerId, ProgressReporter,
},
executors::{Executor, HasObservers},
fuzzer::{EvaluatorObservers, ExecutionProcessor},
@ -29,7 +29,11 @@ use crate::{
observers::ObserversTuple,
Error,
};
use alloc::string::ToString;
use alloc::{
boxed::Box,
string::{String, ToString},
vec::Vec,
};
#[cfg(feature = "std")]
use core::sync::atomic::{compiler_fence, Ordering};
use core::{marker::PhantomData, time::Duration};
@ -41,6 +45,8 @@ use std::net::{SocketAddr, ToSocketAddrs};
#[cfg(feature = "std")]
use typed_builder::TypedBuilder;
use super::{CustomBufEventResult, CustomBufHandlerFn};
/// Forward this to the client
const _LLMP_TAG_EVENT_TO_CLIENT: Tag = 0x2C11E471;
/// Only handle this in the broker
@ -228,14 +234,15 @@ where
#[cfg(feature = "std")]
println!("[LOG {}]: {}", severity_level, message);
Ok(BrokerEventResult::Handled)
} //_ => Ok(BrokerEventResult::Forward),
}
Event::CustomBuf { .. } => Ok(BrokerEventResult::Forward),
//_ => Ok(BrokerEventResult::Forward),
}
}
}
/// An [`EventManager`] that forwards all events to other attached fuzzers on shared maps or via tcp,
/// using low-level message passing, [`crate::bolts::llmp`].
#[derive(Debug)]
pub struct LlmpEventManager<I, OT, S, SP>
where
I: Input,
@ -244,12 +251,33 @@ where
//CE: CustomEvent<I>,
{
llmp: LlmpClient<SP>,
/// The custom buf handler
custom_buf_handlers: Vec<Box<CustomBufHandlerFn<S>>>,
#[cfg(feature = "llmp_compression")]
compressor: GzipCompressor,
configuration: EventConfig,
phantom: PhantomData<(I, OT, S)>,
}
impl<I, OT, S, SP> core::fmt::Debug for LlmpEventManager<I, OT, S, SP>
where
I: Input,
OT: ObserversTuple<I, S>,
SP: ShMemProvider + 'static,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut debug_struct = f.debug_struct("LlmpEventManager");
let debug = debug_struct.field("llmp", &self.llmp);
//.field("custom_buf_handlers", &self.custom_buf_handlers)
#[cfg(feature = "llmp_compression")]
let debug = debug.field("compressor", &self.compressor);
debug
.field("configuration", &self.configuration)
.field("phantom", &self.phantom)
.finish_non_exhaustive()
}
}
impl<I, OT, S, SP> Drop for LlmpEventManager<I, OT, S, SP>
where
I: Input,
@ -276,6 +304,7 @@ where
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
configuration,
phantom: PhantomData,
custom_buf_handlers: vec![],
})
}
@ -294,6 +323,7 @@ where
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
configuration,
phantom: PhantomData,
custom_buf_handlers: vec![],
})
}
@ -310,6 +340,7 @@ where
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
configuration,
phantom: PhantomData,
custom_buf_handlers: vec![],
})
}
@ -330,6 +361,7 @@ where
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
configuration,
phantom: PhantomData,
custom_buf_handlers: vec![],
})
}
@ -384,6 +416,14 @@ where
}
Ok(())
}
Event::CustomBuf { tag, buf } => {
for handler in &mut self.custom_buf_handlers {
if handler(state, &tag, &buf)? == CustomBufEventResult::Handled {
break;
}
}
Ok(())
}
_ => Err(Error::unknown(format!(
"Received illegal message that message should not have arrived: {:?}.",
event.name()
@ -496,6 +536,20 @@ where
{
}
impl<I, OT, S, SP> HasCustomBufHandlers<S> for LlmpEventManager<I, OT, S, SP>
where
I: Input,
OT: ObserversTuple<I, S>,
SP: ShMemProvider,
{
fn add_custom_buf_handler(
&mut self,
handler: Box<dyn FnMut(&mut S, &String, &[u8]) -> Result<CustomBufEventResult, Error>>,
) {
self.custom_buf_handlers.push(handler);
}
}
impl<I, OT, S, SP> ProgressReporter<I> for LlmpEventManager<I, OT, S, SP>
where
I: Input,

View File

@ -7,6 +7,7 @@ pub use llmp::*;
use ahash::AHasher;
use alloc::{
boxed::Box,
string::{String, ToString},
vec::Vec,
};
@ -36,8 +37,6 @@ pub struct EventManagerId {
#[cfg(feature = "introspection")]
use crate::monitors::ClientPerfMonitor;
#[cfg(feature = "introspection")]
use alloc::boxed::Box;
/// The log event severity
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
@ -63,6 +62,15 @@ impl fmt::Display for LogSeverity {
}
}
/// The result of a custom buf handler added using [`HasCustomBufHandlers::add_custom_buf_handler`]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CustomBufEventResult {
/// Exit early from event handling
Handled,
/// Call the next handler, if available
Next,
}
/// Indicate if an event worked or not
#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
pub enum BrokerEventResult {
@ -231,6 +239,13 @@ where
/// `PhantomData`
phantom: PhantomData<I>,
},
/// Sends a custom buffer to other clients
CustomBuf {
/// The buffer
buf: Vec<u8>,
/// Tag of this buffer
tag: String,
},
/*/// A custom type
Custom {
// TODO: Allow custom events
@ -270,12 +285,13 @@ where
introspection_monitor: _,
phantom: _,
} => "PerfMonitor",
Event::Objective { objective_size: _ } => "Objective",
Event::Objective { .. } => "Objective",
Event::Log {
severity_level: _,
message: _,
phantom: _,
} => "Log",
Event::CustomBuf { .. } => "CustomBuf",
/*Event::Custom {
sender_id: _, /*custom_event} => custom_event.name()*/
} => "todo",*/
@ -451,6 +467,16 @@ where
{
}
/// The handler function for custom buffers exchanged via [`EventManager`]
type CustomBufHandlerFn<S> =
dyn FnMut(&mut S, &String, &[u8]) -> Result<CustomBufEventResult, Error>;
/// Supports custom buf handlers to handle `CustomBuf` events.
pub trait HasCustomBufHandlers<S> {
/// Adds a custom buffer handler that will run for each incoming `CustomBuf` event.
fn add_custom_buf_handler(&mut self, handler: Box<CustomBufHandlerFn<S>>);
}
/// An eventmgr for tests, and as placeholder if you really don't need an event manager.
#[derive(Copy, Clone, Debug)]
pub struct NopEventManager {}
@ -479,6 +505,14 @@ impl<E, I, S, Z> EventProcessor<E, I, S, Z> for NopEventManager {
impl<E, I, S, Z> EventManager<E, I, S, Z> for NopEventManager where I: Input {}
impl<S> HasCustomBufHandlers<S> for NopEventManager {
fn add_custom_buf_handler(
&mut self,
_handler: Box<dyn FnMut(&mut S, &String, &[u8]) -> Result<CustomBufEventResult, Error>>,
) {
}
}
impl<I> ProgressReporter<I> for NopEventManager where I: Input {}
impl HasEventManagerId for NopEventManager {
@ -548,16 +582,17 @@ mod tests {
#[cfg(feature = "python")]
#[allow(missing_docs)]
pub mod pybind {
use crate::events::simple::pybind::PythonSimpleEventManager;
use crate::events::{
Event, EventFirer, EventManager, EventManagerId, EventProcessor, EventRestarter,
HasEventManagerId, ProgressReporter,
use crate::{
events::{
simple::pybind::PythonSimpleEventManager, Event, EventFirer, EventManager,
EventManagerId, EventProcessor, EventRestarter, HasEventManagerId, ProgressReporter,
},
executors::pybind::PythonExecutor,
fuzzer::pybind::PythonStdFuzzer,
inputs::BytesInput,
state::pybind::PythonStdState,
Error,
};
use crate::executors::pybind::PythonExecutor;
use crate::fuzzer::pybind::PythonStdFuzzer;
use crate::inputs::BytesInput;
use crate::state::pybind::PythonStdState;
use crate::Error;
use pyo3::prelude::*;
#[derive(Debug, Clone)]

View File

@ -9,9 +9,14 @@ use crate::{
monitors::Monitor,
Error,
};
use alloc::{string::ToString, vec::Vec};
use alloc::{
boxed::Box,
string::{String, ToString},
vec::Vec,
};
#[cfg(feature = "std")]
use core::sync::atomic::{compiler_fence, Ordering};
use core::{fmt::Debug, marker::PhantomData};
#[cfg(feature = "std")]
use serde::{de::DeserializeOwned, Serialize};
@ -23,10 +28,11 @@ use crate::bolts::os::{fork, ForkResult};
use crate::{
bolts::{shmem::ShMemProvider, staterestore::StateRestorer},
corpus::Corpus,
executors::Executor,
state::{HasCorpus, HasSolutions},
};
use super::ProgressReporter;
use super::{CustomBufEventResult, CustomBufHandlerFn, HasCustomBufHandlers, ProgressReporter};
/// The llmp connection from the actual fuzzer to the process supervising it
const _ENV_FUZZER_SENDER: &str = "_AFL_ENV_FUZZER_SENDER";
@ -35,24 +41,40 @@ const _ENV_FUZZER_RECEIVER: &str = "_AFL_ENV_FUZZER_RECEIVER";
const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = "_AFL_ENV_FUZZER_BROKER_CLIENT";
/// A simple, single-threaded event manager that just logs
#[derive(Clone, Debug)]
pub struct SimpleEventManager<I, MT>
pub struct SimpleEventManager<I, MT, S>
where
I: Input,
MT: Monitor, //CE: CustomEvent<I, OT>,
MT: Monitor + Debug, //CE: CustomEvent<I, OT>,
{
/// The monitor
monitor: MT,
/// The events that happened since the last handle_in_broker
events: Vec<Event<I>>,
/// The custom buf handler
custom_buf_handlers: Vec<Box<CustomBufHandlerFn<S>>>,
phantom: PhantomData<S>,
}
impl<I, MT> EventFirer<I> for SimpleEventManager<I, MT>
impl<I, MT, S> Debug for SimpleEventManager<I, MT, S>
where
I: Input,
MT: Monitor, //CE: CustomEvent<I, OT>,
MT: Monitor + Debug,
{
fn fire<S>(&mut self, _state: &mut S, event: Event<I>) -> Result<(), Error> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("SimpleEventManager")
//.field("custom_buf_handlers", self.custom_buf_handlers)
.field("monitor", &self.monitor)
.field("events", &self.events)
.finish_non_exhaustive()
}
}
impl<I, MT, S> EventFirer<I> for SimpleEventManager<I, MT, S>
where
I: Input,
MT: Monitor + Debug, //CE: CustomEvent<I, OT>,
{
fn fire<S2>(&mut self, _state: &mut S2, event: Event<I>) -> Result<(), Error> {
match Self::handle_in_broker(&mut self.monitor, &event)? {
BrokerEventResult::Forward => self.events.push(event),
BrokerEventResult::Handled => (),
@ -61,17 +83,17 @@ where
}
}
impl<I, MT, S> EventRestarter<S> for SimpleEventManager<I, MT>
impl<I, MT, S> EventRestarter<S> for SimpleEventManager<I, MT, S>
where
I: Input,
MT: Monitor, //CE: CustomEvent<I, OT>,
MT: Monitor + Debug, //CE: CustomEvent<I, OT>,
{
}
impl<E, I, MT, S, Z> EventProcessor<E, I, S, Z> for SimpleEventManager<I, MT>
impl<E, I, MT, S, Z> EventProcessor<E, I, S, Z> for SimpleEventManager<I, MT, S>
where
I: Input,
MT: Monitor, //CE: CustomEvent<I, OT>,
MT: Monitor + Debug, //CE: CustomEvent<I, OT>,
{
fn process(
&mut self,
@ -88,44 +110,60 @@ where
}
}
impl<E, I, MT, S, Z> EventManager<E, I, S, Z> for SimpleEventManager<I, MT>
impl<E, I, MT, S, Z> EventManager<E, I, S, Z> for SimpleEventManager<I, MT, S>
where
I: Input,
MT: Monitor, //CE: CustomEvent<I, OT>,
MT: Monitor + Debug, //CE: CustomEvent<I, OT>,
{
}
impl<I, MT> ProgressReporter<I> for SimpleEventManager<I, MT>
impl<I, MT, S> HasCustomBufHandlers<S> for SimpleEventManager<I, MT, S>
where
I: Input,
MT: Monitor, //CE: CustomEvent<I, OT>,
MT: Monitor + Debug, //CE: CustomEvent<I, OT>,
{
/// Adds a custom buffer handler that will run for each incoming `CustomBuf` event.
fn add_custom_buf_handler(
&mut self,
handler: Box<dyn FnMut(&mut S, &String, &[u8]) -> Result<CustomBufEventResult, Error>>,
) {
self.custom_buf_handlers.push(handler);
}
}
impl<I, MT, S> ProgressReporter<I> for SimpleEventManager<I, MT, S>
where
I: Input,
MT: Monitor + Debug, //CE: CustomEvent<I, OT>,
{
}
impl<I, MT> HasEventManagerId for SimpleEventManager<I, MT>
impl<I, MT, S> HasEventManagerId for SimpleEventManager<I, MT, S>
where
I: Input,
MT: Monitor,
MT: Monitor + Debug,
{
fn mgr_id(&self) -> EventManagerId {
EventManagerId { id: 0 }
}
}
impl<I, MT> SimpleEventManager<I, MT>
impl<I, MT, S> SimpleEventManager<I, MT, S>
where
I: Input,
MT: Monitor, //TODO CE: CustomEvent,
MT: Monitor + Debug, //TODO CE: CustomEvent,
{
/// Creates a new [`SimpleEventManager`].
pub fn new(monitor: MT) -> Self {
Self {
monitor,
events: vec![],
custom_buf_handlers: vec![],
phantom: PhantomData,
}
}
// Handle arriving events in the broker
/// Handle arriving events in the broker
#[allow(clippy::unnecessary_wraps)]
fn handle_in_broker(monitor: &mut MT, event: &Event<I>) -> Result<BrokerEventResult, Error> {
match event {
@ -201,17 +239,26 @@ where
#[cfg(feature = "std")]
println!("[LOG {}]: {}", severity_level, message);
Ok(BrokerEventResult::Handled)
} //_ => Ok(BrokerEventResult::Forward),
}
Event::CustomBuf { .. } => Ok(BrokerEventResult::Forward),
//_ => Ok(BrokerEventResult::Forward),
}
}
// Handle arriving events in the client
#[allow(clippy::needless_pass_by_value, clippy::unused_self)]
fn handle_in_client<S>(&mut self, _state: &mut S, event: Event<I>) -> Result<(), Error> {
Err(Error::unknown(format!(
"Received illegal message that message should not have arrived: {:?}.",
event
)))
fn handle_in_client(&mut self, state: &mut S, event: Event<I>) -> Result<(), Error> {
if let Event::CustomBuf { tag, buf } = &event {
for handler in &mut self.custom_buf_handlers {
handler(state, tag, buf)?;
}
Ok(())
} else {
Err(Error::unknown(format!(
"Received illegal message that message should not have arrived: {:?}.",
event
)))
}
}
}
@ -220,25 +267,25 @@ where
/// `restarter` will start a new process each time the child crashes or times out.
#[cfg(feature = "std")]
#[allow(clippy::default_trait_access)]
#[derive(Debug, Clone)]
pub struct SimpleRestartingEventManager<I, MT, SP>
#[derive(Debug)]
pub struct SimpleRestartingEventManager<I, MT, S, SP>
where
I: Input,
SP: ShMemProvider,
MT: Monitor, //CE: CustomEvent<I, OT>,
MT: Monitor + Debug, //CE: CustomEvent<I, OT>,
{
/// The actual simple event mgr
simple_event_mgr: SimpleEventManager<I, MT>,
simple_event_mgr: SimpleEventManager<I, MT, S>,
/// [`StateRestorer`] for restarts
staterestorer: StateRestorer<SP>,
}
#[cfg(feature = "std")]
impl<I, MT, SP> EventFirer<I> for SimpleRestartingEventManager<I, MT, SP>
impl<I, MT, S, SP> EventFirer<I> for SimpleRestartingEventManager<I, MT, S, SP>
where
I: Input,
SP: ShMemProvider,
MT: Monitor, //CE: CustomEvent<I, OT>,
MT: Monitor + Debug, //CE: CustomEvent<I, OT>,
{
fn fire<S2>(&mut self, _state: &mut S2, event: Event<I>) -> Result<(), Error> {
self.simple_event_mgr.fire(_state, event)
@ -246,12 +293,12 @@ where
}
#[cfg(feature = "std")]
impl<I, MT, S, SP> EventRestarter<S> for SimpleRestartingEventManager<I, MT, SP>
impl<I, MT, S, SP> EventRestarter<S> for SimpleRestartingEventManager<I, MT, S, SP>
where
I: Input,
S: Serialize,
SP: ShMemProvider,
MT: Monitor, //CE: CustomEvent<I, OT>,
MT: Monitor + Debug, //CE: CustomEvent<I, OT>,
{
/// Reset the single page (we reuse it over and over from pos 0), then send the current state to the next runner.
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
@ -262,12 +309,12 @@ where
}
#[cfg(feature = "std")]
impl<E, I, S, SP, MT, Z> EventProcessor<E, I, S, Z> for SimpleRestartingEventManager<I, MT, SP>
impl<E, I, S, SP, MT, Z> EventProcessor<E, I, S, Z> for SimpleRestartingEventManager<I, MT, S, SP>
where
I: Input,
S: Serialize,
SP: ShMemProvider,
MT: Monitor, //CE: CustomEvent<I, OT>,
MT: Monitor + Debug, //CE: CustomEvent<I, OT>,
{
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
self.simple_event_mgr.process(fuzzer, state, executor)
@ -275,30 +322,46 @@ where
}
#[cfg(feature = "std")]
impl<E, I, S, SP, MT, Z> EventManager<E, I, S, Z> for SimpleRestartingEventManager<I, MT, SP>
impl<E, I, S, SP, MT, Z> EventManager<E, I, S, Z> for SimpleRestartingEventManager<I, MT, S, SP>
where
E: Executor<Self, I, S, Z>,
I: Input,
S: Serialize,
SP: ShMemProvider,
MT: Monitor, //CE: CustomEvent<I, OT>,
MT: Monitor + Debug, //CE: CustomEvent<I, OT>,
{
}
#[cfg(feature = "std")]
impl<I, MT, SP> ProgressReporter<I> for SimpleRestartingEventManager<I, MT, SP>
impl<I, MT, S, SP> HasCustomBufHandlers<S> for SimpleRestartingEventManager<I, MT, S, SP>
where
I: Input,
SP: ShMemProvider,
MT: Monitor, //CE: CustomEvent<I, OT>,
MT: Monitor + Debug, //CE: CustomEvent<I, OT>,
{
fn add_custom_buf_handler(
&mut self,
handler: Box<dyn FnMut(&mut S, &String, &[u8]) -> Result<CustomBufEventResult, Error>>,
) {
self.simple_event_mgr.add_custom_buf_handler(handler);
}
}
#[cfg(feature = "std")]
impl<I, MT, S, SP> ProgressReporter<I> for SimpleRestartingEventManager<I, MT, S, SP>
where
I: Input,
SP: ShMemProvider,
MT: Monitor + Debug, //CE: CustomEvent<I, OT>,
{
}
#[cfg(feature = "std")]
impl<I, MT, SP> HasEventManagerId for SimpleRestartingEventManager<I, MT, SP>
impl<I, MT, S, SP> HasEventManagerId for SimpleRestartingEventManager<I, MT, S, SP>
where
I: Input,
SP: ShMemProvider,
MT: Monitor,
MT: Monitor + Debug,
{
fn mgr_id(&self) -> EventManagerId {
self.simple_event_mgr.mgr_id()
@ -307,11 +370,11 @@ where
#[cfg(feature = "std")]
#[allow(clippy::type_complexity, clippy::too_many_lines)]
impl<I, MT, SP> SimpleRestartingEventManager<I, MT, SP>
impl<I, MT, S, SP> SimpleRestartingEventManager<I, MT, S, SP>
where
I: Input,
SP: ShMemProvider,
MT: Monitor, //TODO CE: CustomEvent,
MT: Monitor + Debug, //TODO CE: CustomEvent,
{
/// Creates a new [`SimpleEventManager`].
fn new_launched(monitor: MT, staterestorer: StateRestorer<SP>) -> Self {
@ -325,9 +388,10 @@ where
/// This [`EventManager`] is simple and single threaded,
/// but can still used shared maps to recover from crashes and timeouts.
#[allow(clippy::similar_names)]
pub fn launch<S>(mut monitor: MT, shmem_provider: &mut SP) -> Result<(Option<S>, Self), Error>
pub fn launch(mut monitor: MT, shmem_provider: &mut SP) -> Result<(Option<S>, Self), Error>
where
S: DeserializeOwned + Serialize + HasCorpus<I> + HasSolutions<I>,
MT: Debug,
{
// We start ourself as child process to actually fuzz
let mut staterestorer = if std::env::var(_ENV_FUZZER_SENDER).is_err() {
@ -430,18 +494,18 @@ where
#[cfg(feature = "python")]
#[allow(missing_docs)]
pub mod pybind {
use crate::events::pybind::PythonEventManager;
use crate::events::SimpleEventManager;
use crate::inputs::BytesInput;
use crate::monitors::pybind::PythonMonitor;
use crate::{
events::pybind::PythonEventManager, events::SimpleEventManager, inputs::BytesInput,
monitors::pybind::PythonMonitor, state::pybind::PythonStdState,
};
use pyo3::prelude::*;
#[pyclass(unsendable, name = "SimpleEventManager")]
#[derive(Debug, Clone)]
#[derive(Debug)]
/// Python class for SimpleEventManager
pub struct PythonSimpleEventManager {
/// Rust wrapped SimpleEventManager object
pub inner: SimpleEventManager<BytesInput, PythonMonitor>,
pub inner: SimpleEventManager<BytesInput, PythonMonitor, PythonStdState>,
}
#[pymethods]

View File

@ -674,7 +674,7 @@ mod tests {
#[test]
#[cfg(unix)]
fn test_builder() {
let mut mgr = SimpleEventManager::<BytesInput, _>::new(SimpleMonitor::new(|status| {
let mut mgr = SimpleEventManager::<BytesInput, _, ()>::new(SimpleMonitor::new(|status| {
println!("{}", status);
}));
@ -700,7 +700,7 @@ mod tests {
fn test_parse_afl_cmdline() {
use alloc::string::ToString;
let mut mgr = SimpleEventManager::<BytesInput, _>::new(SimpleMonitor::new(|status| {
let mut mgr = SimpleEventManager::<BytesInput, _, ()>::new(SimpleMonitor::new(|status| {
println!("{}", status);
}));

View File

@ -1689,16 +1689,16 @@ mod tests {
#[allow(missing_docs)]
/// `InProcess` Python bindings
pub mod pybind {
use crate::events::pybind::PythonEventManager;
use crate::executors::pybind::PythonExecutor;
use crate::executors::{inprocess::OwnedInProcessExecutor, ExitKind};
use crate::fuzzer::pybind::PythonStdFuzzerWrapper;
use crate::inputs::{BytesInput, HasBytesVec};
use crate::observers::pybind::PythonObserversTuple;
use crate::state::pybind::{PythonStdState, PythonStdStateWrapper};
use crate::{
events::pybind::PythonEventManager,
executors::{inprocess::OwnedInProcessExecutor, pybind::PythonExecutor, ExitKind},
fuzzer::pybind::PythonStdFuzzerWrapper,
inputs::{BytesInput, HasBytesVec},
observers::pybind::PythonObserversTuple,
state::pybind::{PythonStdState, PythonStdStateWrapper},
};
use alloc::boxed::Box;
use pyo3::prelude::*;
use pyo3::types::PyBytes;
use pyo3::{prelude::*, types::PyBytes};
#[pyclass(unsendable, name = "InProcessExecutor")]
#[derive(Debug)]

View File

@ -12,7 +12,7 @@ pub mod disk;
#[cfg(feature = "std")]
pub use disk::OnDiskTOMLMonitor;
use alloc::{string::String, vec::Vec};
use alloc::{fmt::Debug, string::String, vec::Vec};
#[cfg(feature = "introspection")]
use alloc::string::ToString;
@ -282,7 +282,7 @@ impl Default for NopMonitor {
}
/// Tracking monitor during fuzzing.
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct SimpleMonitor<F>
where
F: FnMut(String),
@ -292,6 +292,18 @@ where
client_stats: Vec<ClientStats>,
}
impl<F> Debug for SimpleMonitor<F>
where
F: FnMut(String),
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SimpleMonitor")
.field("start_time", &self.start_time)
.field("client_stats", &self.client_stats)
.finish()
}
}
impl<F> Monitor for SimpleMonitor<F>
where
F: FnMut(String),

View File

@ -261,13 +261,14 @@ where
#[cfg(feature = "python")]
#[allow(missing_docs)]
pub mod pybind {
use crate::events::pybind::PythonEventManager;
use crate::executors::pybind::PythonExecutor;
use crate::fuzzer::pybind::{PythonStdFuzzer, PythonStdFuzzerWrapper};
use crate::stages::mutational::pybind::PythonStdMutationalStage;
use crate::stages::{Stage, StagesTuple};
use crate::state::pybind::{PythonStdState, PythonStdStateWrapper};
use crate::Error;
use crate::{
events::pybind::PythonEventManager,
executors::pybind::PythonExecutor,
fuzzer::pybind::{PythonStdFuzzer, PythonStdFuzzerWrapper},
stages::{mutational::pybind::PythonStdMutationalStage, Stage, StagesTuple},
state::pybind::{PythonStdState, PythonStdStateWrapper},
Error,
};
use alloc::vec::Vec;
use pyo3::prelude::*;

View File

@ -166,14 +166,15 @@ where
#[allow(missing_docs)]
/// `StdMutationalStage` Python bindings
pub mod pybind {
use crate::events::pybind::PythonEventManager;
use crate::executors::pybind::PythonExecutor;
use crate::fuzzer::pybind::PythonStdFuzzer;
use crate::inputs::BytesInput;
use crate::mutators::pybind::PythonMutator;
use crate::stages::pybind::PythonStage;
use crate::stages::StdMutationalStage;
use crate::state::pybind::PythonStdState;
use crate::{
events::pybind::PythonEventManager,
executors::pybind::PythonExecutor,
fuzzer::pybind::PythonStdFuzzer,
inputs::BytesInput,
mutators::pybind::PythonMutator,
stages::{pybind::PythonStage, StdMutationalStage},
state::pybind::PythonStdState,
};
use pyo3::prelude::*;
#[pyclass(unsendable, name = "StdMutationalStage")]

View File

@ -655,22 +655,22 @@ where
#[allow(missing_docs)]
/// `State` Python bindings
pub mod pybind {
use crate::bolts::ownedref::OwnedPtrMut;
use crate::bolts::rands::pybind::PythonRand;
use crate::corpus::pybind::PythonCorpus;
use crate::events::pybind::PythonEventManager;
use crate::executors::pybind::PythonExecutor;
use crate::feedbacks::pybind::PythonFeedback;
use crate::fuzzer::pybind::PythonStdFuzzerWrapper;
use crate::generators::pybind::PythonGenerator;
use crate::inputs::BytesInput;
use crate::pybind::PythonMetadata;
use crate::state::{
HasCorpus, HasExecutions, HasMaxSize, HasMetadata, HasRand, HasSolutions, StdState,
use crate::{
bolts::{ownedref::OwnedPtrMut, rands::pybind::PythonRand},
corpus::pybind::PythonCorpus,
events::pybind::PythonEventManager,
executors::pybind::PythonExecutor,
feedbacks::pybind::PythonFeedback,
fuzzer::pybind::PythonStdFuzzerWrapper,
generators::pybind::PythonGenerator,
inputs::BytesInput,
pybind::PythonMetadata,
state::{
HasCorpus, HasExecutions, HasMaxSize, HasMetadata, HasRand, HasSolutions, StdState,
},
};
use alloc::{boxed::Box, vec::Vec};
use pyo3::prelude::*;
use pyo3::types::PyDict;
use pyo3::{prelude::*, types::PyDict};
use std::path::PathBuf;
/// `StdState` with fixed generics