Skip to content

Commit

Permalink
Add fuzzing harness for all 3 map types (#70).
Browse files Browse the repository at this point in the history
  • Loading branch information
5225225 authored Jul 3, 2021
1 parent fb19178 commit b03adb2
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 0 deletions.
4 changes: 4 additions & 0 deletions fuzz/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

target
corpus
artifacts
38 changes: 38 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

[package]
name = "slotmap-fuzz"
version = "0.0.0"
authors = ["Automatically generated"]
publish = false
edition = "2018"

[package.metadata]
cargo-fuzz = true

[dependencies]
libfuzzer-sys = { version = "0.4.0", features = ["arbitrary-derive"] }

[dependencies.slotmap]
path = ".."

# Prevent this from interfering with workspaces
[workspace]
members = ["."]

[[bin]]
name = "hop_slot_map"
path = "fuzz_targets/hop_slot_map.rs"
test = false
doc = false

[[bin]]
name = "dense_slot_map"
path = "fuzz_targets/dense_slot_map.rs"
test = false
doc = false

[[bin]]
name = "basic_slot_map"
path = "fuzz_targets/basic_slot_map.rs"
test = false
doc = false
8 changes: 8 additions & 0 deletions fuzz/fuzz_targets/basic_slot_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![no_main]
use libfuzzer_sys::fuzz_target;

mod target;

fuzz_target!(|data: target::Target| {
fuzz_slotmap!(data, slotmap::SlotMap::<slotmap::DefaultKey, u32>);
});
8 changes: 8 additions & 0 deletions fuzz/fuzz_targets/dense_slot_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![no_main]
use libfuzzer_sys::fuzz_target;

mod target;

fuzz_target!(|data: target::Target| {
fuzz_slotmap!(data, slotmap::DenseSlotMap::<slotmap::DefaultKey, u32>);
});
8 changes: 8 additions & 0 deletions fuzz/fuzz_targets/hop_slot_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![no_main]
use libfuzzer_sys::fuzz_target;

mod target;

fuzz_target!(|data: target::Target| {
fuzz_slotmap!(data, slotmap::HopSlotMap::<slotmap::DefaultKey, u32>);
});
119 changes: 119 additions & 0 deletions fuzz/fuzz_targets/target.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
use libfuzzer_sys::arbitrary::{self, Arbitrary};

#[derive(Arbitrary, Debug)]
pub struct Target {
pub ctor: Constructor,
pub ops: Vec<Op>,
pub dtor: Destructor,
}

#[derive(Arbitrary, Debug)]
pub enum Constructor {
New,
WithCapacity(u8),
}

#[derive(Arbitrary, Debug)]
pub enum Op {
Reserve(u8),
Insert,
InsertWithKey,
Remove(usize),
Retain(Vec<bool>),
Clear,
Drain(usize),
IterMut(usize),
GetDisjointMut([usize; 4]),
}

#[derive(Arbitrary, Debug)]
pub enum Destructor {
LetDrop,
IntoIter(usize),
}

#[macro_export]
macro_rules! fuzz_slotmap {
($target:expr, $map:ty) => {
use std::convert::TryInto;
use $crate::target::{Constructor, Destructor, Op};

let mut map = match $target.ctor {
Constructor::New => <$map>::new(),
Constructor::WithCapacity(n) => <$map>::with_capacity(n as usize),
};

let mut keys = Vec::new();

for op in $target.ops {
match op {
Op::Reserve(n) => map.reserve(n as usize),
Op::Insert => keys.push(map.insert(0)),
Op::InsertWithKey => keys.push(map.insert_with_key(|_| 0)),
Op::Remove(k) => {
if let Some(k) = keys.get(k) {
map.remove(*k);
} else {
return;
}
}
Op::Retain(s) => {
let mut i = s.into_iter();
map.retain(|_k, _v| i.next().unwrap_or(false));
}
Op::Clear => map.clear(),
Op::Drain(ct) => {
let mut i = map.drain();
for _ in 0..ct {
if i.next().is_none() {
break;
}
}
}
Op::IterMut(ct) => {
let mut iter = map.iter_mut();
for _ in 0..ct {
if let Some((_k, v)) = iter.next() {
*v += 1;
} else {
break;
}
}
}
Op::GetDisjointMut(items) => {
let mut disjoint_keys = Vec::new();
for &item in &items {
if let Some(k) = keys.get(item) {
disjoint_keys.push(*k);
} else {
return;
}
}

let result: [slotmap::DefaultKey; 4] = disjoint_keys.try_into().unwrap();

if let Some(idxs) = map.get_disjoint_mut(result) {
for item in idxs {
*item += 1;
}
}
}
}
}

match $target.dtor {
Destructor::LetDrop => {
drop(map);
}
Destructor::IntoIter(ct) => {
let mut iter = map.into_iter();

for _ in 0..ct {
if iter.next().is_none() {
break;
}
}
}
}
};
}

0 comments on commit b03adb2

Please sign in to comment.