fixed build
This commit is contained in:
parent
77b736ab3b
commit
a24d1edd80
@ -1,3 +1,4 @@
|
|||||||
|
extern crate alloc;
|
||||||
pub mod testcase;
|
pub mod testcase;
|
||||||
pub use testcase::{Testcase, TestcaseMetadata};
|
pub use testcase::{Testcase, TestcaseMetadata};
|
||||||
|
|
||||||
@ -5,10 +6,10 @@ use crate::inputs::Input;
|
|||||||
use crate::utils::{HasRand, Rand};
|
use crate::utils::{HasRand, Rand};
|
||||||
use crate::AflError;
|
use crate::AflError;
|
||||||
|
|
||||||
|
use alloc::rc::Rc;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use std::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
pub trait HasEntriesVec<I>
|
pub trait HasEntriesVec<I>
|
||||||
where
|
where
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
|
extern crate alloc;
|
||||||
use crate::inputs::Input;
|
use crate::inputs::Input;
|
||||||
use crate::AflError;
|
use crate::AflError;
|
||||||
|
|
||||||
use hashbrown::HashMap;
|
use alloc::rc::Rc;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
|
use hashbrown::HashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
// TODO: Give example
|
// TODO: Give example
|
||||||
/// Metadata for a testcase
|
/// Metadata for a testcase
|
||||||
|
@ -1,19 +1,16 @@
|
|||||||
use crate::corpus::testcase::{Testcase, TestcaseMetadata};
|
extern crate alloc;
|
||||||
use crate::corpus::Corpus;
|
use crate::corpus::testcase::Testcase;
|
||||||
use crate::executors::Executor;
|
|
||||||
use crate::feedbacks::Feedback;
|
use crate::feedbacks::Feedback;
|
||||||
use crate::inputs::Input;
|
use crate::inputs::Input;
|
||||||
use crate::stages::Stage;
|
use crate::stages::Stage;
|
||||||
use crate::AflError;
|
use crate::AflError;
|
||||||
|
|
||||||
|
use alloc::rc::Rc;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
pub trait Engine<I, C, E>
|
pub trait Engine<I>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I>,
|
|
||||||
E: Executor<I, C>,
|
|
||||||
{
|
{
|
||||||
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>>;
|
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>>;
|
||||||
|
|
||||||
@ -31,17 +28,12 @@ where
|
|||||||
self.stages_mut().push(stage);
|
self.stages_mut().push(stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn executor(&self) -> &E;
|
|
||||||
|
|
||||||
fn executor_mut(&mut self) -> &mut E;
|
|
||||||
|
|
||||||
fn fuzz_one(&mut self, testcase: &Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
|
fn fuzz_one(&mut self, testcase: &Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
|
||||||
for stage in self.stages_mut() {
|
for stage in self.stages_mut() {
|
||||||
stage.perform(&testcase)?;
|
stage.perform(&testcase)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DefaultEngine<I>
|
pub struct DefaultEngine<I>
|
||||||
@ -52,11 +44,9 @@ where
|
|||||||
stages: Vec<Box<dyn Stage<I>>>,
|
stages: Vec<Box<dyn Stage<I>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, C, E> Engine<I, C, E> for DefaultEngine<I>
|
impl<I> Engine<I> for DefaultEngine<I>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I>,
|
|
||||||
E: Executor<I, C>,
|
|
||||||
{
|
{
|
||||||
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>> {
|
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>> {
|
||||||
&self.feedbacks
|
&self.feedbacks
|
||||||
@ -73,61 +63,39 @@ where
|
|||||||
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<I>>> {
|
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<I>>> {
|
||||||
&mut self.stages
|
&mut self.stages
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I> DefaultEngine<I>
|
impl<I> DefaultEngine<I>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
pub fn new(executor: E) -> Self {
|
pub fn new() -> Self {
|
||||||
DefaultEngine {
|
DefaultEngine {
|
||||||
feedbacks: vec![],
|
feedbacks: vec![],
|
||||||
stages: vec![],
|
stages: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_rr(executor: E) -> Rc<RefCell<Self>> {
|
pub fn new_rr() -> Rc<RefCell<Self>> {
|
||||||
Rc::new(RefCell::new(Self::new(executor)))
|
Rc::new(RefCell::new(Self::new()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FuzzState<I, C>
|
|
||||||
where
|
|
||||||
I: Input,
|
|
||||||
C: Corpus<I>,
|
|
||||||
{
|
|
||||||
|
|
||||||
corpus: C,
|
|
||||||
current_input: Option<I>,
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I, C> FuzzState<I, C>
|
|
||||||
where
|
|
||||||
I: Input,
|
|
||||||
C: Corpus<I>,
|
|
||||||
{
|
|
||||||
pub fn new(corpus: C) -> Self {
|
|
||||||
Self{corpus: corpus, current_input: None}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::corpus::{Corpus, InMemoryCorpus, Testcase};
|
use crate::corpus::{Corpus, InMemoryCorpus, Testcase};
|
||||||
use crate::engines::{DefaultEngine, Engine, FuzzState};
|
use crate::engines::{DefaultEngine, Engine};
|
||||||
use crate::executors::inmemory::InMemoryExecutor;
|
use crate::executors::inmemory::InMemoryExecutor;
|
||||||
use crate::executors::{Executor, ExitKind};
|
use crate::executors::{Executor, ExitKind};
|
||||||
use crate::inputs::bytes::BytesInput;
|
use crate::inputs::bytes::BytesInput;
|
||||||
use crate::mutators::DefaultScheduledMutator;
|
use crate::mutators::scheduled::{
|
||||||
use crate::mutators::scheduled::mutation_bitflip;
|
mutation_bitflip, ComposedByMutations, DefaultScheduledMutator,
|
||||||
|
};
|
||||||
use crate::stages::mutational::DefaultMutationalStage;
|
use crate::stages::mutational::DefaultMutationalStage;
|
||||||
use crate::stages::Stage;
|
|
||||||
use crate::utils::Xoshiro256StarRand;
|
use crate::utils::Xoshiro256StarRand;
|
||||||
|
|
||||||
fn harness<I, C>(_executor: &dyn Executor<I, C>, _buf: &[u8]) -> ExitKind {
|
fn harness<I>(_executor: &dyn Executor<I>, _buf: &[u8]) -> ExitKind {
|
||||||
ExitKind::Ok
|
ExitKind::Ok
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,15 +103,14 @@ mod tests {
|
|||||||
fn test_engine() {
|
fn test_engine() {
|
||||||
let rand = Xoshiro256StarRand::preseeded_rr();
|
let rand = Xoshiro256StarRand::preseeded_rr();
|
||||||
|
|
||||||
let corpus = InMemoryCorpus::<BytesInput, _>::new(&rand);
|
let mut corpus = InMemoryCorpus::<BytesInput, _>::new(&rand);
|
||||||
let testcase = Testcase::new_rr(BytesInput::new(vec![0; 4]));
|
let testcase = Testcase::new_rr(BytesInput::new(vec![0; 4]));
|
||||||
corpus.add(testcase);
|
corpus.add(testcase);
|
||||||
let executor = InMemoryExecutor::new(harness);
|
let executor = InMemoryExecutor::new_rr(harness);
|
||||||
let state = FuzzState::new(corpus);
|
let mut engine = DefaultEngine::new();
|
||||||
let engine = DefaultEngine::new(executor);
|
let mut mutator = DefaultScheduledMutator::new(&rand);
|
||||||
let mutator = DefaultScheduledMutator::new(&rand);
|
|
||||||
mutator.add_mutation(mutation_bitflip);
|
mutator.add_mutation(mutation_bitflip);
|
||||||
let stage = DefaultMutationalStage::new(&rand, &engine, mutator);
|
let stage = DefaultMutationalStage::new(&rand, &executor, mutator);
|
||||||
engine.add_stage(Box::new(stage));
|
engine.add_stage(Box::new(stage));
|
||||||
engine.fuzz_one(&corpus.next().unwrap()).unwrap();
|
engine.fuzz_one(&corpus.next().unwrap()).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,34 @@
|
|||||||
use crate::executors::Corpus;
|
extern crate alloc;
|
||||||
|
use crate::feedbacks::Feedback;
|
||||||
use crate::inputs::Input;
|
use crate::inputs::Input;
|
||||||
use crate::observers::Observer;
|
use crate::observers::Observer;
|
||||||
use crate::AflError;
|
use crate::AflError;
|
||||||
|
use alloc::rc::Rc;
|
||||||
|
use core::cell::RefCell;
|
||||||
|
|
||||||
use crate::executors::{Executor, ExitKind};
|
use crate::executors::{Executor, ExitKind};
|
||||||
|
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
type HarnessFunction<I, C> = fn(&dyn Executor<I, C>, &[u8]) -> ExitKind;
|
type HarnessFunction<I> = fn(&dyn Executor<I>, &[u8]) -> ExitKind;
|
||||||
|
|
||||||
pub struct InMemoryExecutor<I, C>
|
pub struct InMemoryExecutor<I>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I>,
|
|
||||||
{
|
{
|
||||||
observers: Vec<Box<dyn Observer>>,
|
observers: Vec<Box<dyn Observer>>,
|
||||||
harness: HarnessFunction<I, C>,
|
harness: HarnessFunction<I>,
|
||||||
|
feedbacks: Vec<Box<dyn Feedback<I>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut CURRENT_INMEMORY_EXECUTOR_PTR: *const c_void = ptr::null();
|
static mut CURRENT_INMEMORY_EXECUTOR_PTR: *const c_void = ptr::null();
|
||||||
|
|
||||||
impl<I, C> Executor<I, C> for InMemoryExecutor<I, C>
|
impl<I> Executor<I> for InMemoryExecutor<I>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I>,
|
|
||||||
{
|
{
|
||||||
fn run_target(&mut self, input: &mut I) -> Result<ExitKind, AflError> {
|
fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError> {
|
||||||
let bytes = input.serialize()?;
|
let bytes = input.serialize()?;
|
||||||
unsafe {
|
unsafe {
|
||||||
CURRENT_INMEMORY_EXECUTOR_PTR = self as *const InMemoryExecutor<I> as *const c_void;
|
CURRENT_INMEMORY_EXECUTOR_PTR = self as *const InMemoryExecutor<I> as *const c_void;
|
||||||
@ -59,22 +61,38 @@ where
|
|||||||
fn observers(&self) -> &Vec<Box<dyn Observer>> {
|
fn observers(&self) -> &Vec<Box<dyn Observer>> {
|
||||||
&self.observers
|
&self.observers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>> {
|
||||||
|
&self.feedbacks
|
||||||
|
}
|
||||||
|
|
||||||
|
fn feedbacks_mut(&mut self) -> &mut Vec<Box<dyn Feedback<I>>> {
|
||||||
|
&mut self.feedbacks
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_feedback(&mut self, feedback: Box<dyn Feedback<I>>) {
|
||||||
|
self.feedbacks_mut().push(feedback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, C> InMemoryExecutor<I, C>
|
impl<I> InMemoryExecutor<I>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I>,
|
|
||||||
{
|
{
|
||||||
pub fn new(harness_fn: HarnessFunction<I, C>) -> Self {
|
pub fn new(harness_fn: HarnessFunction<I>) -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
os_signals::setup_crash_handlers::<I, Self>();
|
os_signals::setup_crash_handlers::<I>();
|
||||||
}
|
}
|
||||||
InMemoryExecutor {
|
InMemoryExecutor {
|
||||||
observers: vec![],
|
observers: vec![],
|
||||||
|
feedbacks: vec![],
|
||||||
harness: harness_fn,
|
harness: harness_fn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_rr(harness_fn: HarnessFunction<I>) -> Rc<RefCell<Self>> {
|
||||||
|
Rc::new(RefCell::new(Self::new(harness_fn)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
@ -167,8 +185,7 @@ compile_error!("InMemoryExecutor not yet supported on this OS");
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::executors::Corpus;
|
use crate::executors::inmemory::InMemoryExecutor;
|
||||||
use crate::executors::inmemory::InMemoryExecutor;
|
|
||||||
use crate::executors::{Executor, ExitKind};
|
use crate::executors::{Executor, ExitKind};
|
||||||
use crate::inputs::Input;
|
use crate::inputs::Input;
|
||||||
use crate::observers::Observer;
|
use crate::observers::Observer;
|
||||||
@ -196,16 +213,16 @@ use crate::executors::inmemory::InMemoryExecutor;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*fn test_harness_fn_nop(_executor: &dyn Executor<Corpus, NopInput>, buf: &[u8]) -> ExitKind {
|
fn test_harness_fn_nop(_executor: &dyn Executor<NopInput>, buf: &[u8]) -> ExitKind {
|
||||||
println! {"Fake exec with buf of len {}", buf.len()};
|
println! {"Fake exec with buf of len {}", buf.len()};
|
||||||
ExitKind::Ok
|
ExitKind::Ok
|
||||||
}*/
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_inmem_post_exec() {
|
fn test_inmem_post_exec() {
|
||||||
//let mut in_mem_executor = InMemoryExecutor::new(test_harness_fn_nop);
|
let mut in_mem_executor = InMemoryExecutor::new(test_harness_fn_nop);
|
||||||
let nopserver = Nopserver {};
|
let nopserver = Nopserver {};
|
||||||
//in_mem_executor.add_observer(Box::new(nopserver));
|
in_mem_executor.add_observer(Box::new(nopserver));
|
||||||
assert_eq!(in_mem_executor.post_exec_observers().is_err(), true);
|
assert_eq!(in_mem_executor.post_exec_observers().is_err(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,6 +230,6 @@ use crate::executors::inmemory::InMemoryExecutor;
|
|||||||
fn test_inmem_exec() {
|
fn test_inmem_exec() {
|
||||||
let mut in_mem_executor = InMemoryExecutor::new(test_harness_fn_nop);
|
let mut in_mem_executor = InMemoryExecutor::new(test_harness_fn_nop);
|
||||||
let mut input = NopInput {};
|
let mut input = NopInput {};
|
||||||
//assert!(in_mem_executor.run_target(&mut input).is_ok());
|
assert!(in_mem_executor.run_target(&mut input).is_ok());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
|
extern crate alloc;
|
||||||
pub mod inmemory;
|
pub mod inmemory;
|
||||||
|
|
||||||
use crate::corpus::Testcase;
|
use crate::corpus::Testcase;
|
||||||
use core::cell::RefCell;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use crate::corpus::Corpus;
|
|
||||||
use crate::corpus::TestcaseMetadata;
|
use crate::corpus::TestcaseMetadata;
|
||||||
use crate::feedbacks::Feedback;
|
use crate::feedbacks::Feedback;
|
||||||
use crate::inputs::Input;
|
use crate::inputs::Input;
|
||||||
use crate::observers::Observer;
|
use crate::observers::Observer;
|
||||||
use crate::AflError;
|
use crate::AflError;
|
||||||
|
use alloc::rc::Rc;
|
||||||
|
use core::cell::RefCell;
|
||||||
|
|
||||||
pub enum ExitKind {
|
pub enum ExitKind {
|
||||||
Ok,
|
Ok,
|
||||||
@ -19,13 +19,12 @@ pub enum ExitKind {
|
|||||||
|
|
||||||
// TODO unbox input
|
// TODO unbox input
|
||||||
|
|
||||||
pub trait Executor<I, C>
|
pub trait Executor<I>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I>,
|
|
||||||
{
|
{
|
||||||
/// Instruct the target about the input and run
|
/// Instruct the target about the input and run
|
||||||
fn run_target(&mut self, input: &mut I) -> Result<ExitKind, AflError>;
|
fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError>;
|
||||||
|
|
||||||
/// Reset the state of all the observes linked to this executor
|
/// Reset the state of all the observes linked to this executor
|
||||||
fn reset_observers(&mut self) -> Result<(), AflError>;
|
fn reset_observers(&mut self) -> Result<(), AflError>;
|
||||||
@ -45,21 +44,20 @@ where
|
|||||||
/// Returns vector of feebacks
|
/// Returns vector of feebacks
|
||||||
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>>;
|
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>>;
|
||||||
|
|
||||||
|
/// Returns vector of feebacks (mutable)
|
||||||
|
fn feedbacks_mut(&mut self) -> &mut Vec<Box<dyn Feedback<I>>>;
|
||||||
|
|
||||||
// TODO: Move to another struct, like evaluator?
|
// TODO: Move to another struct, like evaluator?
|
||||||
// In any case, the dependency on Corpus should probably go
|
// In any case, the dependency on Corpus should probably go
|
||||||
/// Runs the input and triggers observers and feedback
|
/// Runs the input and triggers observers and feedback
|
||||||
fn evaluate_input(
|
fn evaluate_input(&mut self, input: &I) -> Result<bool, AflError> {
|
||||||
&mut self,
|
|
||||||
corpus: &mut C,
|
|
||||||
input: &mut I,
|
|
||||||
) -> Result<bool, AflError> {
|
|
||||||
self.reset_observers()?;
|
self.reset_observers()?;
|
||||||
self.run_target(input)?;
|
self.run_target(input)?;
|
||||||
self.post_exec_observers()?;
|
self.post_exec_observers()?;
|
||||||
|
|
||||||
let mut metadatas: Vec<Box<dyn TestcaseMetadata>> = vec![];
|
let mut metadatas: Vec<Box<dyn TestcaseMetadata>> = vec![];
|
||||||
let mut rate_acc = 0;
|
let mut rate_acc = 0;
|
||||||
for feedback in self.feedbacks() {
|
for feedback in self.feedbacks_mut() {
|
||||||
let (rate, meta) = feedback.is_interesting(input);
|
let (rate, meta) = feedback.is_interesting(input);
|
||||||
rate_acc += rate;
|
rate_acc += rate;
|
||||||
if let Some(m) = meta {
|
if let Some(m) = meta {
|
||||||
@ -72,12 +70,11 @@ where
|
|||||||
for meta in metadatas {
|
for meta in metadatas {
|
||||||
new_entry.borrow_mut().add_metadata(meta);
|
new_entry.borrow_mut().add_metadata(meta);
|
||||||
}
|
}
|
||||||
corpus.add(new_entry);
|
//TODO corpus.add(new_entry);
|
||||||
|
|
||||||
Ok(true)
|
Ok(true)
|
||||||
} else {
|
} else {
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
|
extern crate alloc;
|
||||||
extern crate num;
|
extern crate num;
|
||||||
|
|
||||||
use crate::corpus::TestcaseMetadata;
|
use crate::corpus::TestcaseMetadata;
|
||||||
use crate::inputs::Input;
|
use crate::inputs::Input;
|
||||||
use crate::observers::MapObserver;
|
use crate::observers::MapObserver;
|
||||||
|
|
||||||
use num::Integer;
|
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use std::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
use num::Integer;
|
||||||
|
|
||||||
pub trait Feedback<I>
|
pub trait Feedback<I>
|
||||||
where
|
where
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
extern crate alloc;
|
||||||
use crate::inputs::{HasBytesVec, HasTargetBytes, Input};
|
use crate::inputs::{HasBytesVec, HasTargetBytes, Input};
|
||||||
use crate::AflError;
|
use crate::AflError;
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
extern crate alloc;
|
||||||
pub mod bytes;
|
pub mod bytes;
|
||||||
pub use bytes::BytesInput;
|
pub use bytes::BytesInput;
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
extern crate alloc;
|
||||||
use std::io;
|
use std::io;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
|
extern crate alloc;
|
||||||
pub mod scheduled;
|
pub mod scheduled;
|
||||||
|
pub use scheduled::ComposedByMutations;
|
||||||
pub use scheduled::DefaultScheduledMutator;
|
pub use scheduled::DefaultScheduledMutator;
|
||||||
pub use scheduled::HavocBytesMutator;
|
pub use scheduled::HavocBytesMutator;
|
||||||
pub use scheduled::ScheduledMutator;
|
pub use scheduled::ScheduledMutator;
|
||||||
|
|
||||||
use crate::corpus::Corpus;
|
|
||||||
use crate::inputs::Input;
|
use crate::inputs::Input;
|
||||||
use crate::utils::HasRand;
|
use crate::utils::HasRand;
|
||||||
use crate::AflError;
|
use crate::AflError;
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use crate::corpus::Corpus;
|
extern crate alloc;
|
||||||
use crate::inputs::{HasBytesVec, Input};
|
use crate::inputs::{HasBytesVec, Input};
|
||||||
use crate::mutators::Mutator;
|
use crate::mutators::Mutator;
|
||||||
use crate::utils::{HasRand, Rand};
|
use crate::utils::{HasRand, Rand};
|
||||||
use crate::AflError;
|
use crate::AflError;
|
||||||
|
|
||||||
|
use alloc::rc::Rc;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use std::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
/// The generic function type that identifies mutations
|
/// The generic function type that identifies mutations
|
||||||
type MutationFunction<M, I> = fn(&mut M, &mut I) -> Result<(), AflError>;
|
type MutationFunction<M, I> = fn(&mut M, &mut I) -> Result<(), AflError>;
|
||||||
@ -58,21 +58,19 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DefaultScheduledMutator<'a, I, C, R>
|
pub struct DefaultScheduledMutator<'a, I, R>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I>,
|
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
rand: Rc<RefCell<R>>,
|
rand: Rc<RefCell<R>>,
|
||||||
mutations: Vec<MutationFunction<Self, I>>,
|
mutations: Vec<MutationFunction<Self, I>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, I, C, R> HasRand for DefaultScheduledMutator<'_, I, C, R>
|
impl<'a, I, R> HasRand for DefaultScheduledMutator<'_, I, R>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
C: Corpus<I>,
|
|
||||||
{
|
{
|
||||||
type R = R;
|
type R = R;
|
||||||
|
|
||||||
@ -81,23 +79,20 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, I, R> Mutator<I> for DefaultScheduledMutator<'_, I, R>
|
||||||
impl<'a, I, C, R> Mutator<I> for DefaultScheduledMutator<'_, I, C, R>
|
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
C: Corpus<I>,
|
|
||||||
{
|
{
|
||||||
fn mutate(&mut self, input: &mut I, _stage_idx: i32) -> Result<(), AflError> {
|
fn mutate(&mut self, input: &mut I, _stage_idx: i32) -> Result<(), AflError> {
|
||||||
self.scheduled_mutate(input, _stage_idx)
|
self.scheduled_mutate(input, _stage_idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, I, C, R> ComposedByMutations<I> for DefaultScheduledMutator<'_, I, C, R>
|
impl<'a, I, R> ComposedByMutations<I> for DefaultScheduledMutator<'_, I, R>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
C: Corpus<I>,
|
|
||||||
{
|
{
|
||||||
fn mutation_by_idx(&self, index: usize) -> Result<MutationFunction<Self, I>, AflError> {
|
fn mutation_by_idx(&self, index: usize) -> Result<MutationFunction<Self, I>, AflError> {
|
||||||
if index >= self.mutations.len() {
|
if index >= self.mutations.len() {
|
||||||
@ -115,19 +110,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, I, C, R> ScheduledMutator<I> for DefaultScheduledMutator<'_, I, C, R>
|
impl<'a, I, R> ScheduledMutator<I> for DefaultScheduledMutator<'_, I, R>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
C: Corpus<I>,
|
|
||||||
{
|
{
|
||||||
// Just use the default methods
|
// Just use the default methods
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, I, C, R> DefaultScheduledMutator<'a, I, C, R>
|
impl<'a, I, R> DefaultScheduledMutator<'a, I, R>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I>,
|
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
/// Create a new DefaultScheduledMutator instance without mutations and corpus
|
/// Create a new DefaultScheduledMutator instance without mutations and corpus
|
||||||
@ -139,16 +132,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new DefaultScheduledMutator instance specifying mutations and corpus too
|
/// Create a new DefaultScheduledMutator instance specifying mutations and corpus too
|
||||||
pub fn new_all(
|
pub fn new_all(rand: &Rc<RefCell<R>>, mutations: Vec<MutationFunction<Self, I>>) -> Self {
|
||||||
rand: &Rc<RefCell<R>>,
|
|
||||||
mutations: Vec<MutationFunction<Self, I>>,
|
|
||||||
) -> Self {
|
|
||||||
DefaultScheduledMutator {
|
DefaultScheduledMutator {
|
||||||
rand: Rc::clone(rand),
|
rand: Rc::clone(rand),
|
||||||
mutations: mutations,
|
mutations: mutations,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bitflip mutation for inputs with a bytes vector
|
/// Bitflip mutation for inputs with a bytes vector
|
||||||
@ -209,15 +198,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, I, C, R> HavocBytesMutator<I, DefaultScheduledMutator<'a, I, C, R>>
|
impl<'a, I, R> HavocBytesMutator<I, DefaultScheduledMutator<'a, I, R>>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
C: Corpus<I>,
|
|
||||||
{
|
{
|
||||||
/// Create a new HavocBytesMutator instance wrapping DefaultScheduledMutator
|
/// Create a new HavocBytesMutator instance wrapping DefaultScheduledMutator
|
||||||
pub fn new_default(rand: &Rc<RefCell<R>>) -> Self {
|
pub fn new_default(rand: &Rc<RefCell<R>>) -> Self {
|
||||||
let mut scheduled = DefaultScheduledMutator::<'a, I, C, R>::new(rand);
|
let mut scheduled = DefaultScheduledMutator::<'a, I, R>::new(rand);
|
||||||
scheduled.add_mutation(mutation_bitflip);
|
scheduled.add_mutation(mutation_bitflip);
|
||||||
HavocBytesMutator {
|
HavocBytesMutator {
|
||||||
scheduled: scheduled,
|
scheduled: scheduled,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
extern crate alloc;
|
||||||
extern crate num;
|
extern crate num;
|
||||||
|
|
||||||
use num::Integer;
|
use num::Integer;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
extern crate alloc;
|
||||||
pub mod mutational;
|
pub mod mutational;
|
||||||
pub use mutational::DefaultMutationalStage;
|
pub use mutational::DefaultMutationalStage;
|
||||||
|
|
||||||
@ -5,8 +6,8 @@ use crate::corpus::Testcase;
|
|||||||
use crate::inputs::Input;
|
use crate::inputs::Input;
|
||||||
use crate::AflError;
|
use crate::AflError;
|
||||||
|
|
||||||
|
use alloc::rc::Rc;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
pub trait Stage<I>
|
pub trait Stage<I>
|
||||||
where
|
where
|
||||||
|
@ -1,26 +1,23 @@
|
|||||||
use crate::corpus::Corpus;
|
extern crate alloc;
|
||||||
use crate::corpus::TestcaseMetadata;
|
|
||||||
use crate::executors::Executor;
|
|
||||||
use crate::corpus::testcase::Testcase;
|
use crate::corpus::testcase::Testcase;
|
||||||
use crate::engines::Evaluator;
|
use crate::executors::Executor;
|
||||||
use crate::inputs::Input;
|
use crate::inputs::Input;
|
||||||
use crate::mutators::Mutator;
|
use crate::mutators::Mutator;
|
||||||
use crate::stages::Stage;
|
use crate::stages::Stage;
|
||||||
use crate::utils::{HasRand, Rand};
|
use crate::utils::{HasRand, Rand};
|
||||||
use crate::AflError;
|
use crate::AflError;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use alloc::rc::Rc;
|
||||||
use std::marker::PhantomData;
|
use core::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
// TODO create HasMutatorsVec trait
|
// TODO create HasMutatorsVec trait
|
||||||
|
|
||||||
pub trait MutationalStage<I, C, M, E>: Stage<I> + HasRand
|
pub trait MutationalStage<I, M, E>: Stage<I> + HasRand
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
M: Mutator<I, R = Self::R>,
|
M: Mutator<I, R = Self::R>,
|
||||||
C: Corpus<I>,
|
E: Executor<I>,
|
||||||
E: Executor<I, C>,
|
|
||||||
{
|
{
|
||||||
/// The mutator registered for this stage
|
/// The mutator registered for this stage
|
||||||
fn mutator(&self) -> &M;
|
fn mutator(&self) -> &M;
|
||||||
@ -37,9 +34,9 @@ where
|
|||||||
1 + self.rand_below(128) as usize
|
1 + self.rand_below(128) as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: We need a way to get testcases for splicing
|
||||||
/// Runs this (mutational) stage for the given testcase
|
/// Runs this (mutational) stage for the given testcase
|
||||||
fn perform_mutational(&mut self, corpus: &mut C, testcase: &Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
|
fn perform_mutational(&mut self, testcase: &Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
|
||||||
let testcase = corpus.next()?;
|
|
||||||
let num = self.iterations();
|
let num = self.iterations();
|
||||||
let input = testcase.borrow_mut().load_input()?.clone();
|
let input = testcase.borrow_mut().load_input()?.clone();
|
||||||
|
|
||||||
@ -47,7 +44,7 @@ where
|
|||||||
let mut input_tmp = input.clone();
|
let mut input_tmp = input.clone();
|
||||||
self.mutator_mut().mutate(&mut input_tmp, i as i32)?;
|
self.mutator_mut().mutate(&mut input_tmp, i as i32)?;
|
||||||
|
|
||||||
let interesting = self.executor().borrow_mut().evaluate_input(&corpus)?;
|
let interesting = self.executor().borrow_mut().evaluate_input(&input_tmp)?;
|
||||||
|
|
||||||
self.mutator_mut().post_exec(interesting, i as i32)?;
|
self.mutator_mut().post_exec(interesting, i as i32)?;
|
||||||
}
|
}
|
||||||
@ -56,28 +53,25 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The default mutational stage
|
/// The default mutational stage
|
||||||
pub struct DefaultMutationalStage<I, C, R, M, E>
|
pub struct DefaultMutationalStage<I, R, M, E>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I>,
|
|
||||||
R: Rand,
|
R: Rand,
|
||||||
M: Mutator<I, R = R>,
|
M: Mutator<I, R = R>,
|
||||||
E: Executor<I, C>,
|
E: Executor<I>,
|
||||||
{
|
{
|
||||||
rand: Rc<RefCell<R>>,
|
rand: Rc<RefCell<R>>,
|
||||||
executor: Rc<RefCell<E>>,
|
executor: Rc<RefCell<E>>,
|
||||||
mutator: M,
|
mutator: M,
|
||||||
_phantom_input: PhantomData<I>,
|
_phantom_input: PhantomData<I>,
|
||||||
_phantom_corpus: PhantomData<C>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, C, R, M, E> HasRand for DefaultMutationalStage<I, C, R, M, E>
|
impl<I, R, M, E> HasRand for DefaultMutationalStage<I, R, M, E>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I>,
|
|
||||||
R: Rand,
|
R: Rand,
|
||||||
M: Mutator<I, R = R>,
|
M: Mutator<I, R = R>,
|
||||||
E: Executor<I, C>,
|
E: Executor<I>,
|
||||||
{
|
{
|
||||||
type R = R;
|
type R = R;
|
||||||
|
|
||||||
@ -86,14 +80,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<I, R, M, E> MutationalStage<I, M, E> for DefaultMutationalStage<I, R, M, E>
|
||||||
impl<I, C, R, M, E> MutationalStage<I, C, M, E> for DefaultMutationalStage<I, C, R, M, E>
|
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I>,
|
|
||||||
R: Rand,
|
R: Rand,
|
||||||
M: Mutator<I, R = R>,
|
M: Mutator<I, R = R>,
|
||||||
E: Executor<I, C>,
|
E: Executor<I>,
|
||||||
{
|
{
|
||||||
/// The mutator, added to this stage
|
/// The mutator, added to this stage
|
||||||
fn mutator(&self) -> &M {
|
fn mutator(&self) -> &M {
|
||||||
@ -104,28 +96,30 @@ where
|
|||||||
fn mutator_mut(&mut self) -> &mut M {
|
fn mutator_mut(&mut self) -> &mut M {
|
||||||
&mut self.mutator
|
&mut self.mutator
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<I, C, R, M, E> Stage<I> for DefaultMutationalStage<I, C, R, M, E>
|
fn executor(&self) -> &Rc<RefCell<E>> {
|
||||||
where
|
&self.executor
|
||||||
I: Input,
|
|
||||||
C: Corpus<I>,
|
|
||||||
R: Rand,
|
|
||||||
M: Mutator<I, R = R>,
|
|
||||||
E: Executor<I, C>,
|
|
||||||
{
|
|
||||||
fn perform(&mut self, corpus: &mut C) -> Result<(), AflError> {
|
|
||||||
self.perform_mutational(corpus)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, C, R, M, E> DefaultMutationalStage<I, C, R, M, E>
|
impl<I, R, M, E> Stage<I> for DefaultMutationalStage<I, R, M, E>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
C: Corpus<I>,
|
|
||||||
M: Mutator<I, R = R>,
|
M: Mutator<I, R = R>,
|
||||||
E: Executor<I, C>,
|
E: Executor<I>,
|
||||||
|
{
|
||||||
|
fn perform(&mut self, testcase: &Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
|
||||||
|
self.perform_mutational(testcase)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, R, M, E> DefaultMutationalStage<I, R, M, E>
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
|
M: Mutator<I, R = R>,
|
||||||
|
E: Executor<I>,
|
||||||
{
|
{
|
||||||
/// Creates a new default mutational stage
|
/// Creates a new default mutational stage
|
||||||
pub fn new(rand: &Rc<RefCell<R>>, executor: &Rc<RefCell<E>>, mutator: M) -> Self {
|
pub fn new(rand: &Rc<RefCell<R>>, executor: &Rc<RefCell<E>>, mutator: M) -> Self {
|
||||||
@ -134,7 +128,6 @@ where
|
|||||||
executor: Rc::clone(executor),
|
executor: Rc::clone(executor),
|
||||||
mutator: mutator,
|
mutator: mutator,
|
||||||
_phantom_input: PhantomData,
|
_phantom_input: PhantomData,
|
||||||
_phantom_corpus: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
//! Utility functions for AFL
|
//! Utility functions for AFL
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
use alloc::rc::Rc;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use std::debug_assert;
|
use std::debug_assert;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
use xxhash_rust::xxh3::xxh3_64_with_seed;
|
use xxhash_rust::xxh3::xxh3_64_with_seed;
|
||||||
@ -160,8 +161,8 @@ mod tests {
|
|||||||
assert!(rand.between(11, 20) > 10);
|
assert!(rand.between(11, 20) > 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use alloc::rc::Rc;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use std::rc::Rc;
|
|
||||||
struct HasRandTest<R>
|
struct HasRandTest<R>
|
||||||
where
|
where
|
||||||
R: Rand,
|
R: Rand,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user