Skip to content

Commit

Permalink
Reducing type parameters and bounds from Scheduler (AFLplusplus#2544)
Browse files Browse the repository at this point in the history
* actually reducing type parameters

* no std

* aa

* aa

* a
  • Loading branch information
tokatoka authored Sep 23, 2024
1 parent 3577986 commit cbfd194
Show file tree
Hide file tree
Showing 14 changed files with 341 additions and 376 deletions.
2 changes: 1 addition & 1 deletion fuzzers/others/push_stage_harness/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ pub fn main() {
let testcase = Testcase::new(BytesInput::new(b"aaaa".to_vec()));
//self.feedback_mut().append_metadata(state, &mut testcase)?;
let idx = state.corpus_mut().add(testcase).unwrap();
scheduler.on_add(&mut state, idx).unwrap();
<QueueScheduler as Scheduler<BytesInput, _>>::on_add(&mut scheduler, &mut state, idx).unwrap();

// A fuzzer with feedbacks and a corpus scheduler
let fuzzer = StdFuzzer::new(scheduler, feedback, objective);
Expand Down
9 changes: 1 addition & 8 deletions libafl/src/corpus/minimizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use crate::{
corpus::Corpus,
events::{Event, EventFirer, LogSeverity},
executors::{Executor, HasObservers},
inputs::UsesInput,
monitors::{AggregatorOps, UserStats, UserStatsValue},
observers::{MapObserver, ObserversTuple},
schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore},
Expand Down Expand Up @@ -57,13 +56,7 @@ pub struct MapCorpusMinimizer<C, E, O, T, TS> {
}

/// Standard corpus minimizer, which weights inputs by length and time.
pub type StdCorpusMinimizer<C, E, O, T> = MapCorpusMinimizer<
C,
E,
O,
T,
LenTimeMulTestcaseScore<<E as UsesInput>::Input, <E as UsesState>::State>,
>;
pub type StdCorpusMinimizer<C, E, O, T> = MapCorpusMinimizer<C, E, O, T, LenTimeMulTestcaseScore>;

impl<C, E, O, T, TS> MapCorpusMinimizer<C, E, O, T, TS>
where
Expand Down
58 changes: 15 additions & 43 deletions libafl/src/corpus/testcase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@ use libafl_bolts::{serdeany::SerdeAnyMap, HasLen};
use serde::{Deserialize, Serialize};

use super::Corpus;
use crate::{
corpus::CorpusId,
inputs::{Input, UsesInput},
Error, HasMetadata,
};
use crate::{corpus::CorpusId, inputs::UsesInput, Error, HasMetadata};

/// Shorthand to receive a [`Ref`] or [`RefMut`] to a stored [`Testcase`], by [`CorpusId`].
/// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives.
Expand All @@ -38,11 +34,7 @@ pub trait HasTestcase: UsesInput {

/// An entry in the [`Testcase`] Corpus
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")]
pub struct Testcase<I>
where
I: Input,
{
pub struct Testcase<I> {
/// The [`Input`] of this [`Testcase`], or `None`, if it is not currently in memory
input: Option<I>,
/// The filename for this [`Testcase`]
Expand Down Expand Up @@ -77,10 +69,7 @@ where
hit_objectives: Vec<Cow<'static, str>>,
}

impl<I> HasMetadata for Testcase<I>
where
I: Input,
{
impl<I> HasMetadata for Testcase<I> {
/// Get all the metadata into an [`hashbrown::HashMap`]
#[inline]
fn metadata_map(&self) -> &SerdeAnyMap {
Expand All @@ -95,10 +84,7 @@ where
}

/// Impl of a testcase
impl<I> Testcase<I>
where
I: Input,
{
impl<I> Testcase<I> {
/// Returns this [`Testcase`] with a loaded `Input`]
pub fn load_input<C: Corpus<Input = I>>(&mut self, corpus: &C) -> Result<&I, Error> {
corpus.load_input_into(self)?;
Expand All @@ -120,8 +106,7 @@ where

/// Set the input
#[inline]
pub fn set_input(&mut self, mut input: I) {
input.wrapped_as_testcase();
pub fn set_input(&mut self, input: I) {
self.input = Some(input);
}

Expand Down Expand Up @@ -249,8 +234,7 @@ where

/// Create a new Testcase instance given an input
#[inline]
pub fn new(mut input: I) -> Self {
input.wrapped_as_testcase();
pub fn new(input: I) -> Self {
Self {
input: Some(input),
filename: None,
Expand All @@ -275,8 +259,7 @@ where

/// Creates a testcase, attaching the id of the parent
/// that this [`Testcase`] was derived from on creation
pub fn with_parent_id(mut input: I, parent_id: CorpusId) -> Self {
input.wrapped_as_testcase();
pub fn with_parent_id(input: I, parent_id: CorpusId) -> Self {
Testcase {
input: Some(input),
filename: None,
Expand All @@ -299,10 +282,9 @@ where
}
}

/// Create a new Testcase instance given an [`Input`] and a `filename`
/// Create a new Testcase instance given an input and a `filename`
#[inline]
pub fn with_filename(mut input: I, filename: String) -> Self {
input.wrapped_as_testcase();
pub fn with_filename(input: I, filename: String) -> Self {
Self {
input: Some(input),
filename: Some(filename),
Expand All @@ -325,10 +307,9 @@ where
}
}

/// Create a new Testcase instance given an [`Input`] and the number of executions
/// Create a new Testcase instance given an input and the number of executions
#[inline]
pub fn with_executions(mut input: I, executions: u64) -> Self {
input.wrapped_as_testcase();
pub fn with_executions(input: I, executions: u64) -> Self {
Self {
input: Some(input),
filename: None,
Expand Down Expand Up @@ -378,10 +359,7 @@ where
}
}

impl<I> Default for Testcase<I>
where
I: Input,
{
impl<I> Default for Testcase<I> {
/// Create a new default Testcase
#[inline]
fn default() -> Self {
Expand Down Expand Up @@ -411,7 +389,7 @@ where
/// Impl of a testcase when the input has len
impl<I> Testcase<I>
where
I: Input + HasLen,
I: HasLen,
{
/// Get the cached `len`. Will `Error::EmptyOptional` if `len` is not yet cached.
#[inline]
Expand Down Expand Up @@ -441,10 +419,7 @@ where
}

/// Create a testcase from an input
impl<I> From<I> for Testcase<I>
where
I: Input,
{
impl<I> From<I> for Testcase<I> {
fn from(input: I) -> Self {
Testcase::new(input)
}
Expand Down Expand Up @@ -563,10 +538,7 @@ impl SchedulerTestcaseMetadata {
libafl_bolts::impl_serdeany!(SchedulerTestcaseMetadata);

#[cfg(feature = "std")]
impl<I> Drop for Testcase<I>
where
I: Input,
{
impl<I> Drop for Testcase<I> {
fn drop(&mut self) {
if let Some(filename) = &self.filename {
let mut path = PathBuf::from(filename);
Expand Down
6 changes: 0 additions & 6 deletions libafl/src/inputs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ pub trait Input: Clone + Serialize + serde::de::DeserializeOwned + Debug {

/// Generate a name for this input
fn generate_name(&self, id: Option<CorpusId>) -> String;

/// An hook executed if the input is stored as `Testcase`
fn wrapped_as_testcase(&mut self) {}
}

/// An input for the target
Expand All @@ -89,9 +86,6 @@ pub trait Input: Clone + Serialize + serde::de::DeserializeOwned + Debug {

/// Generate a name for this input, the user is responsible for making each name of testcase unique.
fn generate_name(&self, id: Option<CorpusId>) -> String;

/// An hook executed if the input is stored as `Testcase`
fn wrapped_as_testcase(&mut self) {}
}

/// Convert between two input types with a state
Expand Down
48 changes: 28 additions & 20 deletions libafl/src/schedulers/accounting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,16 @@ use core::{
};

use hashbrown::HashMap;
use libafl_bolts::{rands::Rand, HasLen, HasRefCnt};
use libafl_bolts::{rands::Rand, tuples::MatchName, HasLen, HasRefCnt};
use serde::{Deserialize, Serialize};

use super::IndexesLenTimeMinimizerScheduler;
use crate::{
corpus::{Corpus, CorpusId},
feedbacks::MapIndexesMetadata,
inputs::Input,
observers::{CanTrack, ObserversTuple},
observers::CanTrack,
schedulers::{
minimizer::{IsFavoredMetadata, MinimizerScheduler, DEFAULT_SKIP_NON_FAVORED_PROB},
LenTimeMulTestcaseScore, Scheduler,
Scheduler,
},
state::{HasCorpus, HasRand},
Error, HasMetadata,
Expand Down Expand Up @@ -105,17 +104,17 @@ impl TopAccountingMetadata {

/// A minimizer scheduler using coverage accounting
#[derive(Debug)]
pub struct CoverageAccountingScheduler<'a, CS, I, O, S> {
pub struct CoverageAccountingScheduler<'a, CS, O> {
accounting_map: &'a [u32],
skip_non_favored_prob: f64,
inner: MinimizerScheduler<CS, LenTimeMulTestcaseScore<I, S>, I, MapIndexesMetadata, O, S>,
inner: IndexesLenTimeMinimizerScheduler<CS, O>,
}

impl<'a, CS, I, O, S> Scheduler<I, S> for CoverageAccountingScheduler<'a, CS, I, O, S>
impl<'a, CS, I, O, S> Scheduler<I, S> for CoverageAccountingScheduler<'a, CS, O>
where
CS: Scheduler<I, S>,
S: HasCorpus<Input = I> + HasMetadata + HasRand + Debug,
I: HasLen + Input,
S: HasCorpus<Input = I> + HasMetadata + HasRand,
I: HasLen,
O: CanTrack,
{
fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
Expand All @@ -125,7 +124,7 @@ where

fn on_evaluation<OT>(&mut self, state: &mut S, input: &I, observers: &OT) -> Result<(), Error>
where
OT: ObserversTuple<S>,
OT: MatchName,
{
self.inner.on_evaluation(state, input, observers)
}
Expand Down Expand Up @@ -169,17 +168,17 @@ where
}
}

impl<'a, CS, I, O, S> CoverageAccountingScheduler<'a, CS, I, O, S>
impl<'a, CS, O> CoverageAccountingScheduler<'a, CS, O>
where
CS: Scheduler<I, S>,
S: HasCorpus<Input = I> + HasMetadata + HasRand + Debug,
I: HasLen + Input,
O: CanTrack,
{
/// Update the `Corpus` score
#[allow(clippy::unused_self)]
#[allow(clippy::cast_possible_wrap)]
pub fn update_accounting_score(&self, state: &mut S, id: CorpusId) -> Result<(), Error> {
pub fn update_accounting_score<S>(&self, state: &mut S, id: CorpusId) -> Result<(), Error>
where
S: HasCorpus + HasMetadata,
{
let mut indexes = vec![];
let mut new_favoreds = vec![];
{
Expand Down Expand Up @@ -264,7 +263,10 @@ where

/// Cull the `Corpus`
#[allow(clippy::unused_self)]
pub fn accounting_cull(&self, state: &S) -> Result<(), Error> {
pub fn accounting_cull<S>(&self, state: &S) -> Result<(), Error>
where
S: HasCorpus + HasMetadata,
{
let Some(top_rated) = state.metadata_map().get::<TopAccountingMetadata>() else {
return Ok(());
};
Expand All @@ -285,7 +287,10 @@ where
/// and has a default probability to skip non-faved Testcases of [`DEFAULT_SKIP_NON_FAVORED_PROB`].
///
/// Provide the observer responsible for determining new indexes.
pub fn new(observer: &O, state: &mut S, base: CS, accounting_map: &'a [u32]) -> Self {
pub fn new<S>(observer: &O, state: &mut S, base: CS, accounting_map: &'a [u32]) -> Self
where
S: HasMetadata,
{
match state.metadata_map().get::<TopAccountingMetadata>() {
Some(meta) => {
if meta.max_accounting.len() != accounting_map.len() {
Expand All @@ -307,13 +312,16 @@ where
/// and has a non-default probability to skip non-faved Testcases using (`skip_non_favored_prob`).
///
/// Provide the observer responsible for determining new indexes.
pub fn with_skip_prob(
pub fn with_skip_prob<S>(
observer: &O,
state: &mut S,
base: CS,
skip_non_favored_prob: f64,
accounting_map: &'a [u32],
) -> Self {
) -> Self
where
S: HasMetadata,
{
match state.metadata_map().get::<TopAccountingMetadata>() {
Some(meta) => {
if meta.max_accounting.len() != accounting_map.len() {
Expand Down
Loading

0 comments on commit cbfd194

Please sign in to comment.