mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-12 10:08:07 +00:00
Updated rust custom mutator bindgen, fixed clippy lints
This commit is contained in:
@ -1,12 +1,12 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "custom_mutator-sys"
|
name = "custom_mutator-sys"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
authors = ["Julius Hohnerlein <julihoh@users.noreply.github.com>"]
|
authors = ["Julius Hohnerlein <julihoh@users.noreply.github.com>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
bindgen = "0.56"
|
bindgen = "0.63"
|
||||||
|
@ -15,8 +15,8 @@ fn main() {
|
|||||||
// The input header we would like to generate
|
// The input header we would like to generate
|
||||||
// bindings for.
|
// bindings for.
|
||||||
.header("wrapper.h")
|
.header("wrapper.h")
|
||||||
.whitelist_type("afl_state_t")
|
.allowlist_type("afl_state_t")
|
||||||
.blacklist_type(r"u\d+")
|
.blocklist_type(r"u\d+")
|
||||||
.opaque_type(r"_.*")
|
.opaque_type(r"_.*")
|
||||||
.opaque_type("FILE")
|
.opaque_type("FILE")
|
||||||
.opaque_type("in_addr(_t)?")
|
.opaque_type("in_addr(_t)?")
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(clippy::too_many_lines)]
|
||||||
|
#![allow(clippy::used_underscore_binding)]
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
name = "custom_mutator"
|
name = "custom_mutator"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Julius Hohnerlein <julihoh@users.noreply.github.com>"]
|
authors = ["Julius Hohnerlein <julihoh@users.noreply.github.com>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
//! This binding is panic-safe in that it will prevent panics from unwinding into AFL++. Any panic will `abort` at the boundary between the custom mutator and AFL++.
|
//! This binding is panic-safe in that it will prevent panics from unwinding into AFL++. Any panic will `abort` at the boundary between the custom mutator and AFL++.
|
||||||
//!
|
//!
|
||||||
//! # Access to AFL++ internals
|
//! # Access to AFL++ internals
|
||||||
//! This crate has an optional feature "afl_internals", which gives access to AFL++'s internal state.
|
//! This crate has an optional feature "`afl_internals`", which gives access to AFL++'s internal state.
|
||||||
//! The state is passed to [`CustomMutator::init`], when the feature is activated.
|
//! The state is passed to [`CustomMutator::init`], when the feature is activated.
|
||||||
//!
|
//!
|
||||||
//! _This is completely unsafe and uses automatically generated types extracted from the AFL++ source._
|
//! _This is completely unsafe and uses automatically generated types extracted from the AFL++ source._
|
||||||
@ -115,7 +115,7 @@ pub mod wrappers {
|
|||||||
impl<M: RawCustomMutator> FFIContext<M> {
|
impl<M: RawCustomMutator> FFIContext<M> {
|
||||||
fn from(ptr: *mut c_void) -> ManuallyDrop<Box<Self>> {
|
fn from(ptr: *mut c_void) -> ManuallyDrop<Box<Self>> {
|
||||||
assert!(!ptr.is_null());
|
assert!(!ptr.is_null());
|
||||||
ManuallyDrop::new(unsafe { Box::from_raw(ptr as *mut Self) })
|
ManuallyDrop::new(unsafe { Box::from_raw(ptr.cast::<Self>()) })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_ptr(self: Box<Self>) -> *const c_void {
|
fn into_ptr(self: Box<Self>) -> *const c_void {
|
||||||
@ -141,27 +141,28 @@ pub mod wrappers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// panic handler called for every panic
|
/// panic handler called for every panic
|
||||||
fn panic_handler(method: &str, panic_info: Box<dyn Any + Send + 'static>) -> ! {
|
fn panic_handler(method: &str, panic_info: &Box<dyn Any + Send + 'static>) -> ! {
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
let cause = panic_info
|
let cause = panic_info.downcast_ref::<String>().map_or_else(
|
||||||
.downcast_ref::<String>()
|
|| {
|
||||||
.map(String::deref)
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
panic_info
|
panic_info
|
||||||
.downcast_ref::<&str>()
|
.downcast_ref::<&str>()
|
||||||
.copied()
|
.copied()
|
||||||
.unwrap_or("<cause unknown>")
|
.unwrap_or("<cause unknown>")
|
||||||
});
|
},
|
||||||
eprintln!("A panic occurred at {}: {}", method, cause);
|
String::deref,
|
||||||
|
);
|
||||||
|
eprintln!("A panic occurred at {method}: {cause}");
|
||||||
abort()
|
abort()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal function used in the macro
|
/// Internal function used in the macro
|
||||||
#[cfg(not(feature = "afl_internals"))]
|
#[cfg(not(feature = "afl_internals"))]
|
||||||
|
#[must_use]
|
||||||
pub fn afl_custom_init_<M: RawCustomMutator>(seed: u32) -> *const c_void {
|
pub fn afl_custom_init_<M: RawCustomMutator>(seed: u32) -> *const c_void {
|
||||||
match catch_unwind(|| FFIContext::<M>::new(seed).into_ptr()) {
|
match catch_unwind(|| FFIContext::<M>::new(seed).into_ptr()) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(err) => panic_handler("afl_custom_init", err),
|
Err(err) => panic_handler("afl_custom_init", &err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +177,7 @@ pub mod wrappers {
|
|||||||
FFIContext::<M>::new(afl, seed).into_ptr()
|
FFIContext::<M>::new(afl, seed).into_ptr()
|
||||||
}) {
|
}) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(err) => panic_handler("afl_custom_init", err),
|
Err(err) => panic_handler("afl_custom_init", &err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,32 +197,27 @@ pub mod wrappers {
|
|||||||
) -> usize {
|
) -> usize {
|
||||||
match catch_unwind(|| {
|
match catch_unwind(|| {
|
||||||
let mut context = FFIContext::<M>::from(data);
|
let mut context = FFIContext::<M>::from(data);
|
||||||
if buf.is_null() {
|
|
||||||
panic!("null buf passed to afl_custom_fuzz")
|
assert!(!buf.is_null(), "null buf passed to afl_custom_fuzz");
|
||||||
}
|
assert!(!out_buf.is_null(), "null out_buf passed to afl_custom_fuzz");
|
||||||
if out_buf.is_null() {
|
|
||||||
panic!("null out_buf passed to afl_custom_fuzz")
|
|
||||||
}
|
|
||||||
let buff_slice = slice::from_raw_parts_mut(buf, buf_size);
|
let buff_slice = slice::from_raw_parts_mut(buf, buf_size);
|
||||||
let add_buff_slice = if add_buf.is_null() {
|
let add_buff_slice = if add_buf.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(slice::from_raw_parts(add_buf, add_buf_size))
|
Some(slice::from_raw_parts(add_buf, add_buf_size))
|
||||||
};
|
};
|
||||||
match context.mutator.fuzz(buff_slice, add_buff_slice, max_size) {
|
if let Some(buffer) = context.mutator.fuzz(buff_slice, add_buff_slice, max_size) {
|
||||||
Some(buffer) => {
|
*out_buf = buffer.as_ptr();
|
||||||
*out_buf = buffer.as_ptr();
|
buffer.len()
|
||||||
buffer.len()
|
} else {
|
||||||
}
|
// return the input buffer with 0-length to let AFL skip this mutation attempt
|
||||||
None => {
|
*out_buf = buf;
|
||||||
// return the input buffer with 0-length to let AFL skip this mutation attempt
|
0
|
||||||
*out_buf = buf;
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(err) => panic_handler("afl_custom_fuzz", err),
|
Err(err) => panic_handler("afl_custom_fuzz", &err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,9 +233,8 @@ pub mod wrappers {
|
|||||||
) -> u32 {
|
) -> u32 {
|
||||||
match catch_unwind(|| {
|
match catch_unwind(|| {
|
||||||
let mut context = FFIContext::<M>::from(data);
|
let mut context = FFIContext::<M>::from(data);
|
||||||
if buf.is_null() {
|
assert!(!buf.is_null(), "null buf passed to afl_custom_fuzz");
|
||||||
panic!("null buf passed to afl_custom_fuzz")
|
|
||||||
}
|
|
||||||
let buf_slice = slice::from_raw_parts(buf, buf_size);
|
let buf_slice = slice::from_raw_parts(buf, buf_size);
|
||||||
// see https://doc.rust-lang.org/nomicon/borrow-splitting.html
|
// see https://doc.rust-lang.org/nomicon/borrow-splitting.html
|
||||||
let ctx = &mut **context;
|
let ctx = &mut **context;
|
||||||
@ -247,7 +242,7 @@ pub mod wrappers {
|
|||||||
mutator.fuzz_count(buf_slice)
|
mutator.fuzz_count(buf_slice)
|
||||||
}) {
|
}) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(err) => panic_handler("afl_custom_fuzz_count", err),
|
Err(err) => panic_handler("afl_custom_fuzz_count", &err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,25 +254,27 @@ pub mod wrappers {
|
|||||||
) -> bool {
|
) -> bool {
|
||||||
match catch_unwind(|| {
|
match catch_unwind(|| {
|
||||||
let mut context = FFIContext::<M>::from(data);
|
let mut context = FFIContext::<M>::from(data);
|
||||||
if filename_new_queue.is_null() {
|
assert!(
|
||||||
panic!("received null filename_new_queue in afl_custom_queue_new_entry");
|
!filename_new_queue.is_null(),
|
||||||
}
|
"received null filename_new_queue in afl_custom_queue_new_entry"
|
||||||
|
);
|
||||||
|
|
||||||
let filename_new_queue = Path::new(OsStr::from_bytes(
|
let filename_new_queue = Path::new(OsStr::from_bytes(
|
||||||
unsafe { CStr::from_ptr(filename_new_queue) }.to_bytes(),
|
unsafe { CStr::from_ptr(filename_new_queue) }.to_bytes(),
|
||||||
));
|
));
|
||||||
let filename_orig_queue = if !filename_orig_queue.is_null() {
|
let filename_orig_queue = if filename_orig_queue.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
Some(Path::new(OsStr::from_bytes(
|
Some(Path::new(OsStr::from_bytes(
|
||||||
unsafe { CStr::from_ptr(filename_orig_queue) }.to_bytes(),
|
unsafe { CStr::from_ptr(filename_orig_queue) }.to_bytes(),
|
||||||
)))
|
)))
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
};
|
||||||
context
|
context
|
||||||
.mutator
|
.mutator
|
||||||
.queue_new_entry(filename_new_queue, filename_orig_queue)
|
.queue_new_entry(filename_new_queue, filename_orig_queue)
|
||||||
}) {
|
}) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(err) => panic_handler("afl_custom_queue_new_entry", err),
|
Err(err) => panic_handler("afl_custom_queue_new_entry", &err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,7 +289,7 @@ pub mod wrappers {
|
|||||||
ManuallyDrop::into_inner(FFIContext::<M>::from(data));
|
ManuallyDrop::into_inner(FFIContext::<M>::from(data));
|
||||||
}) {
|
}) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(err) => panic_handler("afl_custom_deinit", err),
|
Err(err) => panic_handler("afl_custom_deinit", &err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,13 +303,13 @@ pub mod wrappers {
|
|||||||
buf.extend_from_slice(res.as_bytes());
|
buf.extend_from_slice(res.as_bytes());
|
||||||
buf.push(0);
|
buf.push(0);
|
||||||
// unwrapping here, as the error case should be extremely rare
|
// unwrapping here, as the error case should be extremely rare
|
||||||
CStr::from_bytes_with_nul(&buf).unwrap().as_ptr()
|
CStr::from_bytes_with_nul(buf).unwrap().as_ptr()
|
||||||
} else {
|
} else {
|
||||||
null()
|
null()
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(err) => panic_handler("afl_custom_introspection", err),
|
Err(err) => panic_handler("afl_custom_introspection", &err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,13 +326,13 @@ pub mod wrappers {
|
|||||||
buf.extend_from_slice(res.as_bytes());
|
buf.extend_from_slice(res.as_bytes());
|
||||||
buf.push(0);
|
buf.push(0);
|
||||||
// unwrapping here, as the error case should be extremely rare
|
// unwrapping here, as the error case should be extremely rare
|
||||||
CStr::from_bytes_with_nul(&buf).unwrap().as_ptr()
|
CStr::from_bytes_with_nul(buf).unwrap().as_ptr()
|
||||||
} else {
|
} else {
|
||||||
null()
|
null()
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(err) => panic_handler("afl_custom_describe", err),
|
Err(err) => panic_handler("afl_custom_describe", &err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,12 +345,12 @@ pub mod wrappers {
|
|||||||
let mut context = FFIContext::<M>::from(data);
|
let mut context = FFIContext::<M>::from(data);
|
||||||
assert!(!filename.is_null());
|
assert!(!filename.is_null());
|
||||||
|
|
||||||
context.mutator.queue_get(Path::new(OsStr::from_bytes(
|
u8::from(context.mutator.queue_get(Path::new(OsStr::from_bytes(
|
||||||
unsafe { CStr::from_ptr(filename) }.to_bytes(),
|
unsafe { CStr::from_ptr(filename) }.to_bytes(),
|
||||||
))) as u8
|
))))
|
||||||
}) {
|
}) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(err) => panic_handler("afl_custom_queue_get", err),
|
Err(err) => panic_handler("afl_custom_queue_get", &err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -373,7 +370,7 @@ macro_rules! _define_afl_custom_init {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An exported macro to defined afl_custom_init meant for insternal usage
|
/// An exported macro to defined `afl_custom_init` meant for internal usage
|
||||||
#[cfg(not(feature = "afl_internals"))]
|
#[cfg(not(feature = "afl_internals"))]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! _define_afl_custom_init {
|
macro_rules! _define_afl_custom_init {
|
||||||
@ -520,9 +517,10 @@ mod sanity_test {
|
|||||||
export_mutator!(ExampleMutator);
|
export_mutator!(ExampleMutator);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
/// A custom mutator.
|
/// A custom mutator.
|
||||||
/// [`CustomMutator::handle_error`] will be called in case any method returns an [`Result::Err`].
|
/// [`CustomMutator::handle_error`] will be called in case any method returns an [`Result::Err`].
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
#[allow(clippy::missing_errors_doc)]
|
||||||
pub trait CustomMutator {
|
pub trait CustomMutator {
|
||||||
/// The error type. All methods must return the same error type.
|
/// The error type. All methods must return the same error type.
|
||||||
type Error: Debug;
|
type Error: Debug;
|
||||||
@ -537,7 +535,7 @@ pub trait CustomMutator {
|
|||||||
.map(|v| !v.is_empty())
|
.map(|v| !v.is_empty())
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
eprintln!("Error in custom mutator: {:?}", err)
|
eprintln!("Error in custom mutator: {err:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
name = "example_mutator"
|
name = "example_mutator"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Julius Hohnerlein <julihoh@users.noreply.github.com>"]
|
authors = ["Julius Hohnerlein <julihoh@users.noreply.github.com>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user