libafl_libfuzzer 0.16.0

libFuzzer shim which uses LibAFL with common defaults
use std::{collections::BTreeSet, marker::PhantomData};

use hashbrown::HashMap;
use libafl::{
    Error, HasMetadata,
    corpus::{Corpus, CorpusId, Testcase},
    feedbacks::MapNoveltiesMetadata,
    inputs::Input,
    schedulers::{RemovableScheduler, Scheduler},
    state::HasCorpus,
};

#[derive(Debug, Clone)]
pub struct MergeScheduler<I, S> {
    mapping: HashMap<usize, CorpusId>,
    all: BTreeSet<CorpusId>,
    phantom: PhantomData<(I, S)>,
}

impl<I, S> RemovableScheduler<I, S> for MergeScheduler<I, S>
where
    I: Input,
    S: HasCorpus<I>,
{
    fn on_remove(
        &mut self,
        _state: &mut S,
        id: CorpusId,
        _testcase: &Option<Testcase<I>>,
    ) -> Result<(), Error> {
        self.all.remove(&id);
        Ok(())
    }
}

impl<I, S> Scheduler<I, S> for MergeScheduler<I, S>
where
    S: HasCorpus<I>,
{
    fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
        self.all.insert(id);
        let testcase = state.corpus().get(id)?.borrow();
        let meta = testcase.metadata::<MapNoveltiesMetadata>()?;
        for cov_ in &meta.list {
            self.mapping.insert(*cov_, id);
        }
        Ok(())
    }

    fn next(&mut self, _state: &mut S) -> Result<CorpusId, Error> {
        unimplemented!("Not suitable for actual scheduling.");
    }

    fn set_current_scheduled(
        &mut self,
        state: &mut S,
        next_id: Option<CorpusId>,
    ) -> Result<(), Error> {
        *state.corpus_mut().current_mut() = next_id;
        Ok(())
    }
}

impl<I, S> MergeScheduler<I, S> {
    pub fn new() -> Self {
        Self {
            mapping: HashMap::default(),
            all: BTreeSet::default(),
            phantom: PhantomData,
        }
    }

    pub fn removable(&self) -> BTreeSet<CorpusId> {
        self.all
            .difference(&self.mapping.values().copied().collect())
            .copied()
            .collect()
    }

    pub fn current(&self) -> &BTreeSet<CorpusId> {
        &self.all
    }
}