add TimeoutFeedback and send ExitKind::Timeout from the handler

This commit is contained in:
toka 2021-03-16 18:48:40 +09:00
parent ab3d070f1a
commit b321675aa9
5 changed files with 65 additions and 26 deletions

View File

@ -17,7 +17,6 @@
#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>
@ -84,7 +83,6 @@ 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;
} }

View File

@ -11,7 +11,7 @@ use libafl::{
QueueCorpusScheduler, QueueCorpusScheduler,
}, },
events::setup_restarting_mgr, events::setup_restarting_mgr,
executors::{inprocess::InProcessExecutor, Executor, ExitKind, inprocess::TimeoutExecutor}, executors::{inprocess::InProcessExecutor, Executor, ExitKind},
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 tmexecutor, &mut executor,
&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 tmexecutor, &mut restarting_mgr)?; fuzzer.fuzz_loop(&mut state, &mut executor, &mut restarting_mgr)?;
// Never reached // Never reached
Ok(()) Ok(())

View File

@ -213,7 +213,7 @@ where
I: Input + HasTargetBytes, I: Input + HasTargetBytes,
OT: ObserversTuple, OT: ObserversTuple,
{ {
fn name(&self) -> &str{ fn name(&self) -> &str {
self.executor.name() self.executor.name()
} }
} }
@ -241,8 +241,8 @@ where
I: Input + HasTargetBytes, I: Input + HasTargetBytes,
OT: ObserversTuple, OT: ObserversTuple,
{ {
pub fn new(executor: EX, exec_tmout: u64) -> Self{ pub fn new(executor: EX, exec_tmout: u64) -> Self {
Self{ Self {
executor, executor,
exec_tmout: Duration::from_secs(exec_tmout), exec_tmout: Duration::from_secs(exec_tmout),
phantom: PhantomData, phantom: PhantomData,
@ -257,20 +257,25 @@ where
OT: ObserversTuple, OT: ObserversTuple,
{ {
#[inline] #[inline]
fn pre_exec<EM: EventManager<I, S>, S>(&mut self, _state: &mut S, _event_mgr: &mut EM, _input: &I,) -> Result<(), Error>{ fn pre_exec<EM: EventManager<I, S>, S>(
unsafe{ &mut self,
_state: &mut S,
_event_mgr: &mut EM,
_input: &I,
) -> Result<(), Error> {
unsafe {
let milli_sec = self.exec_tmout.as_millis(); let milli_sec = self.exec_tmout.as_millis();
let it_value = Timeval{ let it_value = Timeval {
tv_sec: (milli_sec / 1000) as i64, tv_sec: (milli_sec / 1000) as i64,
tv_usec: (milli_sec % 1000) as i64, tv_usec: (milli_sec % 1000) as i64,
}; };
let it_interval = Timeval{ let it_interval = Timeval {
tv_sec: 0, tv_sec: 0,
tv_usec: 0, tv_usec: 0,
}; };
setitimer( setitimer(
ITIMER_REAL, ITIMER_REAL,
&mut Itimerval{ &mut Itimerval {
it_interval, it_interval,
it_value, it_value,
}, },
@ -280,21 +285,20 @@ where
self.executor.pre_exec(_state, _event_mgr, _input) self.executor.pre_exec(_state, _event_mgr, _input)
} }
fn run_target(&mut self, input: &I) -> Result<ExitKind, Error>{ fn run_target(&mut self, input: &I) -> Result<ExitKind, Error> {
let run_result = self.executor.run_target(input); let run_result = self.executor.run_target(input);
unsafe{ unsafe {
let it_value = Timeval{ let it_value = Timeval {
tv_sec: 0, tv_sec: 0,
tv_usec: 0, tv_usec: 0,
}; };
let it_interval = Timeval{ let it_interval = Timeval {
tv_sec: 0, tv_sec: 0,
tv_usec: 0, tv_usec: 0,
}; };
setitimer( setitimer(
ITIMER_REAL, ITIMER_REAL,
&mut Itimerval{ &mut Itimerval {
it_interval, it_interval,
it_value, it_value,
}, },
@ -305,7 +309,6 @@ where
} }
} }
#[cfg(unix)] #[cfg(unix)]
mod unix_signal_handler { mod unix_signal_handler {
use alloc::vec::Vec; use alloc::vec::Vec;
@ -373,9 +376,7 @@ mod unix_signal_handler {
Signal::SigUser2 | Signal::SigAlarm => { Signal::SigUser2 | Signal::SigAlarm => {
(data.timeout_handler)(signal, info, void, data) (data.timeout_handler)(signal, info, void, data)
}, },
_ => { _ => (data.crash_handler)(signal, info, void, data),
(data.crash_handler)(signal, info, void, data)
},
} }
} }
} }
@ -426,7 +427,7 @@ mod unix_signal_handler {
let obj_fitness = state let obj_fitness = state
.objectives_mut() .objectives_mut()
.is_interesting_all(&input, observers, ExitKind::Crash) .is_interesting_all(&input, observers, ExitKind::Timeout)
.expect("In timeout handler objectives failure."); .expect("In timeout handler objectives failure.");
if obj_fitness > 0 { if obj_fitness > 0 {
state state

View File

@ -157,6 +157,46 @@ impl Default for CrashFeedback {
} }
} }
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct TimeoutFeedback {}
impl<I> Feedback<I> for TimeoutFeedback
where
I: Input,
{
fn is_interesting<OT: ObserversTuple>(
&mut self,
_input: &I,
_observers: &OT,
exit_kind: ExitKind,
) -> Result<u32, Error> {
if exit_kind == ExitKind::Timeout {
Ok(1)
} else {
Ok(0)
}
}
}
impl Named for TimeoutFeedback {
#[inline]
fn name(&self) -> &str {
"TimeoutFeedback"
}
}
impl TimeoutFeedback {
pub fn new() -> Self {
Self {}
}
}
impl Default for TimeoutFeedback {
fn default() -> Self {
Self::new()
}
}
/// Nop feedback that annotates execution time in the new testcase, if any /// Nop feedback that annotates execution time in the new testcase, if any
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct TimeFeedback { pub struct TimeFeedback {

View File

@ -153,4 +153,4 @@ mod tests {
postcard::from_bytes(&vec).unwrap(); postcard::from_bytes(&vec).unwrap();
assert_eq!(obv.0.name(), obv2.0.name()); assert_eq!(obv.0.name(), obv2.0.name());
} }
} }