Batch mode timeouts (Linux only ATM) (#1193)
* batch mode timeouts for linux * batch_mode is linux only atm * fix * fix * fix * imports * winfix * more fix * winfix * fix * fix * fix * fix * clippy * fix macos --------- Co-authored-by: Dongjia "toka" Zhang <tokazerkje@outlook.com>
This commit is contained in:
parent
fafa27a7e9
commit
fd68c8a81f
@ -202,17 +202,21 @@ pub fn libafl_main() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create the executor for an in-process function with one observer for edge coverage and one for the execution time
|
// Create the executor for an in-process function with one observer for edge coverage and one for the execution time
|
||||||
let mut executor = TimeoutExecutor::new(
|
let executor = InProcessExecutor::new(
|
||||||
InProcessExecutor::new(
|
&mut harness,
|
||||||
&mut harness,
|
tuple_list!(edges_observer, time_observer),
|
||||||
tuple_list!(edges_observer, time_observer),
|
&mut fuzzer,
|
||||||
&mut fuzzer,
|
&mut state,
|
||||||
&mut state,
|
&mut restarting_mgr,
|
||||||
&mut restarting_mgr,
|
)?;
|
||||||
)?,
|
|
||||||
// 10 seconds timeout
|
// Wrap the executor with a timeout
|
||||||
opt.timeout,
|
#[cfg(target_os = "linux")]
|
||||||
);
|
let mut executor = TimeoutExecutor::batch_mode(executor, opt.timeout);
|
||||||
|
|
||||||
|
// Wrap the executor with a timeout
|
||||||
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
let mut executor = TimeoutExecutor::new(executor, opt.timeout);
|
||||||
|
|
||||||
// The actual target run starts here.
|
// The actual target run starts here.
|
||||||
// Call LLVMFUzzerInitialize() if present.
|
// Call LLVMFUzzerInitialize() if present.
|
||||||
|
@ -246,11 +246,12 @@ pub trait HasInProcessHandlers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
impl<'a, H, OT, S> HasInProcessHandlers for InProcessExecutor<'a, H, OT, S>
|
impl<H, HB, OT, S> HasInProcessHandlers for GenericInProcessExecutor<H, HB, OT, S>
|
||||||
where
|
where
|
||||||
H: FnMut(&S::Input) -> ExitKind,
|
H: FnMut(&<S as UsesInput>::Input) -> ExitKind + ?Sized,
|
||||||
|
HB: BorrowMut<H>,
|
||||||
OT: ObserversTuple<S>,
|
OT: ObserversTuple<S>,
|
||||||
S: UsesInput,
|
S: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
||||||
{
|
{
|
||||||
/// the timeout handler
|
/// the timeout handler
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -339,6 +340,7 @@ impl InProcessHandlers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create new [`InProcessHandlers`].
|
/// Create new [`InProcessHandlers`].
|
||||||
|
#[cfg(not(all(windows, feature = "std")))]
|
||||||
pub fn new<E, EM, OF, Z>() -> Result<Self, Error>
|
pub fn new<E, EM, OF, Z>() -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
E: Executor<EM, Z> + HasObservers,
|
E: Executor<EM, Z> + HasObservers,
|
||||||
@ -363,7 +365,20 @@ impl InProcessHandlers {
|
|||||||
as *const _,
|
as *const _,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
#[cfg(all(windows, feature = "std"))]
|
#[cfg(not(any(unix, feature = "std")))]
|
||||||
|
Ok(Self {})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create new [`InProcessHandlers`].
|
||||||
|
#[cfg(all(windows, feature = "std"))]
|
||||||
|
pub fn new<E, EM, OF, Z>() -> Result<Self, Error>
|
||||||
|
where
|
||||||
|
E: Executor<EM, Z> + HasObservers + HasInProcessHandlers,
|
||||||
|
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||||
|
OF: Feedback<E::State>,
|
||||||
|
E::State: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
||||||
|
Z: HasObjective<Objective = OF, State = E::State>,
|
||||||
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
let data = &mut GLOBAL_STATE;
|
let data = &mut GLOBAL_STATE;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -378,8 +393,6 @@ impl InProcessHandlers {
|
|||||||
as *const c_void,
|
as *const c_void,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
#[cfg(not(any(unix, feature = "std")))]
|
|
||||||
Ok(Self {})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replace the handlers with `nop` handlers, deactivating the handlers
|
/// Replace the handlers with `nop` handlers, deactivating the handlers
|
||||||
@ -409,12 +422,14 @@ pub(crate) struct InProcessExecutorHandlerData {
|
|||||||
fuzzer_ptr: *mut c_void,
|
fuzzer_ptr: *mut c_void,
|
||||||
executor_ptr: *const c_void,
|
executor_ptr: *const c_void,
|
||||||
pub current_input_ptr: *const c_void,
|
pub current_input_ptr: *const c_void,
|
||||||
|
|
||||||
/// The timeout handler
|
/// The timeout handler
|
||||||
#[cfg(any(unix, feature = "std"))]
|
#[cfg(any(unix, feature = "std"))]
|
||||||
crash_handler: *const c_void,
|
crash_handler: *const c_void,
|
||||||
/// The timeout handler
|
/// The timeout handler
|
||||||
#[cfg(any(unix, feature = "std"))]
|
#[cfg(any(unix, feature = "std"))]
|
||||||
timeout_handler: *const c_void,
|
timeout_handler: *const c_void,
|
||||||
|
|
||||||
#[cfg(all(windows, feature = "std"))]
|
#[cfg(all(windows, feature = "std"))]
|
||||||
pub(crate) tp_timer: *mut c_void,
|
pub(crate) tp_timer: *mut c_void,
|
||||||
#[cfg(all(windows, feature = "std"))]
|
#[cfg(all(windows, feature = "std"))]
|
||||||
@ -423,6 +438,9 @@ pub(crate) struct InProcessExecutorHandlerData {
|
|||||||
pub(crate) critical: *mut c_void,
|
pub(crate) critical: *mut c_void,
|
||||||
#[cfg(all(windows, feature = "std"))]
|
#[cfg(all(windows, feature = "std"))]
|
||||||
pub(crate) timeout_input_ptr: *mut c_void,
|
pub(crate) timeout_input_ptr: *mut c_void,
|
||||||
|
|
||||||
|
#[cfg(any(unix, feature = "std"))]
|
||||||
|
pub(crate) timeout_executor_ptr: *mut c_void,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for InProcessExecutorHandlerData {}
|
unsafe impl Send for InProcessExecutorHandlerData {}
|
||||||
@ -457,14 +475,23 @@ impl InProcessExecutorHandlerData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(windows, feature = "std"))]
|
#[cfg(all(windows, feature = "std"))]
|
||||||
fn is_valid(&self) -> bool {
|
pub(crate) fn is_valid(&self) -> bool {
|
||||||
self.in_target == 1
|
self.in_target == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn is_valid(&self) -> bool {
|
pub(crate) fn is_valid(&self) -> bool {
|
||||||
!self.current_input_ptr.is_null()
|
!self.current_input_ptr.is_null()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(unix, feature = "std"))]
|
||||||
|
fn timeout_executor_mut<'a, E>(&self) -> &'a mut crate::executors::timeout::TimeoutExecutor<E> {
|
||||||
|
unsafe {
|
||||||
|
(self.timeout_executor_ptr as *mut crate::executors::timeout::TimeoutExecutor<E>)
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Exception handling needs some nasty unsafe.
|
/// Exception handling needs some nasty unsafe.
|
||||||
@ -479,6 +506,7 @@ pub(crate) static mut GLOBAL_STATE: InProcessExecutorHandlerData = InProcessExec
|
|||||||
executor_ptr: ptr::null(),
|
executor_ptr: ptr::null(),
|
||||||
/// The current input for signal handling
|
/// The current input for signal handling
|
||||||
current_input_ptr: ptr::null(),
|
current_input_ptr: ptr::null(),
|
||||||
|
|
||||||
/// The crash handler fn
|
/// The crash handler fn
|
||||||
#[cfg(any(unix, feature = "std"))]
|
#[cfg(any(unix, feature = "std"))]
|
||||||
crash_handler: ptr::null(),
|
crash_handler: ptr::null(),
|
||||||
@ -493,6 +521,9 @@ pub(crate) static mut GLOBAL_STATE: InProcessExecutorHandlerData = InProcessExec
|
|||||||
critical: null_mut(),
|
critical: null_mut(),
|
||||||
#[cfg(all(windows, feature = "std"))]
|
#[cfg(all(windows, feature = "std"))]
|
||||||
timeout_input_ptr: null_mut(),
|
timeout_input_ptr: null_mut(),
|
||||||
|
|
||||||
|
#[cfg(any(unix, feature = "std"))]
|
||||||
|
timeout_executor_ptr: null_mut(),
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Get the inprocess [`crate::state::State`]
|
/// Get the inprocess [`crate::state::State`]
|
||||||
@ -715,6 +746,12 @@ mod unix_signal_handler {
|
|||||||
E::State: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
E::State: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
||||||
Z: HasObjective<Objective = OF, State = E::State>,
|
Z: HasObjective<Objective = OF, State = E::State>,
|
||||||
{
|
{
|
||||||
|
if !data.timeout_executor_ptr.is_null()
|
||||||
|
&& data.timeout_executor_mut::<E>().handle_timeout(data)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if !data.is_valid() {
|
if !data.is_valid() {
|
||||||
log::warn!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing.");
|
log::warn!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing.");
|
||||||
return;
|
return;
|
||||||
@ -966,7 +1003,10 @@ mod windows_exception_handler {
|
|||||||
},
|
},
|
||||||
events::{EventFirer, EventRestarter},
|
events::{EventFirer, EventRestarter},
|
||||||
executors::{
|
executors::{
|
||||||
inprocess::{run_observers_and_save_state, InProcessExecutorHandlerData, GLOBAL_STATE},
|
inprocess::{
|
||||||
|
run_observers_and_save_state, HasInProcessHandlers, InProcessExecutorHandlerData,
|
||||||
|
GLOBAL_STATE,
|
||||||
|
},
|
||||||
Executor, ExitKind, HasObservers,
|
Executor, ExitKind, HasObservers,
|
||||||
},
|
},
|
||||||
feedbacks::Feedback,
|
feedbacks::Feedback,
|
||||||
@ -1067,7 +1107,7 @@ mod windows_exception_handler {
|
|||||||
global_state: *mut c_void,
|
global_state: *mut c_void,
|
||||||
_p1: *mut u8,
|
_p1: *mut u8,
|
||||||
) where
|
) where
|
||||||
E: HasObservers,
|
E: HasObservers + HasInProcessHandlers,
|
||||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||||
OF: Feedback<E::State>,
|
OF: Feedback<E::State>,
|
||||||
E::State: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
E::State: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
||||||
@ -1083,6 +1123,20 @@ mod windows_exception_handler {
|
|||||||
);
|
);
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
|
if !data.timeout_executor_ptr.is_null()
|
||||||
|
&& data.timeout_executor_mut::<E>().handle_timeout(data)
|
||||||
|
{
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
LeaveCriticalSection(
|
||||||
|
(data.critical as *mut RTL_CRITICAL_SECTION)
|
||||||
|
.as_mut()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if data.in_target == 1 {
|
if data.in_target == 1 {
|
||||||
let executor = data.executor_mut::<E>();
|
let executor = data.executor_mut::<E>();
|
||||||
let state = data.state_mut::<E::State>();
|
let state = data.state_mut::<E::State>();
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
use core::ptr::{addr_of, addr_of_mut};
|
use core::ptr::{addr_of, addr_of_mut};
|
||||||
#[cfg(all(windows, feature = "std"))]
|
#[cfg(any(windows, target_os = "linux"))]
|
||||||
use core::{ffi::c_void, ptr::write_volatile};
|
use core::{ffi::c_void, ptr::write_volatile};
|
||||||
#[cfg(any(windows, unix))]
|
#[cfg(any(windows, unix))]
|
||||||
use core::{
|
use core::{
|
||||||
@ -29,10 +29,14 @@ use windows::Win32::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
use crate::bolts::current_time;
|
||||||
#[cfg(all(windows, feature = "std"))]
|
#[cfg(all(windows, feature = "std"))]
|
||||||
use crate::executors::inprocess::{HasInProcessHandlers, GLOBAL_STATE};
|
use crate::executors::inprocess::HasInProcessHandlers;
|
||||||
|
#[cfg(any(windows, target_os = "linux"))]
|
||||||
|
use crate::executors::inprocess::GLOBAL_STATE;
|
||||||
use crate::{
|
use crate::{
|
||||||
executors::{Executor, ExitKind, HasObservers},
|
executors::{inprocess::InProcessExecutorHandlerData, Executor, ExitKind, HasObservers},
|
||||||
observers::UsesObservers,
|
observers::UsesObservers,
|
||||||
state::UsesState,
|
state::UsesState,
|
||||||
Error,
|
Error,
|
||||||
@ -40,7 +44,7 @@ use crate::{
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[cfg(all(unix, not(target_os = "linux")))]
|
#[cfg(all(unix, not(target_os = "linux")))]
|
||||||
struct Timeval {
|
pub(crate) struct Timeval {
|
||||||
pub tv_sec: i64,
|
pub tv_sec: i64,
|
||||||
pub tv_usec: i64,
|
pub tv_usec: i64,
|
||||||
}
|
}
|
||||||
@ -62,7 +66,7 @@ impl Debug for Timeval {
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[cfg(all(unix, not(target_os = "linux")))]
|
#[cfg(all(unix, not(target_os = "linux")))]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Itimerval {
|
pub(crate) struct Itimerval {
|
||||||
pub it_interval: Timeval,
|
pub it_interval: Timeval,
|
||||||
pub it_value: Timeval,
|
pub it_value: Timeval,
|
||||||
}
|
}
|
||||||
@ -91,6 +95,24 @@ pub struct TimeoutExecutor<E> {
|
|||||||
tp_timer: *mut TP_TIMER,
|
tp_timer: *mut TP_TIMER,
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
critical: RTL_CRITICAL_SECTION,
|
critical: RTL_CRITICAL_SECTION,
|
||||||
|
|
||||||
|
exec_tmout: Duration,
|
||||||
|
|
||||||
|
// for batch mode (linux only atm)
|
||||||
|
#[allow(unused)]
|
||||||
|
batch_mode: bool,
|
||||||
|
#[allow(unused)]
|
||||||
|
executions: u32,
|
||||||
|
#[allow(unused)]
|
||||||
|
avg_mul_k: u32,
|
||||||
|
#[allow(unused)]
|
||||||
|
last_signal_time: Duration,
|
||||||
|
#[allow(unused)]
|
||||||
|
avg_exec_time: Duration,
|
||||||
|
#[allow(unused)]
|
||||||
|
start_time: Duration,
|
||||||
|
#[allow(unused)]
|
||||||
|
tmout_start_time: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Debug> Debug for TimeoutExecutor<E> {
|
impl<E: Debug> Debug for TimeoutExecutor<E> {
|
||||||
@ -158,9 +180,25 @@ impl<E> TimeoutExecutor<E> {
|
|||||||
executor,
|
executor,
|
||||||
itimerspec,
|
itimerspec,
|
||||||
timerid,
|
timerid,
|
||||||
|
exec_tmout,
|
||||||
|
batch_mode: false,
|
||||||
|
executions: 0,
|
||||||
|
avg_mul_k: 1,
|
||||||
|
last_signal_time: Duration::ZERO,
|
||||||
|
avg_exec_time: Duration::ZERO,
|
||||||
|
start_time: Duration::ZERO,
|
||||||
|
tmout_start_time: Duration::ZERO,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new [`TimeoutExecutor`], wrapping the given `executor` and checking for timeouts.
|
||||||
|
/// With this method batch mode is enabled.
|
||||||
|
pub fn batch_mode(executor: E, exec_tmout: Duration) -> Self {
|
||||||
|
let mut me = Self::new(executor, exec_tmout);
|
||||||
|
me.batch_mode = true;
|
||||||
|
me
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the timeout for this executor
|
/// Set the timeout for this executor
|
||||||
pub fn set_timeout(&mut self, exec_tmout: Duration) {
|
pub fn set_timeout(&mut self, exec_tmout: Duration) {
|
||||||
let milli_sec = exec_tmout.as_millis();
|
let milli_sec = exec_tmout.as_millis();
|
||||||
@ -177,6 +215,50 @@ impl<E> TimeoutExecutor<E> {
|
|||||||
it_value,
|
it_value,
|
||||||
};
|
};
|
||||||
self.itimerspec = itimerspec;
|
self.itimerspec = itimerspec;
|
||||||
|
self.exec_tmout = exec_tmout;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn handle_timeout(&mut self, data: &mut InProcessExecutorHandlerData) -> bool {
|
||||||
|
if !self.batch_mode {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// eprintln!("handle_timeout {:?} {}", self.avg_exec_time, self.avg_mul_k);
|
||||||
|
let cur_time = current_time();
|
||||||
|
if !data.is_valid() {
|
||||||
|
// outside the target
|
||||||
|
unsafe {
|
||||||
|
let disarmed: libc::itimerspec = zeroed();
|
||||||
|
libc::timer_settime(self.timerid, 0, addr_of!(disarmed), null_mut());
|
||||||
|
}
|
||||||
|
let elapsed = cur_time - self.tmout_start_time;
|
||||||
|
// set timer the next exec
|
||||||
|
if self.executions > 0 {
|
||||||
|
self.avg_exec_time = elapsed / self.executions;
|
||||||
|
self.executions = 0;
|
||||||
|
}
|
||||||
|
self.avg_mul_k += 1;
|
||||||
|
self.last_signal_time = cur_time;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let elapsed_run = cur_time - self.start_time;
|
||||||
|
if elapsed_run < self.exec_tmout {
|
||||||
|
// fp, reset timeout
|
||||||
|
unsafe {
|
||||||
|
libc::timer_settime(self.timerid, 0, addr_of!(self.itimerspec), null_mut());
|
||||||
|
}
|
||||||
|
if self.executions > 0 {
|
||||||
|
let elapsed = cur_time - self.tmout_start_time;
|
||||||
|
self.avg_exec_time = elapsed / self.executions;
|
||||||
|
self.executions = 0; // It will be 1 when the exec finish
|
||||||
|
}
|
||||||
|
self.tmout_start_time = current_time();
|
||||||
|
self.avg_mul_k += 1;
|
||||||
|
self.last_signal_time = cur_time;
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,6 +283,14 @@ impl<E> TimeoutExecutor<E> {
|
|||||||
Self {
|
Self {
|
||||||
executor,
|
executor,
|
||||||
itimerval,
|
itimerval,
|
||||||
|
exec_tmout,
|
||||||
|
batch_mode: false,
|
||||||
|
executions: 0,
|
||||||
|
avg_mul_k: 1,
|
||||||
|
last_signal_time: Duration::ZERO,
|
||||||
|
avg_exec_time: Duration::ZERO,
|
||||||
|
start_time: Duration::ZERO,
|
||||||
|
tmout_start_time: Duration::ZERO,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,6 +310,12 @@ impl<E> TimeoutExecutor<E> {
|
|||||||
it_value,
|
it_value,
|
||||||
};
|
};
|
||||||
self.itimerval = itimerval;
|
self.itimerval = itimerval;
|
||||||
|
self.exec_tmout = exec_tmout;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::unused_self)]
|
||||||
|
pub(crate) fn handle_timeout(&mut self, _data: &mut InProcessExecutorHandlerData) -> bool {
|
||||||
|
false // TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,13 +344,26 @@ impl<E: HasInProcessHandlers> TimeoutExecutor<E> {
|
|||||||
milli_sec,
|
milli_sec,
|
||||||
tp_timer,
|
tp_timer,
|
||||||
critical,
|
critical,
|
||||||
|
exec_tmout,
|
||||||
|
batch_mode: false,
|
||||||
|
executions: 0,
|
||||||
|
avg_mul_k: 1,
|
||||||
|
last_signal_time: Duration::ZERO,
|
||||||
|
avg_exec_time: Duration::ZERO,
|
||||||
|
start_time: Duration::ZERO,
|
||||||
|
tmout_start_time: Duration::ZERO,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the timeout for this executor
|
/// Set the timeout for this executor
|
||||||
#[cfg(windows)]
|
|
||||||
pub fn set_timeout(&mut self, exec_tmout: Duration) {
|
pub fn set_timeout(&mut self, exec_tmout: Duration) {
|
||||||
self.milli_sec = exec_tmout.as_millis() as i64;
|
self.milli_sec = exec_tmout.as_millis() as i64;
|
||||||
|
self.exec_tmout = exec_tmout;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::unused_self)]
|
||||||
|
pub(crate) fn handle_timeout(&mut self, _data: &mut InProcessExecutorHandlerData) -> bool {
|
||||||
|
false // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the inner `Executor` that is wrapped by this `TimeoutExecutor`.
|
/// Retrieve the inner `Executor` that is wrapped by this `TimeoutExecutor`.
|
||||||
@ -280,6 +389,11 @@ where
|
|||||||
) -> Result<ExitKind, Error> {
|
) -> Result<ExitKind, Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let data = &mut GLOBAL_STATE;
|
let data = &mut GLOBAL_STATE;
|
||||||
|
write_volatile(
|
||||||
|
&mut data.timeout_executor_ptr,
|
||||||
|
self as *mut _ as *mut c_void,
|
||||||
|
);
|
||||||
|
|
||||||
write_volatile(&mut data.tp_timer, self.tp_timer as *mut _ as *mut c_void);
|
write_volatile(&mut data.tp_timer, self.tp_timer as *mut _ as *mut c_void);
|
||||||
write_volatile(
|
write_volatile(
|
||||||
&mut data.critical,
|
&mut data.critical,
|
||||||
@ -349,7 +463,22 @@ where
|
|||||||
input: &Self::Input,
|
input: &Self::Input,
|
||||||
) -> Result<ExitKind, Error> {
|
) -> Result<ExitKind, Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
libc::timer_settime(self.timerid, 0, addr_of_mut!(self.itimerspec), null_mut());
|
if self.batch_mode {
|
||||||
|
let data = &mut GLOBAL_STATE;
|
||||||
|
write_volatile(
|
||||||
|
&mut data.timeout_executor_ptr,
|
||||||
|
self as *mut _ as *mut c_void,
|
||||||
|
);
|
||||||
|
|
||||||
|
if self.executions == 0 {
|
||||||
|
libc::timer_settime(self.timerid, 0, addr_of_mut!(self.itimerspec), null_mut());
|
||||||
|
self.tmout_start_time = current_time();
|
||||||
|
}
|
||||||
|
self.start_time = current_time();
|
||||||
|
} else {
|
||||||
|
libc::timer_settime(self.timerid, 0, addr_of_mut!(self.itimerspec), null_mut());
|
||||||
|
}
|
||||||
|
|
||||||
let ret = self.executor.run_target(fuzzer, state, mgr, input);
|
let ret = self.executor.run_target(fuzzer, state, mgr, input);
|
||||||
// reset timer
|
// reset timer
|
||||||
self.post_run_reset();
|
self.post_run_reset();
|
||||||
@ -358,9 +487,35 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn post_run_reset(&mut self) {
|
fn post_run_reset(&mut self) {
|
||||||
unsafe {
|
if self.batch_mode {
|
||||||
let disarmed: libc::itimerspec = zeroed();
|
unsafe {
|
||||||
libc::timer_settime(self.timerid, 0, addr_of!(disarmed), null_mut());
|
let elapsed = current_time() - self.tmout_start_time;
|
||||||
|
// elapsed may be > than tmout in case of reveived but ingored signal
|
||||||
|
if elapsed > self.exec_tmout
|
||||||
|
|| self.exec_tmout - elapsed < self.avg_exec_time * self.avg_mul_k
|
||||||
|
{
|
||||||
|
let disarmed: libc::itimerspec = zeroed();
|
||||||
|
libc::timer_settime(self.timerid, 0, addr_of!(disarmed), null_mut());
|
||||||
|
// set timer the next exec
|
||||||
|
if self.executions > 0 {
|
||||||
|
self.avg_exec_time = elapsed / self.executions;
|
||||||
|
self.executions = 0;
|
||||||
|
}
|
||||||
|
// readjust K
|
||||||
|
if self.last_signal_time > self.exec_tmout * self.avg_mul_k
|
||||||
|
&& self.avg_mul_k > 1
|
||||||
|
{
|
||||||
|
self.avg_mul_k -= 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.executions += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsafe {
|
||||||
|
let disarmed: libc::itimerspec = zeroed();
|
||||||
|
libc::timer_settime(self.timerid, 0, addr_of!(disarmed), null_mut());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.executor.post_run_reset();
|
self.executor.post_run_reset();
|
||||||
}
|
}
|
||||||
|
@ -498,7 +498,7 @@ where
|
|||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
|
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
|
||||||
self.last_runtime = None;
|
self.last_runtime = None;
|
||||||
self.start_time = Duration::from_secs(0);
|
self.start_time = current_time();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user