parent
751330e8ee
commit
5605f233fc
@ -53,10 +53,8 @@ where
|
|||||||
harness_fn: &'a mut H,
|
harness_fn: &'a mut H,
|
||||||
/// The observers, observing each run
|
/// The observers, observing each run
|
||||||
observers: OT,
|
observers: OT,
|
||||||
/// On crash C function pointer
|
// Crash and timeout hah
|
||||||
crash_handler: *const c_void,
|
handlers: InProcessHandlers,
|
||||||
/// On timeout C function pointer
|
|
||||||
timeout_handler: *const c_void,
|
|
||||||
phantom: PhantomData<(I, S)>,
|
phantom: PhantomData<(I, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,59 +67,15 @@ where
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn run_target(
|
fn run_target(
|
||||||
&mut self,
|
&mut self,
|
||||||
_fuzzer: &mut Z,
|
fuzzer: &mut Z,
|
||||||
_state: &mut S,
|
state: &mut S,
|
||||||
_mgr: &mut EM,
|
mgr: &mut EM,
|
||||||
input: &I,
|
input: &I,
|
||||||
) -> Result<ExitKind, Error> {
|
) -> Result<ExitKind, Error> {
|
||||||
#[cfg(unix)]
|
self.handlers
|
||||||
unsafe {
|
.pre_run_target(self, fuzzer, state, mgr, input);
|
||||||
let data = &mut GLOBAL_STATE;
|
|
||||||
write_volatile(
|
|
||||||
&mut data.current_input_ptr,
|
|
||||||
input as *const _ as *const c_void,
|
|
||||||
);
|
|
||||||
write_volatile(&mut data.executor_ptr, self as *const _ as *const c_void);
|
|
||||||
data.crash_handler = self.crash_handler;
|
|
||||||
data.timeout_handler = self.timeout_handler;
|
|
||||||
// Direct raw pointers access /aliasing is pretty undefined behavior.
|
|
||||||
// Since the state and event may have moved in memory, refresh them right before the signal may happen
|
|
||||||
write_volatile(&mut data.state_ptr, _state as *mut _ as *mut c_void);
|
|
||||||
write_volatile(&mut data.event_mgr_ptr, _mgr as *mut _ as *mut c_void);
|
|
||||||
write_volatile(&mut data.fuzzer_ptr, _fuzzer as *mut _ as *mut c_void);
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
}
|
|
||||||
#[cfg(all(windows, feature = "std"))]
|
|
||||||
unsafe {
|
|
||||||
let data = &mut GLOBAL_STATE;
|
|
||||||
write_volatile(
|
|
||||||
&mut data.current_input_ptr,
|
|
||||||
input as *const _ as *const c_void,
|
|
||||||
);
|
|
||||||
write_volatile(&mut data.executor_ptr, self as *const _ as *const c_void);
|
|
||||||
data.crash_handler = self.crash_handler;
|
|
||||||
data.timeout_handler = self.timeout_handler;
|
|
||||||
// Direct raw pointers access /aliasing is pretty undefined behavior.
|
|
||||||
// Since the state and event may have moved in memory, refresh them right before the signal may happen
|
|
||||||
write_volatile(&mut data.state_ptr, _state as *mut _ as *mut c_void);
|
|
||||||
write_volatile(&mut data.event_mgr_ptr, _mgr as *mut _ as *mut c_void);
|
|
||||||
write_volatile(&mut data.fuzzer_ptr, _fuzzer as *mut _ as *mut c_void);
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
}
|
|
||||||
|
|
||||||
let ret = (self.harness_fn)(input);
|
let ret = (self.harness_fn)(input);
|
||||||
|
self.handlers.post_run_target();
|
||||||
#[cfg(unix)]
|
|
||||||
unsafe {
|
|
||||||
write_volatile(&mut GLOBAL_STATE.current_input_ptr, ptr::null());
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
}
|
|
||||||
#[cfg(all(windows, feature = "std"))]
|
|
||||||
unsafe {
|
|
||||||
write_volatile(&mut GLOBAL_STATE.current_input_ptr, ptr::null());
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -169,77 +123,11 @@ where
|
|||||||
S: HasSolutions<OC, I> + HasClientPerfMonitor,
|
S: HasSolutions<OC, I> + HasClientPerfMonitor,
|
||||||
Z: HasObjective<I, OF, S>,
|
Z: HasObjective<I, OF, S>,
|
||||||
{
|
{
|
||||||
#[cfg(unix)]
|
let handlers = InProcessHandlers::new::<Self, EM, I, OC, OF, OT, S, Z>()?;
|
||||||
unsafe {
|
|
||||||
let data = &mut GLOBAL_STATE;
|
|
||||||
setup_signal_handler(data)?;
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
harness_fn,
|
harness_fn,
|
||||||
observers,
|
observers,
|
||||||
crash_handler: unix_signal_handler::inproc_crash_handler::<
|
handlers,
|
||||||
Self,
|
|
||||||
EM,
|
|
||||||
I,
|
|
||||||
OC,
|
|
||||||
OF,
|
|
||||||
OT,
|
|
||||||
S,
|
|
||||||
Z,
|
|
||||||
> as *const _,
|
|
||||||
timeout_handler: unix_signal_handler::inproc_timeout_handler::<
|
|
||||||
Self,
|
|
||||||
EM,
|
|
||||||
I,
|
|
||||||
OC,
|
|
||||||
OF,
|
|
||||||
OT,
|
|
||||||
S,
|
|
||||||
Z,
|
|
||||||
> as *const _,
|
|
||||||
phantom: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
#[cfg(all(windows, feature = "std"))]
|
|
||||||
unsafe {
|
|
||||||
let data = &mut GLOBAL_STATE;
|
|
||||||
setup_exception_handler(data)?;
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
harness_fn,
|
|
||||||
observers,
|
|
||||||
crash_handler: windows_exception_handler::inproc_crash_handler::<
|
|
||||||
Self,
|
|
||||||
EM,
|
|
||||||
I,
|
|
||||||
OC,
|
|
||||||
OF,
|
|
||||||
OT,
|
|
||||||
S,
|
|
||||||
Z,
|
|
||||||
> as *const _,
|
|
||||||
timeout_handler: windows_exception_handler::inproc_timeout_handler::<
|
|
||||||
Self,
|
|
||||||
EM,
|
|
||||||
I,
|
|
||||||
OC,
|
|
||||||
OF,
|
|
||||||
OT,
|
|
||||||
S,
|
|
||||||
Z,
|
|
||||||
> as *const c_void,
|
|
||||||
// timeout_handler: ptr::null(),
|
|
||||||
phantom: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
#[cfg(not(any(unix, all(windows, feature = "std"))))]
|
|
||||||
Ok(Self {
|
|
||||||
harness_fn,
|
|
||||||
observers,
|
|
||||||
crash_handler: ptr::null(),
|
|
||||||
timeout_handler: ptr::null(),
|
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -257,6 +145,157 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct InProcessHandlers {
|
||||||
|
/// On crash C function pointer
|
||||||
|
crash_handler: *const c_void,
|
||||||
|
/// On timeout C function pointer
|
||||||
|
timeout_handler: *const c_void,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InProcessHandlers {
|
||||||
|
pub fn pre_run_target<E, EM, I, S, Z>(
|
||||||
|
&self,
|
||||||
|
executor: &E,
|
||||||
|
fuzzer: &mut Z,
|
||||||
|
state: &mut S,
|
||||||
|
mgr: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
) {
|
||||||
|
#[cfg(unix)]
|
||||||
|
unsafe {
|
||||||
|
let data = &mut GLOBAL_STATE;
|
||||||
|
write_volatile(
|
||||||
|
&mut data.current_input_ptr,
|
||||||
|
input as *const _ as *const c_void,
|
||||||
|
);
|
||||||
|
write_volatile(
|
||||||
|
&mut data.executor_ptr,
|
||||||
|
executor as *const _ as *const c_void,
|
||||||
|
);
|
||||||
|
data.crash_handler = self.crash_handler;
|
||||||
|
data.timeout_handler = self.timeout_handler;
|
||||||
|
// Direct raw pointers access /aliasing is pretty undefined behavior.
|
||||||
|
// Since the state and event may have moved in memory, refresh them right before the signal may happen
|
||||||
|
write_volatile(&mut data.state_ptr, state as *mut _ as *mut c_void);
|
||||||
|
write_volatile(&mut data.event_mgr_ptr, mgr as *mut _ as *mut c_void);
|
||||||
|
write_volatile(&mut data.fuzzer_ptr, fuzzer as *mut _ as *mut c_void);
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
#[cfg(all(windows, feature = "std"))]
|
||||||
|
unsafe {
|
||||||
|
let data = &mut GLOBAL_STATE;
|
||||||
|
write_volatile(
|
||||||
|
&mut data.current_input_ptr,
|
||||||
|
input as *const _ as *const c_void,
|
||||||
|
);
|
||||||
|
write_volatile(
|
||||||
|
&mut data.executor_ptr,
|
||||||
|
executor as *const _ as *const c_void,
|
||||||
|
);
|
||||||
|
data.crash_handler = self.crash_handler;
|
||||||
|
data.timeout_handler = self.timeout_handler;
|
||||||
|
// Direct raw pointers access /aliasing is pretty undefined behavior.
|
||||||
|
// Since the state and event may have moved in memory, refresh them right before the signal may happen
|
||||||
|
write_volatile(&mut data.state_ptr, state as *mut _ as *mut c_void);
|
||||||
|
write_volatile(&mut data.event_mgr_ptr, mgr as *mut _ as *mut c_void);
|
||||||
|
write_volatile(&mut data.fuzzer_ptr, fuzzer as *mut _ as *mut c_void);
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::unused_self)]
|
||||||
|
pub fn post_run_target(&self) {
|
||||||
|
#[cfg(unix)]
|
||||||
|
unsafe {
|
||||||
|
write_volatile(&mut GLOBAL_STATE.current_input_ptr, ptr::null());
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
#[cfg(all(windows, feature = "std"))]
|
||||||
|
unsafe {
|
||||||
|
write_volatile(&mut GLOBAL_STATE.current_input_ptr, ptr::null());
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn new<E, EM, I, OC, OF, OT, S, Z>() -> Result<Self, Error>
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
E: HasObservers<I, OT, S>,
|
||||||
|
OT: ObserversTuple<I, S>,
|
||||||
|
EM: EventFirer<I> + EventRestarter<S>,
|
||||||
|
OC: Corpus<I>,
|
||||||
|
OF: Feedback<I, S>,
|
||||||
|
S: HasSolutions<OC, I> + HasClientPerfMonitor,
|
||||||
|
Z: HasObjective<I, OF, S>,
|
||||||
|
{
|
||||||
|
#[cfg(unix)]
|
||||||
|
unsafe {
|
||||||
|
let data = &mut GLOBAL_STATE;
|
||||||
|
setup_signal_handler(data)?;
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
crash_handler: unix_signal_handler::inproc_crash_handler::<E, EM, I, OC, OF, OT, S, Z>
|
||||||
|
as *const _,
|
||||||
|
timeout_handler: unix_signal_handler::inproc_timeout_handler::<
|
||||||
|
E,
|
||||||
|
EM,
|
||||||
|
I,
|
||||||
|
OC,
|
||||||
|
OF,
|
||||||
|
OT,
|
||||||
|
S,
|
||||||
|
Z,
|
||||||
|
> as *const _,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#[cfg(all(windows, feature = "std"))]
|
||||||
|
unsafe {
|
||||||
|
let data = &mut GLOBAL_STATE;
|
||||||
|
setup_exception_handler(data)?;
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
crash_handler: windows_exception_handler::inproc_crash_handler::<
|
||||||
|
E,
|
||||||
|
EM,
|
||||||
|
I,
|
||||||
|
OC,
|
||||||
|
OF,
|
||||||
|
OT,
|
||||||
|
S,
|
||||||
|
Z,
|
||||||
|
> as *const _,
|
||||||
|
timeout_handler: windows_exception_handler::inproc_timeout_handler::<
|
||||||
|
E,
|
||||||
|
EM,
|
||||||
|
I,
|
||||||
|
OC,
|
||||||
|
OF,
|
||||||
|
OT,
|
||||||
|
S,
|
||||||
|
Z,
|
||||||
|
> as *const c_void,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#[cfg(not(any(unix, all(windows, feature = "std"))))]
|
||||||
|
Ok(Self {
|
||||||
|
crash_handler: ptr::null(),
|
||||||
|
timeout_handler: ptr::null(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn nop() -> Self {
|
||||||
|
Self {
|
||||||
|
crash_handler: ptr::null(),
|
||||||
|
timeout_handler: ptr::null(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct InProcessExecutorHandlerData {
|
pub struct InProcessExecutorHandlerData {
|
||||||
pub state_ptr: *mut c_void,
|
pub state_ptr: *mut c_void,
|
||||||
pub event_mgr_ptr: *mut c_void,
|
pub event_mgr_ptr: *mut c_void,
|
||||||
@ -965,7 +1004,7 @@ where
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use core::{marker::PhantomData, ptr};
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
#[cfg(all(feature = "std", feature = "fork", unix))]
|
#[cfg(all(feature = "std", feature = "fork", unix))]
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -974,7 +1013,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::tuples::tuple_list,
|
bolts::tuples::tuple_list,
|
||||||
executors::{Executor, ExitKind, InProcessExecutor},
|
executors::{inprocess::InProcessHandlers, Executor, ExitKind, InProcessExecutor},
|
||||||
inputs::NopInput,
|
inputs::NopInput,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -985,8 +1024,7 @@ mod tests {
|
|||||||
let mut in_process_executor = InProcessExecutor::<_, NopInput, (), ()> {
|
let mut in_process_executor = InProcessExecutor::<_, NopInput, (), ()> {
|
||||||
harness_fn: &mut harness,
|
harness_fn: &mut harness,
|
||||||
observers: tuple_list!(),
|
observers: tuple_list!(),
|
||||||
crash_handler: ptr::null(),
|
handlers: InProcessHandlers::nop(),
|
||||||
timeout_handler: ptr::null(),
|
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
};
|
};
|
||||||
let input = NopInput {};
|
let input = NopInput {};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user