From ab6026535c8f00c37c13a8c1301dac755e21e7d4 Mon Sep 17 00:00:00 2001 From: Alwin Berger Date: Fri, 8 Nov 2024 11:05:36 +0100 Subject: [PATCH] rate-limit testcase printing --- fuzzers/FRET/src/fuzzer.rs | 4 +-- fuzzers/FRET/src/time/worst.rs | 66 +++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/fuzzers/FRET/src/fuzzer.rs b/fuzzers/FRET/src/fuzzer.rs index 0b58f92ee9..2dc028a3db 100644 --- a/fuzzers/FRET/src/fuzzer.rs +++ b/fuzzers/FRET/src/fuzzer.rs @@ -16,7 +16,7 @@ edges::{self, edges_map_mut_ptr, QemuEdgeCoverageHelper, MAX_EDGES_FOUND}, elf:: use rand::{SeedableRng, StdRng, Rng}; use crate::{ systemstate::{self, feedbacks::{DumpSystraceFeedback, SystraceErrorFeedback}, helpers::{get_function_range, load_symbol, try_load_symbol, QemuSystemStateHelper}, mutational::{input_bytes_to_interrupt_times, InterruptShiftStage, STGSnippetStage}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, GraphMaximizerCorpusScheduler, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}}, time::{ - clock::{ClockTimeFeedback, IcHist, QemuClockIncreaseFeedback, QemuClockObserver, FUZZ_START_TIMESTAMP, QEMU_ICOUNT_SHIFT, QEMU_ISNS_PER_USEC}, qemustate::QemuStateRestoreHelper, worst::{AlwaysTrueFeedback, ExecTimeIncFeedback, TimeMaximizerCorpusScheduler, TimeProbMassScheduler, TimeStateMaximizerCorpusScheduler} + clock::{ClockTimeFeedback, IcHist, QemuClockIncreaseFeedback, QemuClockObserver, FUZZ_START_TIMESTAMP, QEMU_ICOUNT_SHIFT, QEMU_ISNS_PER_USEC}, qemustate::QemuStateRestoreHelper, worst::{AlwaysTrueFeedback, ExecTimeIncFeedback, RateLimitedMonitor, TimeMaximizerCorpusScheduler, TimeProbMassScheduler, TimeStateMaximizerCorpusScheduler} } }; use std::time::SystemTime; @@ -677,7 +677,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| { #[cfg(feature = "singlecore")] { - let monitor = SimplePrintingMonitor::new(); + let monitor = RateLimitedMonitor::new(); #[cfg(not(feature = "restarting"))] { let mgr = SimpleEventManager::new(monitor); diff --git a/fuzzers/FRET/src/time/worst.rs b/fuzzers/FRET/src/time/worst.rs index 69f7cd3c30..d2ccad8dd4 100644 --- a/fuzzers/FRET/src/time/worst.rs +++ b/fuzzers/FRET/src/time/worst.rs @@ -4,7 +4,7 @@ use libafl::inputs::BytesInput; use libafl::inputs::HasTargetBytes; use libafl::feedbacks::MapIndexesMetadata; use libafl::corpus::Testcase; -use libafl::prelude::{UsesInput}; +use libafl::prelude::{ClientStats, Monitor, SimplePrintingMonitor, UsesInput}; use core::marker::PhantomData; use libafl::schedulers::{MinimizerScheduler, ProbabilitySamplingScheduler, TestcaseScore}; use std::path::PathBuf; @@ -22,11 +22,12 @@ use libafl_qemu::edges::QemuEdgesMapMetadata; use libafl::observers::MapObserver; use serde::{Deserialize, Serialize}; use std::cmp; +use std::time::Duration; +use std::time::Instant; +use std::ops::Sub; use libafl_bolts::{ - Named, - HasLen, - AsSlice, + AsSlice, ClientId, HasLen, Named }; use libafl::{ observers::Observer, @@ -432,4 +433,61 @@ where let tns : i64 = et.as_nanos().try_into().expect("failed to convert time"); Ok(((tns as f64)/1000.0).powf(2.0)) //microseconds } +} + + +/// Monitor that prints with a limited rate. +#[derive(Debug, Clone)] +pub struct RateLimitedMonitor { + inner: SimplePrintingMonitor, + last: Instant, +} + +impl Monitor for RateLimitedMonitor { + /// The client monitor, mutable + fn client_stats_mut(&mut self) -> &mut Vec { + self.inner.client_stats_mut() + } + + /// The client monitor + fn client_stats(&self) -> &[ClientStats] { + self.inner.client_stats() + } + + /// Time this fuzzing run stated + fn start_time(&self) -> Duration { + self.inner.start_time() + } + + /// Time this fuzzing run stated + fn set_start_time(&mut self, time: Duration) { + self.inner.set_start_time(time); + } + + #[inline] + fn display(&mut self, event_msg: &str, sender_id: ClientId) { + let now = Instant::now(); + const RATE : Duration = Duration::from_secs(5); + if event_msg!="Testcase" || now.duration_since(self.last) > RATE { + self.inner.display(event_msg, sender_id); + self.last = now; + } + } +} + +impl RateLimitedMonitor { + /// Create new [`NopMonitor`] + #[must_use] + pub fn new() -> Self { + Self { + inner: SimplePrintingMonitor::new(), + last: Instant::now().sub(Duration::from_secs(7200)), + } + } +} + +impl Default for RateLimitedMonitor { + fn default() -> Self { + Self::new() + } } \ No newline at end of file