add TimeoutExecutor
This commit is contained in:
parent
b259e57524
commit
ab3d070f1a
@ -17,6 +17,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -83,6 +84,7 @@ static const int kPngHeaderSize = 8;
|
|||||||
// Roughly follows the libpng book example:
|
// Roughly follows the libpng book example:
|
||||||
// http://www.libpng.org/pub/png/book/chapter13.html
|
// http://www.libpng.org/pub/png/book/chapter13.html
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
|
sleep(3);
|
||||||
if (size < kPngHeaderSize) {
|
if (size < kPngHeaderSize) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ use libafl::{
|
|||||||
QueueCorpusScheduler,
|
QueueCorpusScheduler,
|
||||||
},
|
},
|
||||||
events::setup_restarting_mgr,
|
events::setup_restarting_mgr,
|
||||||
executors::{inprocess::InProcessExecutor, Executor, ExitKind},
|
executors::{inprocess::InProcessExecutor, Executor, ExitKind, inprocess::TimeoutExecutor},
|
||||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||||
fuzzer::{Fuzzer, HasCorpusScheduler, StdFuzzer},
|
fuzzer::{Fuzzer, HasCorpusScheduler, StdFuzzer},
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
@ -150,7 +150,7 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
|
|||||||
&mut state,
|
&mut state,
|
||||||
&mut restarting_mgr,
|
&mut restarting_mgr,
|
||||||
)?;
|
)?;
|
||||||
|
let mut tmexecutor = TimeoutExecutor::new(executor, 2);
|
||||||
// The actual target run starts here.
|
// The actual target run starts here.
|
||||||
// Call LLVMFUzzerInitialize() if present.
|
// Call LLVMFUzzerInitialize() if present.
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -163,7 +163,7 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
|
|||||||
if state.corpus().count() < 1 {
|
if state.corpus().count() < 1 {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(
|
.load_initial_inputs(
|
||||||
&mut executor,
|
&mut tmexecutor,
|
||||||
&mut restarting_mgr,
|
&mut restarting_mgr,
|
||||||
fuzzer.scheduler(),
|
fuzzer.scheduler(),
|
||||||
&corpus_dirs,
|
&corpus_dirs,
|
||||||
@ -175,7 +175,7 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
|
|||||||
println!("We imported {} inputs from disk.", state.corpus().count());
|
println!("We imported {} inputs from disk.", state.corpus().count());
|
||||||
}
|
}
|
||||||
|
|
||||||
fuzzer.fuzz_loop(&mut state, &mut executor, &mut restarting_mgr)?;
|
fuzzer.fuzz_loop(&mut state, &mut tmexecutor, &mut restarting_mgr)?;
|
||||||
|
|
||||||
// Never reached
|
// Never reached
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -2,6 +2,14 @@
|
|||||||
//! It should usually be paired with extra error-handling, such as a restarting event manager, to be effective.
|
//! It should usually be paired with extra error-handling, such as a restarting event manager, to be effective.
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
use core::time::Duration;
|
||||||
|
#[cfg(unix)]
|
||||||
|
use std::os::raw::c_int;
|
||||||
|
#[cfg(unix)]
|
||||||
|
use std::ptr::null_mut;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use core::{
|
use core::{
|
||||||
ptr::{self, write_volatile},
|
ptr::{self, write_volatile},
|
||||||
@ -164,6 +172,140 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[cfg(unix)]
|
||||||
|
struct Timeval {
|
||||||
|
pub tv_sec: i64,
|
||||||
|
pub tv_usec: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[cfg(unix)]
|
||||||
|
struct Itimerval {
|
||||||
|
pub it_interval: Timeval,
|
||||||
|
pub it_value: Timeval,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
extern "C" {
|
||||||
|
fn setitimer(which: c_int, new_value: *mut Itimerval, old_value: *mut Itimerval) -> c_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
const ITIMER_REAL: c_int = 0;
|
||||||
|
|
||||||
|
//timeout excutor wrap a InProcessExecutor
|
||||||
|
#[cfg(unix)]
|
||||||
|
pub struct TimeoutExecutor<I, OT, EX>
|
||||||
|
where
|
||||||
|
EX: Executor<I> + HasObservers<OT>,
|
||||||
|
I: Input + HasTargetBytes,
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
executor: EX,
|
||||||
|
exec_tmout: Duration,
|
||||||
|
phantom: PhantomData<(I, OT)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, OT, EX> Named for TimeoutExecutor<I, OT, EX>
|
||||||
|
where
|
||||||
|
EX: Executor<I> + HasObservers<OT>,
|
||||||
|
I: Input + HasTargetBytes,
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
fn name(&self) -> &str{
|
||||||
|
self.executor.name()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, OT, EX> HasObservers<OT> for TimeoutExecutor<I, OT, EX>
|
||||||
|
where
|
||||||
|
EX: Executor<I> + HasObservers<OT>,
|
||||||
|
I: Input + HasTargetBytes,
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn observers(&self) -> &OT {
|
||||||
|
self.executor.observers()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn observers_mut(&mut self) -> &mut OT {
|
||||||
|
self.executor.observers_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, OT, EX> TimeoutExecutor<I, OT, EX>
|
||||||
|
where
|
||||||
|
EX: Executor<I> + HasObservers<OT>,
|
||||||
|
I: Input + HasTargetBytes,
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
pub fn new(executor: EX, exec_tmout: u64) -> Self{
|
||||||
|
Self{
|
||||||
|
executor,
|
||||||
|
exec_tmout: Duration::from_secs(exec_tmout),
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, OT, EX> Executor<I> for TimeoutExecutor<I, OT, EX>
|
||||||
|
where
|
||||||
|
EX: Executor<I> + HasObservers<OT>,
|
||||||
|
I: Input + HasTargetBytes,
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn pre_exec<EM: EventManager<I, S>, S>(&mut self, _state: &mut S, _event_mgr: &mut EM, _input: &I,) -> Result<(), Error>{
|
||||||
|
unsafe{
|
||||||
|
let milli_sec = self.exec_tmout.as_millis();
|
||||||
|
let it_value = Timeval{
|
||||||
|
tv_sec: (milli_sec / 1000) as i64,
|
||||||
|
tv_usec: (milli_sec % 1000) as i64,
|
||||||
|
};
|
||||||
|
let it_interval = Timeval{
|
||||||
|
tv_sec: 0,
|
||||||
|
tv_usec: 0,
|
||||||
|
};
|
||||||
|
setitimer(
|
||||||
|
ITIMER_REAL,
|
||||||
|
&mut Itimerval{
|
||||||
|
it_interval,
|
||||||
|
it_value,
|
||||||
|
},
|
||||||
|
null_mut(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
self.executor.pre_exec(_state, _event_mgr, _input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_target(&mut self, input: &I) -> Result<ExitKind, Error>{
|
||||||
|
|
||||||
|
let run_result = self.executor.run_target(input);
|
||||||
|
unsafe{
|
||||||
|
let it_value = Timeval{
|
||||||
|
tv_sec: 0,
|
||||||
|
tv_usec: 0,
|
||||||
|
};
|
||||||
|
let it_interval = Timeval{
|
||||||
|
tv_sec: 0,
|
||||||
|
tv_usec: 0,
|
||||||
|
};
|
||||||
|
setitimer(
|
||||||
|
ITIMER_REAL,
|
||||||
|
&mut Itimerval{
|
||||||
|
it_interval,
|
||||||
|
it_value,
|
||||||
|
},
|
||||||
|
null_mut(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
run_result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
mod unix_signal_handler {
|
mod unix_signal_handler {
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
@ -8,11 +8,6 @@ use alloc::{
|
|||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
use std::os::raw::c_int;
|
|
||||||
#[cfg(unix)]
|
|
||||||
use std::ptr::null_mut;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::tuples::{MatchFirstType, MatchNameAndType, MatchType, Named, TupleList},
|
bolts::tuples::{MatchFirstType, MatchNameAndType, MatchType, Named, TupleList},
|
||||||
utils::current_time,
|
utils::current_time,
|
||||||
@ -99,31 +94,8 @@ pub struct TimeObserver {
|
|||||||
name: String,
|
name: String,
|
||||||
start_time: Duration,
|
start_time: Duration,
|
||||||
last_runtime: Option<Duration>,
|
last_runtime: Option<Duration>,
|
||||||
exec_tmout: Option<Duration>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[cfg(unix)]
|
|
||||||
struct Timeval {
|
|
||||||
pub tv_sec: i64,
|
|
||||||
pub tv_usec: i64,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[cfg(unix)]
|
|
||||||
struct Itimerval {
|
|
||||||
pub it_interval: Timeval,
|
|
||||||
pub it_value: Timeval,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
extern "C" {
|
|
||||||
fn setitimer(which: c_int, new_value: *mut Itimerval, old_value: *mut Itimerval) -> c_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
const ITIMER_REAL: c_int = 0;
|
|
||||||
|
|
||||||
impl TimeObserver {
|
impl TimeObserver {
|
||||||
/// Creates a new TimeObserver with the given name.
|
/// Creates a new TimeObserver with the given name.
|
||||||
pub fn new(name: &'static str) -> Self {
|
pub fn new(name: &'static str) -> Self {
|
||||||
@ -131,17 +103,6 @@ impl TimeObserver {
|
|||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
start_time: Duration::from_secs(0),
|
start_time: Duration::from_secs(0),
|
||||||
last_runtime: None,
|
last_runtime: None,
|
||||||
exec_tmout: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
pub fn with_timeout(name: &'static str, tmout: u64) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
start_time: Duration::from_secs(0),
|
|
||||||
last_runtime: None,
|
|
||||||
exec_tmout: Some(Duration::from_secs(tmout)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,30 +113,6 @@ impl TimeObserver {
|
|||||||
|
|
||||||
impl Observer for TimeObserver {
|
impl Observer for TimeObserver {
|
||||||
fn pre_exec(&mut self) -> Result<(), Error> {
|
fn pre_exec(&mut self) -> Result<(), Error> {
|
||||||
#[cfg(unix)]
|
|
||||||
match self.exec_tmout {
|
|
||||||
Some(exec_tmout) => unsafe {
|
|
||||||
let milli_sec = exec_tmout.as_millis();
|
|
||||||
let it_value = Timeval {
|
|
||||||
tv_sec: (milli_sec / 1000) as i64,
|
|
||||||
tv_usec: (milli_sec % 1000) as i64,
|
|
||||||
};
|
|
||||||
let it_interval = Timeval {
|
|
||||||
tv_sec: 0,
|
|
||||||
tv_usec: 0,
|
|
||||||
};
|
|
||||||
setitimer(
|
|
||||||
ITIMER_REAL,
|
|
||||||
&mut Itimerval {
|
|
||||||
it_interval,
|
|
||||||
it_value,
|
|
||||||
},
|
|
||||||
null_mut(),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
None => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
self.last_runtime = None;
|
self.last_runtime = None;
|
||||||
self.start_time = current_time();
|
self.start_time = current_time();
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -183,30 +120,6 @@ impl Observer for TimeObserver {
|
|||||||
|
|
||||||
fn post_exec(&mut self) -> Result<(), Error> {
|
fn post_exec(&mut self) -> Result<(), Error> {
|
||||||
self.last_runtime = Some(current_time() - self.start_time);
|
self.last_runtime = Some(current_time() - self.start_time);
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
match self.exec_tmout {
|
|
||||||
Some(_) => unsafe {
|
|
||||||
let it_value = Timeval {
|
|
||||||
tv_sec: 0,
|
|
||||||
tv_usec: 0,
|
|
||||||
};
|
|
||||||
let it_interval = Timeval {
|
|
||||||
tv_sec: 0,
|
|
||||||
tv_usec: 0,
|
|
||||||
};
|
|
||||||
setitimer(
|
|
||||||
ITIMER_REAL,
|
|
||||||
&mut Itimerval {
|
|
||||||
it_interval,
|
|
||||||
it_value,
|
|
||||||
},
|
|
||||||
null_mut(),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
None => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user