Skip to content

Commit

Permalink
Add fuzzing of TinyVec as well
Browse files Browse the repository at this point in the history
  • Loading branch information
Nemo157 committed Jan 12, 2020
1 parent 9117614 commit 16de650
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 1 deletion.
2 changes: 1 addition & 1 deletion fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2018"
publish = false

[dependencies]
tinyvec = { path = "..", features = ["nightly_slice_partition_dedup"] }
tinyvec = { path = "..", features = ["extern_crate_alloc", "nightly_slice_partition_dedup"] }
arbitrary-model-tests = { git = "https://github.com/jakubadamw/arbitrary-model-tests" }
honggfuzz = "0.5.45"
arbitrary = "0.2.0"
Expand Down
96 changes: 96 additions & 0 deletions fuzz/src/bin/tinyvec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use derive_arbitrary::Arbitrary;
use arbitrary_model_tests::arbitrary_stateful_operations;
use honggfuzz::fuzz;
use std::{fmt::Debug, iter::FromIterator, ops::{RangeBounds, Bound}};

use tinyvec::TinyVec;
use tinyvec_fuzz::ArbRange;

const CAPACITY: usize = 32;

arbitrary_stateful_operations! {
model = Vec<T>,
tested = TinyVec<[T; CAPACITY]>,

type_parameters = <
T: Default + Clone + Debug + Eq + Ord,
R: RangeBounds<usize> + Clone + Debug,
>,

methods {
equal {
fn as_mut_slice(&mut self) -> &mut [T];
fn as_slice(&self) -> &[T];
fn clear(&mut self);
fn dedup(&mut self);
fn insert(&mut self, index: usize, item: T);
fn is_empty(&self) -> bool;
fn len(&self) -> usize;
fn push(&mut self, item: T);
fn truncate(&mut self, new_len: usize);
}

equal_with(Vec::from_iter) {
fn drain(&self, range: R) -> impl Iterator<Item = T>;
fn iter(&self) -> impl Iterator<Item = &T>;
fn iter_mut(&self) -> impl Iterator<Item = &mut T>;
}
}

pre {
match self {
Self::insert { index, .. } if index > model.len() => {
// TODO: Should test that these identically panic
return;
}
Self::drain { ref range } => {
// TODO: Should test that these identically panic
let start = match range.start_bound() {
Bound::Included(&n) => n,
Bound::Excluded(&n) => n + 1,
Bound::Unbounded => 0,
};
let end = match range.end_bound() {
// If it's already usize::max, doesn't really matter about adding 1
Bound::Included(&n) => n.checked_add(1).unwrap_or(n),
Bound::Excluded(&n) => n,
Bound::Unbounded => model.len(),
};
if start > end || end > model.len() {
return;
}
}
_ => {}
}
}
}

const MAX_RING_SIZE: usize = 16_384;

fn fuzz_cycle(data: &[u8]) -> Result<(), ()> {
use arbitrary::{Arbitrary, FiniteBuffer};

let mut ring = FiniteBuffer::new(&data, MAX_RING_SIZE).map_err(|_| ())?;

let mut model = Vec::<u16>::default();
let mut tested: TinyVec<[u16; 32]> = TinyVec::new();

let mut _op_trace = String::new();
while let Ok(op) = <op::Op<u16, ArbRange<usize>> as Arbitrary>::arbitrary(&mut ring) {
#[cfg(fuzzing_debug)]
_op_trace.push_str(&format!("{}\n", op.to_string()));
op.execute_and_compare(&mut model, &mut tested);
}

Ok(())
}

fn main() -> Result<(), ()> {
better_panic::install();

loop {
fuzz!(|data: &[u8]| {
let _ = fuzz_cycle(data);
});
}
}

0 comments on commit 16de650

Please sign in to comment.