From 87cad475e3d2576ed5ae74f3c069267cafa6a3d5 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Tue, 9 Mar 2021 15:12:48 +0100 Subject: [PATCH] TimeFeedback --- libafl/src/feedbacks/mod.rs | 60 ++++++++++++++++++++++++++++++++++++- libafl/src/observers/mod.rs | 8 +++-- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/libafl/src/feedbacks/mod.rs b/libafl/src/feedbacks/mod.rs index 10a8606a54..79dddaaf5d 100644 --- a/libafl/src/feedbacks/mod.rs +++ b/libafl/src/feedbacks/mod.rs @@ -11,10 +11,12 @@ use crate::{ corpus::Testcase, executors::ExitKind, inputs::Input, - observers::ObserversTuple, + observers::{ObserversTuple, TimeObserver}, Error, }; +use core::time::Duration; + /// Feedbacks evaluate the observers. /// Basically, they reduce the information provided by an observer to a value, /// indicating the "interestingness" of the last run. @@ -154,3 +156,59 @@ impl Default for CrashFeedback { Self::new() } } + +/// Nop feedback that annotates execution time in the new testcase, if any +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct TimeFeedback { + exec_time: Option, +} + +impl Feedback for TimeFeedback +where + I: Input, +{ + fn is_interesting( + &mut self, + _input: &I, + observers: &OT, + _exit_kind: ExitKind, + ) -> Result { + let observer = observers.match_first_type::().unwrap(); + self.exec_time = *observer.last_runtime(); + Ok(0) + } + + /// Append to the testcase the generated metadata in case of a new corpus item + #[inline] + fn append_metadata(&mut self, testcase: &mut Testcase) -> Result<(), Error> { + *testcase.exec_time_mut() = self.exec_time; + self.exec_time = None; + Ok(()) + } + + /// Discard the stored metadata in case that the testcase is not added to the corpus + #[inline] + fn discard_metadata(&mut self, _input: &I) -> Result<(), Error> { + self.exec_time = None; + Ok(()) + } +} + +impl Named for TimeFeedback { + #[inline] + fn name(&self) -> &str { + "TimeFeedback" + } +} + +impl TimeFeedback { + pub fn new() -> Self { + Self { exec_time: None } + } +} + +impl Default for TimeFeedback { + fn default() -> Self { + Self::new() + } +} diff --git a/libafl/src/observers/mod.rs b/libafl/src/observers/mod.rs index ddf3d19203..7404ceeeb9 100644 --- a/libafl/src/observers/mod.rs +++ b/libafl/src/observers/mod.rs @@ -9,7 +9,7 @@ use core::time::Duration; use serde::{Deserialize, Serialize}; use crate::{ - bolts::tuples::{MatchNameAndType, MatchType, Named, TupleList}, + bolts::tuples::{MatchFirstType, MatchNameAndType, MatchType, Named, TupleList}, utils::current_time, Error, }; @@ -52,7 +52,7 @@ pub trait Observer: Named + serde::Serialize + serde::de::DeserializeOwned + 'st /// A hastkel-style tuple of observers pub trait ObserversTuple: - MatchNameAndType + MatchType + serde::Serialize + serde::de::DeserializeOwned + MatchNameAndType + MatchType + MatchFirstType + serde::Serialize + serde::de::DeserializeOwned { /// Reset all executors in the tuple /// This is called right before the next execution. @@ -105,6 +105,10 @@ impl TimeObserver { last_runtime: None, } } + + pub fn last_runtime(&self) -> &Option { + &self.last_runtime + } } impl Observer for TimeObserver {