Skip to content

Commit

Permalink
random action fuzzer
Browse files Browse the repository at this point in the history
  • Loading branch information
evanrichter committed Sep 11, 2022
1 parent 9e5878a commit 0c116a4
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 2 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
coverage
28 changes: 28 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "linked_list_allocator-fuzz"
version = "0.0.0"
publish = false
edition = "2021"

[package.metadata]
cargo-fuzz = true

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

[dependencies.linked_list_allocator]
path = ".."

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

[profile.release]
debug = 1

[[bin]]
name = "chaos"
path = "fuzz_targets/chaos.rs"
test = false
doc = false
120 changes: 120 additions & 0 deletions fuzz/fuzz_targets/chaos.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#![no_main]
use arbitrary::Arbitrary;
use libfuzzer_sys::fuzz_target;
use linked_list_allocator::Heap;
use std::alloc::Layout;
use std::ptr::NonNull;

#[derive(Debug, Arbitrary)]
enum Action {
// allocate a chunk with the size specified
Alloc { size: u16, align_bit: u8 },
// free the pointer at the index specified
Free { index: u8 },
// extend the heap by amount specified
Extend { additional: u16 },
}
use Action::*;

const MAX_HEAP_SIZE: usize = 5000;
static mut HEAP_MEM: [u8; MAX_HEAP_SIZE] = [0; MAX_HEAP_SIZE];
const DEBUG: bool = false;

fuzz_target!(|data: (u16, Vec<Action>)| {
let (size, actions) = data;
let _ = fuzz(size, actions);
});

fn fuzz(size: u16, actions: Vec<Action>) {
// init heap
let mut heap = unsafe {
let size = size as usize;
if size > MAX_HEAP_SIZE || size < 3 * core::mem::size_of::<usize>() {
return;
}

Heap::new(HEAP_MEM.as_mut_ptr(), size)
};
let mut ptrs: Vec<(NonNull<u8>, Layout)> = Vec::new();

if DEBUG {
heap.debug();
}

// process operations
for action in actions {
if DEBUG {
println!("-----\nnext action: {:?}", action);
}
match action {
Alloc { size, align_bit } => {
let layout = {
let align = 1_usize.rotate_left(align_bit as u32);
if align == 1 << 63 {
return;
}
Layout::from_size_align(size as usize, align).unwrap()
};

if let Ok(ptr) = heap.allocate_first_fit(layout) {
if DEBUG {
println!("alloc'd {:?}", ptr);
}
ptrs.push((ptr, layout));
} else {
return;
}
}
Free { index } => {
if index as usize >= ptrs.len() {
return;
}

let (ptr, layout) = ptrs.swap_remove(index as usize);
if DEBUG {
println!("removing {:?}, size: {}", ptr, layout.size());
}
unsafe {
heap.deallocate(ptr, layout);
}
}
Extend { additional } =>
// safety: new heap size never exceeds MAX_HEAP_SIZE
unsafe {
let remaining_space = HEAP_MEM
.as_mut_ptr()
.add(MAX_HEAP_SIZE)
.offset_from(heap.top());
assert!(remaining_space >= 0);

if additional as isize > remaining_space {
return;
}

heap.extend(additional as usize);
if DEBUG {
println!("new heap size: {}, top: {:?}", heap.size(), heap.top());
}
},
}
if DEBUG {
println!("after action:");
print!("live allocs: ");
for ptr in &ptrs {
print!("({:?}, {},{}), ", ptr.0, ptr.1.size(), ptr.1.align());
}
println!();
heap.debug();
}
}

// free the remaining allocations
for (ptr, layout) in ptrs {
if DEBUG {
println!("removing {:?}, size: {}", ptr, layout.size());
}
unsafe {
heap.deallocate(ptr, layout);
}
}
}
2 changes: 1 addition & 1 deletion src/hole.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ impl HoleList {
}
}

#[cfg(test)]
#[cfg(any(test, fuzzing))]
#[allow(dead_code)]
pub(crate) fn debug(&mut self) {
if let Some(cursor) = self.cursor() {
Expand Down
16 changes: 15 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
)]
#![no_std]

#[cfg(test)]
#[cfg(any(test, fuzzing))]
#[macro_use]
extern crate std;

Expand Down Expand Up @@ -37,6 +37,20 @@ pub struct Heap {
holes: HoleList,
}

#[cfg(fuzzing)]
impl Heap {
pub fn debug(&mut self) {
println!(
"bottom: {:?}, top: {:?}, size: {}, pending: {}",
self.bottom(),
self.top(),
self.size(),
self.holes.first.size,
);
self.holes.debug();
}
}

unsafe impl Send for Heap {}

impl Heap {
Expand Down

0 comments on commit 0c116a4

Please sign in to comment.