use serde_derive::Deserialize;
pub use crate::fuzz_config::FuzzConfig;
pub use crate::mutators::{Mutation, MutationType};
pub use crate::undo_buffer::UndoBuffer;
pub mod fuzz_config;
pub mod mutators;
pub mod undo_buffer;
#[derive(Clone, Debug, Deserialize)]
pub enum Iterations {
Bits,
Bytes,
Unlimited,
Limited(usize),
}
#[derive(Clone, Debug, Deserialize)]
pub struct Stage {
pub count: usize,
pub iterations: Iterations,
pub mutations: Vec<Mutation>,
}
impl Stage {
pub fn new(count: usize, mutations: Vec<Mutation>, iterations: Iterations) -> Self {
Self {
count,
mutations,
iterations,
}
}
pub fn is_done(&self, num_bytes: usize) -> bool {
match self.iterations {
Iterations::Bits => self.count >= num_bytes * 8,
Iterations::Bytes => self.count >= num_bytes,
Iterations::Limited(n) => self.count >= n,
Iterations::Unlimited => false,
}
}
pub fn next(&mut self) {
self.count += 1;
}
pub fn add_mutation(&mut self, mutation: Mutation) {
self.mutations.push(mutation);
}
}
impl Default for Stage {
fn default() -> Self {
Stage::new(0, vec![], Iterations::Unlimited)
}
}
#[derive(Debug, Clone)]
pub struct ByteMutator {
bytes: UndoBuffer,
stages: Vec<Stage>,
cur_stage: usize,
}
impl ByteMutator {
pub fn new(bytes: &[u8]) -> Self {
Self {
bytes: UndoBuffer::new(bytes),
stages: vec![],
cur_stage: 0,
}
}
pub fn with_stages(mut self, stages: Vec<Stage>) -> Self {
self.stages = stages;
self
}
pub fn new_from_config(bytes: &[u8], config: FuzzConfig) -> Self {
Self {
bytes: UndoBuffer::new(bytes),
stages: config.stages,
cur_stage: 0,
}
}
pub fn remaining_stages(&self) -> usize {
self.stages.len()
}
pub fn add_stage(&mut self, stage: Stage) {
self.stages.push(stage);
}
pub fn next(&mut self) {
let stage = match self.stages.get_mut(0) {
None => return, Some(s) => s,
};
self.bytes.undo();
for mutation in &mut stage.mutations {
match mutation.range {
Some((start, end)) => {
mutation.mutate(self.bytes.get_mut_range(start, end), stage.count)
}
None => mutation.mutate(self.bytes.get_mut(), stage.count),
};
}
stage.next();
if stage.is_done(self.bytes.len()) {
self.stages.drain(..1);
self.bytes.undo();
}
}
pub fn read(&self) -> &[u8] {
self.bytes.read()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::mutators::MutationType;
#[test]
fn mutator_stage() {
let mut byte_mutator = ByteMutator::new(b"foo");
byte_mutator.add_stage(Stage::new(
0,
vec![Mutation {
range: None,
mutation: MutationType::BitFlipper { width: 1 },
}],
Iterations::Limited(10),
));
assert_eq!(byte_mutator.remaining_stages(), 1);
for _ in 0..10 {
byte_mutator.next();
}
assert_eq!(byte_mutator.remaining_stages(), 0);
}
}