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:
parent
a2388d4400
commit
f7c997ec65
@ -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")?;
|
||||
|
@ -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};
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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>),
|
||||
|
@ -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};
|
||||
|
@ -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>;
|
||||
|
@ -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,
|
||||
|
@ -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)]
|
||||
|
@ -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,44 +239,53 @@ 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> {
|
||||
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
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides a `builder` which can be used to build a [`SimpleRestartingEventManager`], which is a combination of a
|
||||
/// `restarter` and `runner`, that can be used on systems both with and without `fork` support. The
|
||||
/// `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]
|
||||
|
@ -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);
|
||||
}));
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -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),
|
||||
|
@ -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::*;
|
||||
|
||||
|
@ -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")]
|
||||
|
@ -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::{
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user