InProcessHandlers (#387)

* InProcessHandlers

* clippy
This commit is contained in:
Andrea Fioraldi 2021-11-17 18:32:26 +01:00 committed by GitHub
parent 751330e8ee
commit 5605f233fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -53,10 +53,8 @@ where
harness_fn: &'a mut H,
/// The observers, observing each run
observers: OT,
/// On crash C function pointer
crash_handler: *const c_void,
/// On timeout C function pointer
timeout_handler: *const c_void,
// Crash and timeout hah
handlers: InProcessHandlers,
phantom: PhantomData<(I, S)>,
}
@ -69,59 +67,15 @@ where
#[inline]
fn run_target(
&mut self,
_fuzzer: &mut Z,
_state: &mut S,
_mgr: &mut EM,
fuzzer: &mut Z,
state: &mut S,
mgr: &mut EM,
input: &I,
) -> Result<ExitKind, Error> {
#[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, 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);
}
self.handlers
.pre_run_target(self, fuzzer, state, mgr, input);
let ret = (self.harness_fn)(input);
#[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);
}
self.handlers.post_run_target();
Ok(ret)
}
}
@ -169,77 +123,11 @@ where
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 {
harness_fn,
observers,
crash_handler: unix_signal_handler::inproc_crash_handler::<
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"))))]
let handlers = InProcessHandlers::new::<Self, EM, I, OC, OF, OT, S, Z>()?;
Ok(Self {
harness_fn,
observers,
crash_handler: ptr::null(),
timeout_handler: ptr::null(),
handlers,
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 state_ptr: *mut c_void,
pub event_mgr_ptr: *mut c_void,
@ -965,7 +1004,7 @@ where
#[cfg(test)]
mod tests {
use core::{marker::PhantomData, ptr};
use core::marker::PhantomData;
#[cfg(all(feature = "std", feature = "fork", unix))]
use crate::{
@ -974,7 +1013,7 @@ mod tests {
};
use crate::{
bolts::tuples::tuple_list,
executors::{Executor, ExitKind, InProcessExecutor},
executors::{inprocess::InProcessHandlers, Executor, ExitKind, InProcessExecutor},
inputs::NopInput,
};
@ -985,8 +1024,7 @@ mod tests {
let mut in_process_executor = InProcessExecutor::<_, NopInput, (), ()> {
harness_fn: &mut harness,
observers: tuple_list!(),
crash_handler: ptr::null(),
timeout_handler: ptr::null(),
handlers: InProcessHandlers::nop(),
phantom: PhantomData,
};
let input = NopInput {};