add TimeMaximizerCorpusScheduler
This commit is contained in:
parent
25a58ddbe1
commit
3435a79e26
@ -37,7 +37,7 @@ use libafl_qemu::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
clock::{QemuClockObserver, ClockTimeFeedback, QemuClockIncreaseFeedback},
|
clock::{QemuClockObserver, ClockTimeFeedback, QemuClockIncreaseFeedback},
|
||||||
qemustate::QemuStateRestoreHelper,
|
qemustate::QemuStateRestoreHelper,
|
||||||
systemstate::{helpers::QemuSystemStateHelper, observers::QemuSystemStateObserver, feedbacks::DumpSystraceFeedback},
|
systemstate::{helpers::QemuSystemStateHelper, observers::QemuSystemStateObserver, feedbacks::DumpSystraceFeedback}, worst::TimeMaximizerCorpusScheduler,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static mut MAX_INPUT_SIZE: usize = 32;
|
pub static mut MAX_INPUT_SIZE: usize = 32;
|
||||||
@ -205,7 +205,7 @@ pub fn fuzz() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// A minimization+queue policy to get testcasess from the corpus
|
// A minimization+queue policy to get testcasess from the corpus
|
||||||
let scheduler = IndexesLenTimeMinimizerScheduler::new(QueueScheduler::new());
|
let scheduler = TimeMaximizerCorpusScheduler::new(QueueScheduler::new());
|
||||||
|
|
||||||
// A fuzzer with feedbacks and a corpus scheduler
|
// A fuzzer with feedbacks and a corpus scheduler
|
||||||
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#![feature(is_sorted)]
|
||||||
//! A libfuzzer-like fuzzer using qemu for binary-only coverage
|
//! A libfuzzer-like fuzzer using qemu for binary-only coverage
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
mod fuzzer;
|
mod fuzzer;
|
||||||
@ -7,6 +8,8 @@ mod clock;
|
|||||||
mod qemustate;
|
mod qemustate;
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
mod systemstate;
|
mod systemstate;
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
mod worst;
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
264
fuzzers/FRET/src/worst.rs
Normal file
264
fuzzers/FRET/src/worst.rs
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
use core::fmt::Debug;
|
||||||
|
use core::cmp::Ordering::{Greater,Less,Equal};
|
||||||
|
use libafl::inputs::BytesInput;
|
||||||
|
use libafl::inputs::HasTargetBytes;
|
||||||
|
use libafl::feedbacks::MapIndexesMetadata;
|
||||||
|
use libafl::corpus::Testcase;
|
||||||
|
use libafl::prelude::{UsesInput, AsSlice};
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
use libafl::schedulers::{MinimizerScheduler, TestcaseScore};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::fs;
|
||||||
|
use hashbrown::{HashMap};
|
||||||
|
use libafl::observers::ObserversTuple;
|
||||||
|
use libafl::executors::ExitKind;
|
||||||
|
use libafl::events::EventFirer;
|
||||||
|
use libafl::state::{HasClientPerfMonitor, HasCorpus, UsesState};
|
||||||
|
use libafl::inputs::Input;
|
||||||
|
use libafl::feedbacks::Feedback;
|
||||||
|
use libafl::state::HasMetadata;
|
||||||
|
use libafl_qemu::edges::QemuEdgesMapMetadata;
|
||||||
|
use libafl::observers::MapObserver;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::cmp;
|
||||||
|
|
||||||
|
use libafl::{
|
||||||
|
bolts::{
|
||||||
|
tuples::Named,
|
||||||
|
HasLen,
|
||||||
|
},
|
||||||
|
observers::Observer,
|
||||||
|
Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::clock::QemuClockObserver;
|
||||||
|
use crate::systemstate::FreeRTOSSystemStateMetadata;
|
||||||
|
//=========================== Scheduler
|
||||||
|
|
||||||
|
pub type TimeMaximizerCorpusScheduler<CS> =
|
||||||
|
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>, MapIndexesMetadata>;
|
||||||
|
|
||||||
|
/// Multiply the testcase size with the execution time.
|
||||||
|
/// This favors small and quick testcases.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct MaxTimeFavFactor<S>
|
||||||
|
where
|
||||||
|
S: HasCorpus + HasMetadata,
|
||||||
|
S::Input: HasLen,
|
||||||
|
{
|
||||||
|
phantom: PhantomData<S>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> TestcaseScore<S> for MaxTimeFavFactor<S>
|
||||||
|
where
|
||||||
|
S: HasCorpus + HasMetadata,
|
||||||
|
S::Input: HasLen,
|
||||||
|
{
|
||||||
|
fn compute(entry: &mut Testcase<S::Input>, state: &S) -> Result<f64, Error> {
|
||||||
|
// TODO maybe enforce entry.exec_time().is_some()
|
||||||
|
let execs_per_hour = 3600.0/entry.exec_time().expect("testcase.exec_time is needed for scheduler").as_secs_f64();
|
||||||
|
Ok(execs_per_hour)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type LenTimeMaximizerCorpusScheduler<CS> =
|
||||||
|
MinimizerScheduler<CS, MaxExecsLenFavFactor<<CS as UsesInput>::Input>, MapIndexesMetadata>;
|
||||||
|
|
||||||
|
pub type TimeStateMaximizerCorpusScheduler<CS> =
|
||||||
|
MinimizerScheduler<CS, MaxExecsLenFavFactor<<CS as UsesInput>::Input>, FreeRTOSSystemStateMetadata>;
|
||||||
|
|
||||||
|
/// Multiply the testcase size with the execution time.
|
||||||
|
/// This favors small and quick testcases.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct MaxExecsLenFavFactor<S>
|
||||||
|
where
|
||||||
|
S: HasCorpus + HasMetadata,
|
||||||
|
S::Input: HasLen,
|
||||||
|
{
|
||||||
|
phantom: PhantomData<S>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> TestcaseScore<S> for MaxExecsLenFavFactor<S>
|
||||||
|
where
|
||||||
|
S: HasCorpus + HasMetadata,
|
||||||
|
S::Input: HasLen,
|
||||||
|
{
|
||||||
|
fn compute(entry: &mut Testcase<S::Input>, state: &S) -> Result<f64, Error> {
|
||||||
|
let execs_per_hour = (3600.0/entry.exec_time().expect("testcase.exec_time is needed for scheduler").as_secs_f64());
|
||||||
|
let execs_times_length_per_hour = execs_per_hour*entry.cached_len()? as f64;
|
||||||
|
Ok(execs_times_length_per_hour)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===================================================================
|
||||||
|
|
||||||
|
/// A Feedback reporting if the Input consists of strictly decreasing bytes.
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct SortedFeedback {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> Feedback<S> for SortedFeedback
|
||||||
|
where
|
||||||
|
S: UsesInput + HasClientPerfMonitor,
|
||||||
|
S::Input: HasTargetBytes,
|
||||||
|
{
|
||||||
|
#[allow(clippy::wrong_self_convention)]
|
||||||
|
fn is_interesting<EM, OT>(
|
||||||
|
&mut self,
|
||||||
|
_state: &mut S,
|
||||||
|
_manager: &mut EM,
|
||||||
|
_input: &S::Input,
|
||||||
|
observers: &OT,
|
||||||
|
_exit_kind: &ExitKind,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<State = S>,
|
||||||
|
OT: ObserversTuple<S>,
|
||||||
|
{
|
||||||
|
let t = _input.target_bytes();
|
||||||
|
let tmp = t.as_slice();
|
||||||
|
if tmp.len()<32 {return Ok(false);}
|
||||||
|
let tmp = Vec::<u8>::from(&tmp[0..32]);
|
||||||
|
// tmp.reverse();
|
||||||
|
if tmp.is_sorted_by(|a,b| match a.partial_cmp(b).unwrap_or(Less) {
|
||||||
|
Less => Some(Greater),
|
||||||
|
Equal => Some(Greater),
|
||||||
|
Greater => Some(Less),
|
||||||
|
}) {return Ok(true)};
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Named for SortedFeedback {
|
||||||
|
#[inline]
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"Sorted"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SortedFeedback {
|
||||||
|
/// Creates a new [`HitFeedback`]
|
||||||
|
#[must_use]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for SortedFeedback {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===================================================================
|
||||||
|
/// A Feedback which expects a certain minimum execution time
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct ExecTimeReachedFeedback
|
||||||
|
{
|
||||||
|
target_time: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> Feedback<S> for ExecTimeReachedFeedback
|
||||||
|
where
|
||||||
|
S: UsesInput + HasClientPerfMonitor,
|
||||||
|
{
|
||||||
|
#[allow(clippy::wrong_self_convention)]
|
||||||
|
fn is_interesting<EM, OT>(
|
||||||
|
&mut self,
|
||||||
|
_state: &mut S,
|
||||||
|
_manager: &mut EM,
|
||||||
|
_input: &S::Input,
|
||||||
|
observers: &OT,
|
||||||
|
_exit_kind: &ExitKind,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<State = S>,
|
||||||
|
OT: ObserversTuple<S>,
|
||||||
|
{
|
||||||
|
let observer = observers.match_name::<QemuClockObserver>("clock")
|
||||||
|
.expect("QemuClockObserver not found");
|
||||||
|
Ok(observer.last_runtime() >= self.target_time)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Named for ExecTimeReachedFeedback
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"ExecTimeReachedFeedback"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExecTimeReachedFeedback
|
||||||
|
where
|
||||||
|
{
|
||||||
|
/// Creates a new [`ExecTimeReachedFeedback`]
|
||||||
|
#[must_use]
|
||||||
|
pub fn new(target_time : u64) -> Self {
|
||||||
|
Self {target_time: target_time}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static mut EXEC_TIME_COLLECTION : Vec<u32> = Vec::new();
|
||||||
|
|
||||||
|
/// A Noop Feedback which records a list of all execution times
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct ExecTimeCollectorFeedback
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> Feedback<S> for ExecTimeCollectorFeedback
|
||||||
|
where
|
||||||
|
S: UsesInput + HasClientPerfMonitor,
|
||||||
|
{
|
||||||
|
#[allow(clippy::wrong_self_convention)]
|
||||||
|
fn is_interesting<EM, OT>(
|
||||||
|
&mut self,
|
||||||
|
_state: &mut S,
|
||||||
|
_manager: &mut EM,
|
||||||
|
_input: &S::Input,
|
||||||
|
observers: &OT,
|
||||||
|
_exit_kind: &ExitKind,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<State = S>,
|
||||||
|
OT: ObserversTuple<S>,
|
||||||
|
{
|
||||||
|
let observer = observers.match_name::<QemuClockObserver>("clock")
|
||||||
|
.expect("QemuClockObserver not found");
|
||||||
|
unsafe { EXEC_TIME_COLLECTION.push(observer.last_runtime().try_into().unwrap()); }
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Named for ExecTimeCollectorFeedback
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"ExecTimeCollectorFeedback"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExecTimeCollectorFeedback
|
||||||
|
where
|
||||||
|
{
|
||||||
|
/// Creates a new [`ExecTimeCollectorFeedback`]
|
||||||
|
#[must_use]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shared Metadata for a SysStateFeedback
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
|
||||||
|
pub struct ExecTimeCollectorFeedbackState
|
||||||
|
{
|
||||||
|
collection: Vec<u32>,
|
||||||
|
}
|
||||||
|
impl Named for ExecTimeCollectorFeedbackState
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"ExecTimeCollectorFeedbackState"
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user