-
Notifications
You must be signed in to change notification settings - Fork 105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement persistent mode + use panic::set_hook() + many more #137
Merged
Merged
Changes from 10 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
02348dc
Implement persistent mode with new function fuzz()
PaulGrandperrin 201d80b
Use panic::set_hook() to abort process
PaulGrandperrin f420846
Implement defered forkserver mode
PaulGrandperrin b2b306a
Update RUSTFLAGS
PaulGrandperrin 68176b8
Make RUSTFLAGS extensible by user
PaulGrandperrin 0df4ca8
Add ASAN and TSAN flags for Rust
PaulGrandperrin e893d3c
Document fuzz function
PaulGrandperrin e802246
Add fuzz! macro
PaulGrandperrin c4b4a5d
travis: Add macOS
PaulGrandperrin d8c43eb
Deprecate non-persistent functions
PaulGrandperrin 3bf1c09
Update lib.rs
frewsxcv File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,3 +3,6 @@ rust: | |
- stable | ||
- beta | ||
- nightly | ||
os: | ||
- linux | ||
- osx |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,9 @@ use std::{panic, process}; | |
/// }) | ||
/// } | ||
/// ``` | ||
#[deprecated(since = "0.3.3", | ||
note="This function does not use the `persistent mode` and `defered forkserver mode` and is therefore very slow. | ||
Please use fuzz() or fuzz!() instead.")] | ||
pub fn read_stdio_bytes<F>(closure: F) | ||
where | ||
F: Fn(Vec<u8>) + panic::RefUnwindSafe, | ||
|
@@ -66,6 +69,9 @@ where | |
/// }) | ||
/// } | ||
/// ``` | ||
#[deprecated(since = "0.3.3", | ||
note="This function does not use the `persistent mode` and `defered forkserver mode` and is therefore very slow. | ||
Please use fuzz() or fuzz!() instead.")] | ||
pub fn read_stdio_string<F>(closure: F) | ||
where | ||
F: Fn(String) + panic::RefUnwindSafe, | ||
|
@@ -83,6 +89,127 @@ where | |
} | ||
} | ||
|
||
// those functions are provided by the afl-llvm-rt static library | ||
extern "C" { | ||
fn __afl_persistent_loop(counter: usize) -> isize; | ||
fn __afl_manual_init(); | ||
} | ||
|
||
/// Fuzz a closure by passing it a `&[u8]` | ||
/// | ||
/// This slice contains a "random" quantity of "random" data. | ||
/// | ||
/// ```rust,ignore | ||
/// # extern crate afl; | ||
/// # use afl::fuzz; | ||
/// # fn main() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm fine as-is, but considering users are going to need the |
||
/// fuzz(|data|{ | ||
/// if data.len() != 6 {return} | ||
/// if data[0] != b'q' {return} | ||
/// if data[1] != b'w' {return} | ||
/// if data[2] != b'e' {return} | ||
/// if data[3] != b'r' {return} | ||
/// if data[4] != b't' {return} | ||
/// if data[5] != b'y' {return} | ||
/// panic!("BOOM") | ||
/// }); | ||
/// # } | ||
/// ``` | ||
pub fn fuzz<F>(closure: F) where F: Fn(&[u8]) + std::panic::RefUnwindSafe { | ||
// this marker strings needs to be in the produced executable for | ||
// afl-fuzz to detect `persistent mode` and `defered mode` | ||
static PERSIST_MARKER: &'static str = "##SIG_AFL_PERSISTENT##\0"; | ||
static DEFERED_MARKER: &'static str = "##SIG_AFL_DEFER_FORKSRV##\0"; | ||
|
||
// we now need a fake instruction to prevent the compiler from optimizing out | ||
// those marker strings | ||
unsafe{std::ptr::read_volatile(&PERSIST_MARKER)}; // hack used in https://github.com/bluss/bencher for black_box() | ||
unsafe{std::ptr::read_volatile(&DEFERED_MARKER)}; | ||
// unsafe { asm!("" : : "r"(&PERSIST_MARKER)) }; // hack used in nightly's back_box(), requires feature asm | ||
// unsafe { asm!("" : : "r"(&DEFERED_MARKER)) }; | ||
|
||
// sets panic hook to abort | ||
std::panic::set_hook(Box::new(|_| { | ||
std::process::abort(); | ||
})); | ||
|
||
let mut input = vec![]; | ||
|
||
// initialize forkserver there | ||
unsafe{__afl_manual_init()}; | ||
|
||
while unsafe{__afl_persistent_loop(1000)} != 0 { | ||
// get buffer from AFL through stdin | ||
let result = io::stdin().read_to_end(&mut input); | ||
if result.is_err() { | ||
return; | ||
} | ||
|
||
// We still catch unwinding panics just in case the fuzzed code modifies | ||
// the panic hook. | ||
// If so, the fuzzer will be unable to tell different bugs appart and you will | ||
// only be able to find one bug at a time before fixing it to then find a new one. | ||
let did_panic = std::panic::catch_unwind(|| { | ||
closure(&input); | ||
}).is_err(); | ||
|
||
if did_panic { | ||
// hopefully the custom panic hook will be called before and abort the | ||
// process before the stack frames are unwinded. | ||
std::process::abort(); | ||
} | ||
input.clear(); | ||
} | ||
} | ||
|
||
/// Fuzz a closure-like block of code by passing it an object of arbitrary type. | ||
/// | ||
/// You can choose the type of the argument using the syntax as in the example below. | ||
/// Please check out the `arbitrary` crate to see which types are available. | ||
/// | ||
/// For performance reasons, it is recommended that you use the native type `&[u8]` when possible. | ||
/// | ||
/// ```rust,ignore | ||
/// # #[macro_use] extern crate afl; | ||
/// # fn main() { | ||
/// fuzz!(|data: &[u8]| { | ||
/// if data.len() != 6 {return} | ||
/// if data[0] != b'q' {return} | ||
/// if data[1] != b'w' {return} | ||
/// if data[2] != b'e' {return} | ||
/// if data[3] != b'r' {return} | ||
/// if data[4] != b't' {return} | ||
/// if data[5] != b'y' {return} | ||
/// panic!("BOOM") | ||
/// }); | ||
/// # } | ||
/// ``` | ||
#[macro_export] | ||
macro_rules! fuzz { | ||
(|$buf:ident| $body:block) => { | ||
afl::fuzz(|$buf| $body); | ||
}; | ||
(|$buf:ident: &[u8]| $body:block) => { | ||
afl::fuzz(|$buf| $body); | ||
}; | ||
(|$buf:ident: $dty: ty| $body:block) => { | ||
afl::fuzz(|$buf| { | ||
let $buf: $dty = { | ||
use arbitrary::{Arbitrary, RingBuffer}; | ||
if let Ok(d) = RingBuffer::new($buf, $buf.len()).and_then(|mut b|{ | ||
Arbitrary::arbitrary(&mut b).map_err(|_| "") | ||
}) { | ||
d | ||
} else { | ||
return | ||
} | ||
}; | ||
|
||
$body | ||
}); | ||
}; | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
/* | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of
rust,ignore
, this can berust,no_run
to ensure it compiles, but won't attempt to run which is what we wanthttps://doc.rust-lang.org/book/first-edition/documentation.html#running-documentation-tests