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 max: Option<usize>,
pub mutations: Vec<Mutation>,
}
impl Stage {
pub fn new(count: usize, mutations: Vec<Mutation>, max: Option<usize>) -> Self {
Self {
count,
mutations,
max,
}
}
pub fn is_done(&self) -> bool {
match self.max {
None => false,
Some(n) => self.count >= n,
}
}
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![], None)
}
}
#[derive(Debug, Clone)]
pub struct ByteMutator {
stages: Vec<Stage>,
cur_stage: usize,
}
impl ByteMutator {
pub fn new() -> Self {
Self {
stages: vec![],
cur_stage: 0,
}
}
pub fn with_stages(mut self, stages: Vec<Stage>) -> Self {
self.stages = stages;
self
}
pub fn new_from_config(config: FuzzConfig) -> Self {
Self {
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,
};
stage.next();
if stage.is_done() {
self.stages.drain(..1);
}
}
pub fn mutate(&self, bytes: &mut [u8]) {
let stage = match self.stages.get(0) {
None => return, Some(s) => s,
};
for mutation in &stage.mutations {
match mutation.range {
Some((start, end)) => mutation.mutate(&mut bytes[start..end], stage.count),
None => mutation.mutate(bytes, stage.count),
};
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::mutators::MutationType;
#[test]
fn mutator_stage() {
let mut byte_mutator = ByteMutator::new();
byte_mutator.add_stage(Stage::new(
0,
vec![Mutation {
range: None,
mutation: MutationType::BitFlipper { width: 1 },
}],
Some(10),
));
assert_eq!(byte_mutator.remaining_stages(), 1);
for _ in 0..10 {
byte_mutator.next();
}
assert_eq!(byte_mutator.remaining_stages(), 0);
}
}