#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "RUSTC_IS_NIGHTLY", feature(specialization))]
#[macro_use]
extern crate alloc;
#[macro_use]
extern crate static_assertions;
#[cfg(feature = "std")]
extern crate ctor;
#[cfg(feature = "std")]
pub use ctor::ctor;
#[cfg(feature = "libafl_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate libafl_derive;
#[cfg(feature = "libafl_derive")]
#[doc(hidden)]
pub use libafl_derive::*;
pub mod bolts;
pub mod corpus;
pub mod events;
pub mod executors;
pub mod feedbacks;
pub mod generators;
pub mod inputs;
pub mod mutators;
pub mod observers;
pub mod stages;
pub mod state;
pub mod stats;
pub mod utils;
pub mod fuzzer;
pub use fuzzer::*;
use alloc::string::String;
use core::fmt;
#[cfg(feature = "std")]
use std::{env::VarError, io, num::ParseIntError, string::FromUtf8Error};
#[derive(Debug)]
pub enum Error {
Serialize(String),
#[cfg(feature = "llmp_compression")]
Compression(String),
#[cfg(feature = "std")]
File(io::Error),
EmptyOptional(String),
KeyNotFound(String),
Empty(String),
IteratorEnd(String),
NotImplemented(String),
IllegalState(String),
IllegalArgument(String),
ShuttingDown,
Unknown(String),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Serialize(s) => write!(f, "Error in Serialization: `{0}`", &s),
#[cfg(feature = "llmp_compression")]
Self::Compression(s) => write!(f, "Error in Compression: `{0}`", &s),
#[cfg(feature = "std")]
Self::File(err) => write!(f, "File IO failed: {:?}", &err),
Self::EmptyOptional(s) => write!(f, "Optional value `{0}` was not set", &s),
Self::KeyNotFound(s) => write!(f, "Key `{0}` not in Corpus", &s),
Self::Empty(s) => write!(f, "No items in {0}", &s),
Self::IteratorEnd(s) => {
write!(f, "All elements have been processed in {0} iterator", &s)
}
Self::NotImplemented(s) => write!(f, "Not implemented: {0}", &s),
Self::IllegalState(s) => write!(f, "Illegal state: {0}", &s),
Self::IllegalArgument(s) => write!(f, "Illegal argument: {0}", &s),
Self::ShuttingDown => write!(f, "Shutting down!"),
Self::Unknown(s) => write!(f, "Unknown error: {0}", &s),
}
}
}
impl From<postcard::Error> for Error {
fn from(err: postcard::Error) -> Self {
Self::Serialize(format!("{:?}", err))
}
}
#[cfg(feature = "llmp_compression")]
impl From<compression::prelude::CompressionError> for Error {
fn from(err: compression::prelude::CompressionError) -> Self {
Self::Compression(format!("{:?}", err))
}
}
#[cfg(feature = "std")]
impl From<serde_json::Error> for Error {
fn from(err: serde_json::Error) -> Self {
Self::Serialize(format!("{:?}", err))
}
}
#[cfg(feature = "std")]
impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
Self::File(err)
}
}
#[cfg(feature = "std")]
impl From<FromUtf8Error> for Error {
fn from(err: FromUtf8Error) -> Self {
Self::Unknown(format!("Could not convert byte to utf-8: {:?}", err))
}
}
#[cfg(feature = "std")]
impl From<VarError> for Error {
fn from(err: VarError) -> Self {
Self::Empty(format!("Could not get env var: {:?}", err))
}
}
#[cfg(feature = "std")]
impl From<ParseIntError> for Error {
fn from(err: ParseIntError) -> Self {
Self::Unknown(format!("Failed to parse Int: {:?}", err))
}
}
#[cfg(feature = "std")]
#[cfg(test)]
mod tests {
use crate::{
bolts::tuples::tuple_list,
corpus::{Corpus, InMemoryCorpus, RandCorpusScheduler, Testcase},
executors::{ExitKind, InProcessExecutor},
inputs::BytesInput,
mutators::{mutations::BitFlipMutator, StdScheduledMutator},
stages::StdMutationalStage,
state::{HasCorpus, State},
stats::SimpleStats,
utils::StdRand,
Fuzzer, StdFuzzer,
};
#[cfg(feature = "std")]
use crate::events::SimpleEventManager;
#[test]
#[allow(clippy::similar_names)]
fn test_fuzzer() {
let rand = StdRand::with_seed(0);
let mut corpus = InMemoryCorpus::<BytesInput>::new();
let testcase = Testcase::new(vec![0; 4]);
corpus.add(testcase).unwrap();
let mut state = State::new(
rand,
corpus,
tuple_list!(),
InMemoryCorpus::<BytesInput>::new(),
tuple_list!(),
);
let stats = SimpleStats::new(|s| {
println!("{}", s);
});
let mut event_manager = SimpleEventManager::new(stats);
let mut harness = |_buf: &[u8]| ExitKind::Ok;
let mut executor = InProcessExecutor::new(
&mut harness,
tuple_list!(),
&mut state,
&mut event_manager,
)
.unwrap();
let mutator = StdScheduledMutator::new(tuple_list!(BitFlipMutator::new()));
let stage = StdMutationalStage::new(mutator);
let scheduler = RandCorpusScheduler::new();
let mut fuzzer = StdFuzzer::new(tuple_list!(stage));
for i in 0..1000 {
fuzzer
.fuzz_one(&mut state, &mut executor, &mut event_manager, &scheduler)
.unwrap_or_else(|_| panic!("Error in iter {}", i));
}
let state_serialized = postcard::to_allocvec(&state).unwrap();
let state_deserialized: State<
InMemoryCorpus<BytesInput>,
(),
BytesInput,
(),
StdRand,
InMemoryCorpus<BytesInput>,
> = postcard::from_bytes(state_serialized.as_slice()).unwrap();
assert_eq!(state.corpus().count(), state_deserialized.corpus().count());
let corpus_serialized = postcard::to_allocvec(state.corpus()).unwrap();
let corpus_deserialized: InMemoryCorpus<BytesInput> =
postcard::from_bytes(corpus_serialized.as_slice()).unwrap();
assert_eq!(state.corpus().count(), corpus_deserialized.count());
}
}