add TimeMaximizerCorpusScheduler
This commit is contained in:
parent
527bc590d2
commit
74023cc90f
@ -37,7 +37,7 @@ use libafl_qemu::{
|
||||
use crate::{
|
||||
clock::{QemuClockObserver, ClockTimeFeedback, QemuClockIncreaseFeedback},
|
||||
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;
|
||||
@ -205,7 +205,7 @@ pub fn fuzz() {
|
||||
});
|
||||
|
||||
// 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
|
||||
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
|
||||
#[cfg(target_os = "linux")]
|
||||
mod fuzzer;
|
||||
@ -7,6 +8,8 @@ mod clock;
|
||||
mod qemustate;
|
||||
#[cfg(target_os = "linux")]
|
||||
mod systemstate;
|
||||
#[cfg(target_os = "linux")]
|
||||
mod worst;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
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