Mark unsafe functions unsafe, as Ferris intended (#2559)
* Mark unsafe functions unsafe, as Ferris inteded * More * more safety? * more fix * actually safe * More cleanup * More fix * more unsafe * fix imports * more unsafe * fixes * bring back the memories
This commit is contained in:
parent
afb682bff2
commit
82110472d6
@ -9,7 +9,7 @@ They are sorted by focus:
|
||||
- [`binary_only`](./binary_only/): Fuzzers for binary-only targets.
|
||||
- [`forkserver`](./forkserver/): Fuzzers that use a forkserver-style executor.
|
||||
- [`full_system`](./full_system/): Fuzzers for full-system targets (kernels, firmwares, etc...).
|
||||
- [`fuzz-anything`](./fuzz_anything/): Fuzzers for advanced targets like WASM or python, and other fuzzers that can be used for anything.
|
||||
- [`fuzz_anything`](./fuzz_anything/): Fuzzers for advanced targets like WASM or python, and other fuzzers that can be used for anything.
|
||||
- [`inprocess`](./inprocess/): Common In-process fuzzers. Most of the time, this is what you want.
|
||||
- [`structure_aware`](./structure_aware/): Grammar fuzzers, fuzzers for certain languages, fuzzers with custom inputs, and more.
|
||||
|
||||
|
@ -59,7 +59,11 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
let mut harness = |input: &PacketData| {
|
||||
let target = input.target_bytes();
|
||||
let buf = target.as_slice();
|
||||
// # Safety
|
||||
// We're looking for crashes in there!
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
@ -155,7 +159,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
|
14
fuzzers/fuzz_anything/baby_fuzzer_wasm/pkg/index.html
Normal file
14
fuzzers/fuzz_anything/baby_fuzzer_wasm/pkg/index.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>libafl_wasm test</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="module">
|
||||
import libafl_wasm from './libafl_wasm.js'
|
||||
|
||||
libafl_wasm().then(wasm => wasm.fuzz())
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
17
fuzzers/fuzz_anything/baby_fuzzer_wasm/pkg/package.json
Normal file
17
fuzzers/fuzz_anything/baby_fuzzer_wasm/pkg/package.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "baby_fuzzer_wasm",
|
||||
"collaborators": [
|
||||
"Addison Crump <research@addisoncrump.info>"
|
||||
],
|
||||
"version": "0.1.0",
|
||||
"files": [
|
||||
"baby_fuzzer_wasm_bg.wasm",
|
||||
"baby_fuzzer_wasm.js",
|
||||
"baby_fuzzer_wasm.d.ts"
|
||||
],
|
||||
"module": "baby_fuzzer_wasm.js",
|
||||
"types": "baby_fuzzer_wasm.d.ts",
|
||||
"sideEffects": [
|
||||
"./snippets/*"
|
||||
]
|
||||
}
|
@ -176,7 +176,7 @@ fn run_testcases(filenames: &[&str]) {
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
@ -191,8 +191,10 @@ fn run_testcases(filenames: &[&str]) {
|
||||
let mut buffer = vec![];
|
||||
file.read_to_end(&mut buffer).expect("Buffer overflow");
|
||||
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(&buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The actual fuzzer
|
||||
@ -296,7 +298,7 @@ fn fuzz(
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
@ -331,7 +333,9 @@ fn fuzz(
|
||||
let mut harness = |input: &BytesInput| {
|
||||
let target = input.target_bytes();
|
||||
let buf = target.as_slice();
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
|
@ -174,7 +174,7 @@ fn run_testcases(filenames: &[&str]) {
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
@ -189,8 +189,10 @@ fn run_testcases(filenames: &[&str]) {
|
||||
let mut buffer = vec![];
|
||||
file.read_to_end(&mut buffer).expect("Buffer overflow");
|
||||
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(&buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The actual fuzzer
|
||||
@ -290,7 +292,7 @@ fn fuzz(
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
@ -325,7 +327,9 @@ fn fuzz(
|
||||
let mut harness = |input: &BytesInput| {
|
||||
let target = input.target_bytes();
|
||||
let buf = target.as_slice();
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
|
@ -179,7 +179,7 @@ fn run_testcases(filenames: &[&str]) {
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
@ -194,8 +194,10 @@ fn run_testcases(filenames: &[&str]) {
|
||||
let mut buffer = vec![];
|
||||
file.read_to_end(&mut buffer).expect("Buffer overflow");
|
||||
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(&buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The actual fuzzer
|
||||
@ -300,7 +302,7 @@ fn fuzz(
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
@ -335,7 +337,9 @@ fn fuzz(
|
||||
let mut harness = |input: &BytesInput| {
|
||||
let target = input.target_bytes();
|
||||
let buf = target.as_slice();
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
|
@ -236,7 +236,7 @@ fn run_testcases(filenames: &[&str]) {
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
@ -251,8 +251,10 @@ fn run_testcases(filenames: &[&str]) {
|
||||
let mut buffer = vec![];
|
||||
file.read_to_end(&mut buffer).expect("Buffer overflow");
|
||||
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(&buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The actual fuzzer
|
||||
@ -357,7 +359,7 @@ fn fuzz_binary(
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
@ -392,7 +394,9 @@ fn fuzz_binary(
|
||||
let mut harness = |input: &BytesInput| {
|
||||
let target = input.target_bytes();
|
||||
let buf = target.as_slice();
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
@ -570,7 +574,7 @@ fn fuzz_text(
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
@ -618,7 +622,9 @@ fn fuzz_text(
|
||||
let mut harness = |input: &BytesInput| {
|
||||
let target = input.target_bytes();
|
||||
let buf = target.as_slice();
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
|
@ -143,7 +143,9 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
let mut harness = |input: &BytesInput| {
|
||||
let target = input.target_bytes();
|
||||
let buf = target.as_slice();
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
@ -159,7 +161,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,9 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
*addr = 1;
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
@ -191,7 +193,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
|
@ -210,7 +210,9 @@ pub extern "C" fn libafl_main() {
|
||||
let mut harness = |input: &BytesInput| {
|
||||
let target = input.target_bytes();
|
||||
let buf = target.as_slice();
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
@ -227,7 +229,7 @@ pub extern "C" fn libafl_main() {
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
|
@ -205,7 +205,9 @@ pub extern "C" fn libafl_main() {
|
||||
let mut harness = |input: &BytesInput| {
|
||||
let target = input.target_bytes();
|
||||
let buf = target.as_slice();
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
@ -233,7 +235,7 @@ pub extern "C" fn libafl_main() {
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,9 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
*addr = 1;
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
@ -187,7 +189,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
|
@ -204,7 +204,9 @@ pub extern "C" fn libafl_main() {
|
||||
let mut harness = |input: &BytesInput| {
|
||||
let target = input.target_bytes();
|
||||
let buf = target.as_slice();
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
@ -232,7 +234,7 @@ pub extern "C" fn libafl_main() {
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
|
@ -229,7 +229,9 @@ pub extern "C" fn libafl_main() {
|
||||
let mut harness = |input: &BytesInput| {
|
||||
let target = input.target_bytes();
|
||||
let buf = target.as_slice();
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
@ -245,7 +247,7 @@ pub extern "C" fn libafl_main() {
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,9 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
*addr = 1;
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
@ -188,7 +190,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,9 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
let mut harness = |input: &BytesInput| {
|
||||
let target = input.target_bytes();
|
||||
let buf = target.as_slice();
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
@ -137,7 +139,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ pub fn main() {
|
||||
fn fuzz(input_dirs: &[PathBuf], output_dir: PathBuf, cores: &Cores, broker_port: u16) {
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ fn fuzz(input_dirs: &[PathBuf], output_dir: PathBuf, cores: &Cores, broker_port:
|
||||
.output_dir(output_dir)
|
||||
.cores(cores)
|
||||
.broker_port(broker_port)
|
||||
.harness(|buf| {
|
||||
.harness(|buf| unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
})
|
||||
.build()
|
||||
|
@ -132,7 +132,9 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
let mut harness = |input: &BytesInput| {
|
||||
let target = input.target_bytes();
|
||||
let buf = target.as_slice();
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
@ -155,7 +157,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,9 @@ pub extern "C" fn libafl_main() {
|
||||
let mut harness = |input: &BytesInput| {
|
||||
let target = input.target_bytes();
|
||||
let buf = target.as_slice();
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
@ -252,7 +254,7 @@ pub extern "C" fn libafl_main() {
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,9 @@ fn fuzz(
|
||||
let mut harness = |input: &BytesInput| {
|
||||
let target = input.target_bytes();
|
||||
let buf = target.as_slice();
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(buf);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
@ -175,7 +177,7 @@ fn fuzz(
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ script_runner = "@shell"
|
||||
script = '''
|
||||
cd libpng-1.6.37 && ./configure --enable-shared=no --with-pic=yes --enable-hardware-optimizations=yes
|
||||
cd "${PROJECT_DIR}"
|
||||
cp ../../structure-aware/baby_fuzzer_nautilus/grammar.json .
|
||||
cp ../../structure_aware/baby_fuzzer_nautilus/grammar.json .
|
||||
make -C libpng-1.6.37 CC="${CARGO_TARGET_DIR}/${PROFILE_DIR}/libafl_cc" CXX="${CARGO_TARGET_DIR}/${PROFILE_DIR}/libafl_cxx"
|
||||
'''
|
||||
dependencies = ["libpng", "cxx", "cc"]
|
||||
|
@ -140,7 +140,9 @@ pub extern "C" fn libafl_main() {
|
||||
// The closure that we want to fuzz
|
||||
let mut harness = |input: &NautilusInput| {
|
||||
input.unparse(&context, &mut bytes);
|
||||
unsafe {
|
||||
libfuzzer_test_one_input(&bytes);
|
||||
}
|
||||
ExitKind::Ok
|
||||
};
|
||||
|
||||
@ -202,7 +204,7 @@ pub extern "C" fn libafl_main() {
|
||||
// The actual target run starts here.
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if libfuzzer_initialize(&args) == -1 {
|
||||
if unsafe { libfuzzer_initialize(&args) } == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1");
|
||||
}
|
||||
|
||||
|
@ -218,6 +218,8 @@ where
|
||||
#[allow(clippy::unused_self)]
|
||||
fn post_exec(&mut self, _state: &mut S, _input: &S::Input) {
|
||||
// timeout stuff
|
||||
// # Safety
|
||||
// We're calling this only once per execution, in a single thread.
|
||||
#[cfg(all(feature = "std", not(all(miri, target_vendor = "apple"))))]
|
||||
self.timer_mut().unset_timer();
|
||||
}
|
||||
@ -393,28 +395,38 @@ unsafe impl Send for InProcessExecutorHandlerData {}
|
||||
unsafe impl Sync for InProcessExecutorHandlerData {}
|
||||
|
||||
impl InProcessExecutorHandlerData {
|
||||
/// # Safety
|
||||
/// Only safe if not called twice and if the executor is not used from another borrow after this.
|
||||
#[cfg(any(unix, feature = "std"))]
|
||||
pub(crate) fn executor_mut<'a, E>(&self) -> &'a mut E {
|
||||
pub(crate) unsafe fn executor_mut<'a, E>(&self) -> &'a mut E {
|
||||
unsafe { (self.executor_ptr as *mut E).as_mut().unwrap() }
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Only safe if not called twice and if the state is not used from another borrow after this.
|
||||
#[cfg(any(unix, feature = "std"))]
|
||||
pub(crate) fn state_mut<'a, S>(&self) -> &'a mut S {
|
||||
pub(crate) unsafe fn state_mut<'a, S>(&self) -> &'a mut S {
|
||||
unsafe { (self.state_ptr as *mut S).as_mut().unwrap() }
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Only safe if not called twice and if the event manager is not used from another borrow after this.
|
||||
#[cfg(any(unix, feature = "std"))]
|
||||
pub(crate) fn event_mgr_mut<'a, EM>(&self) -> &'a mut EM {
|
||||
pub(crate) unsafe fn event_mgr_mut<'a, EM>(&self) -> &'a mut EM {
|
||||
unsafe { (self.event_mgr_ptr as *mut EM).as_mut().unwrap() }
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Only safe if not called twice and if the fuzzer is not used from another borrow after this.
|
||||
#[cfg(any(unix, feature = "std"))]
|
||||
pub(crate) fn fuzzer_mut<'a, Z>(&self) -> &'a mut Z {
|
||||
pub(crate) unsafe fn fuzzer_mut<'a, Z>(&self) -> &'a mut Z {
|
||||
unsafe { (self.fuzzer_ptr as *mut Z).as_mut().unwrap() }
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Only safe if not called concurrently.
|
||||
#[cfg(any(unix, feature = "std"))]
|
||||
pub(crate) fn take_current_input<'a, I>(&mut self) -> &'a I {
|
||||
pub(crate) unsafe fn take_current_input<'a, I>(&mut self) -> &'a I {
|
||||
let r = unsafe { (self.current_input_ptr as *const I).as_ref().unwrap() };
|
||||
self.current_input_ptr = ptr::null();
|
||||
r
|
||||
@ -463,36 +475,51 @@ pub(crate) static mut GLOBAL_STATE: InProcessExecutorHandlerData = InProcessExec
|
||||
};
|
||||
|
||||
/// Get the inprocess [`crate::state::State`]
|
||||
///
|
||||
/// # Safety
|
||||
/// Only safe if not called twice and if the state is not accessed from another borrow while this one is alive.
|
||||
#[must_use]
|
||||
pub fn inprocess_get_state<'a, S>() -> Option<&'a mut S> {
|
||||
pub unsafe fn inprocess_get_state<'a, S>() -> Option<&'a mut S> {
|
||||
unsafe { (GLOBAL_STATE.state_ptr as *mut S).as_mut() }
|
||||
}
|
||||
|
||||
/// Get the [`crate::events::EventManager`]
|
||||
///
|
||||
/// # Safety
|
||||
/// Only safe if not called twice and if the event manager is not accessed from another borrow while this one is alive.
|
||||
#[must_use]
|
||||
pub fn inprocess_get_event_manager<'a, EM>() -> Option<&'a mut EM> {
|
||||
pub unsafe fn inprocess_get_event_manager<'a, EM>() -> Option<&'a mut EM> {
|
||||
unsafe { (GLOBAL_STATE.event_mgr_ptr as *mut EM).as_mut() }
|
||||
}
|
||||
|
||||
/// Gets the inprocess [`crate::fuzzer::Fuzzer`]
|
||||
///
|
||||
/// # Safety
|
||||
/// Only safe if not called twice and if the fuzzer is not accessed from another borrow while this one is alive.
|
||||
#[must_use]
|
||||
pub fn inprocess_get_fuzzer<'a, F>() -> Option<&'a mut F> {
|
||||
pub unsafe fn inprocess_get_fuzzer<'a, F>() -> Option<&'a mut F> {
|
||||
unsafe { (GLOBAL_STATE.fuzzer_ptr as *mut F).as_mut() }
|
||||
}
|
||||
|
||||
/// Gets the inprocess [`Executor`]
|
||||
///
|
||||
/// # Safety
|
||||
/// Only safe if not called twice and if the executor is not accessed from another borrow while this one is alive.
|
||||
#[must_use]
|
||||
pub fn inprocess_get_executor<'a, E>() -> Option<&'a mut E> {
|
||||
pub unsafe fn inprocess_get_executor<'a, E>() -> Option<&'a mut E> {
|
||||
unsafe { (GLOBAL_STATE.executor_ptr as *mut E).as_mut() }
|
||||
}
|
||||
|
||||
/// Gets the inprocess input
|
||||
///
|
||||
/// # Safety
|
||||
/// Only safe if not called concurrently and if the input is not used mutably while this reference is alive.
|
||||
#[must_use]
|
||||
pub fn inprocess_get_input<'a, I>() -> Option<&'a I> {
|
||||
pub unsafe fn inprocess_get_input<'a, I>() -> Option<&'a I> {
|
||||
unsafe { (GLOBAL_STATE.current_input_ptr as *const I).as_ref() }
|
||||
}
|
||||
|
||||
/// Know if we ar eexecuting in a crash/timeout handler
|
||||
/// Returns if we are executing in a crash/timeout handler
|
||||
#[must_use]
|
||||
pub fn inprocess_in_handler() -> bool {
|
||||
unsafe { GLOBAL_STATE.in_handler }
|
||||
|
@ -107,19 +107,21 @@ unsafe impl Sync for InProcessForkExecutorGlobalData {}
|
||||
unsafe impl Send for InProcessForkExecutorGlobalData {}
|
||||
|
||||
impl InProcessForkExecutorGlobalData {
|
||||
pub(crate) fn executor_mut<'a, E>(&self) -> &'a mut E {
|
||||
/// # Safety
|
||||
/// Only safe if not called twice and if the executor is not used from another borrow after this.
|
||||
pub(crate) unsafe fn executor_mut<'a, E>(&self) -> &'a mut E {
|
||||
unsafe { (self.executor_ptr as *mut E).as_mut().unwrap() }
|
||||
}
|
||||
|
||||
pub(crate) fn state_mut<'a, S>(&self) -> &'a mut S {
|
||||
/// # Safety
|
||||
/// Only safe if not called twice and if the state is not used from another borrow after this.
|
||||
pub(crate) unsafe fn state_mut<'a, S>(&self) -> &'a mut S {
|
||||
unsafe { (self.state_ptr as *mut S).as_mut().unwrap() }
|
||||
}
|
||||
|
||||
/*fn current_input<'a, I>(&self) -> &'a I {
|
||||
unsafe { (self.current_input_ptr as *const I).as_ref().unwrap() }
|
||||
}*/
|
||||
|
||||
pub(crate) fn take_current_input<'a, I>(&mut self) -> &'a I {
|
||||
/// # Safety
|
||||
/// Only safe if not called concurrently.
|
||||
pub(crate) unsafe fn take_current_input<'a, I>(&mut self) -> &'a I {
|
||||
let r = unsafe { (self.current_input_ptr as *const I).as_ref().unwrap() };
|
||||
self.current_input_ptr = null();
|
||||
r
|
||||
|
@ -256,6 +256,8 @@ impl TimerStruct {
|
||||
#[cfg(all(unix, not(target_os = "linux")))]
|
||||
/// Set up timer
|
||||
pub fn set_timer(&mut self) {
|
||||
// # Safety
|
||||
// Safe because the variables are all alive at this time and don't contain pointers.
|
||||
unsafe {
|
||||
setitimer(ITIMER_REAL, &mut self.itimerval, core::ptr::null_mut());
|
||||
}
|
||||
@ -310,18 +312,22 @@ impl TimerStruct {
|
||||
}
|
||||
|
||||
#[cfg(all(unix, not(target_os = "linux")))]
|
||||
/// Disalarm timer
|
||||
/// Disable the timer
|
||||
pub fn unset_timer(&mut self) {
|
||||
// # Safety
|
||||
// No user-provided values.
|
||||
unsafe {
|
||||
let mut itimerval_zero: Itimerval = core::mem::zeroed();
|
||||
setitimer(ITIMER_REAL, &mut itimerval_zero, core::ptr::null_mut());
|
||||
}
|
||||
}
|
||||
|
||||
/// Disalarm timer
|
||||
/// Disable the timer
|
||||
#[cfg(target_os = "linux")]
|
||||
#[allow(unused_variables)]
|
||||
pub fn unset_timer(&mut self) {
|
||||
// # Safety
|
||||
// Just API calls, no user-provided inputs
|
||||
if self.batch_mode {
|
||||
unsafe {
|
||||
let elapsed = current_time().saturating_sub(self.tmout_start_time);
|
||||
@ -354,8 +360,10 @@ impl TimerStruct {
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
/// Disalarm
|
||||
/// Disable the timer
|
||||
pub fn unset_timer(&mut self) {
|
||||
// # Safety
|
||||
// The value accesses are guarded by a critical section.
|
||||
unsafe {
|
||||
let data = addr_of_mut!(GLOBAL_STATE);
|
||||
|
||||
|
@ -38,11 +38,11 @@ static COUNT_CLASS_LOOKUP: [u8; 256] = [
|
||||
static mut COUNT_CLASS_LOOKUP_16: Vec<u16> = vec![];
|
||||
|
||||
/// Initialize the 16-byte hitcounts map
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Calling this from multiple threads may be racey and hence leak 65k mem or even create a broken lookup vec.
|
||||
fn init_count_class_16() {
|
||||
// # Safety
|
||||
//
|
||||
// Calling this from multiple threads may be racey and hence leak 65k mem or even create a broken lookup vec.
|
||||
// We can live with that.
|
||||
unsafe {
|
||||
let count_class_lookup_16 = &mut *addr_of_mut!(COUNT_CLASS_LOOKUP_16);
|
||||
|
||||
|
@ -310,6 +310,8 @@ mod linux {
|
||||
}
|
||||
|
||||
fn new_cpu_set() -> cpu_set_t {
|
||||
// # Safety
|
||||
// Returning a new zeroed value that is allowed to be 0.
|
||||
unsafe { zeroed::<cpu_set_t>() }
|
||||
}
|
||||
|
||||
@ -733,6 +735,8 @@ mod netbsd {
|
||||
}
|
||||
|
||||
fn new_cpuset() -> *mut _cpuset {
|
||||
// # Safety
|
||||
// Simply creating new empty cpuset. No user-provided params.
|
||||
unsafe { _cpuset_create() }
|
||||
}
|
||||
}
|
||||
|
@ -663,6 +663,8 @@ impl LlmpMsg {
|
||||
/// Gets the buffer from this message as slice, with the correct length.
|
||||
#[inline]
|
||||
pub fn try_as_slice<SHM: ShMem>(&self, map: &mut LlmpSharedMap<SHM>) -> Result<&[u8], Error> {
|
||||
// # Safety
|
||||
// Safe because we check if we're in a valid shmem region first.
|
||||
unsafe {
|
||||
if self.in_shmem(map) {
|
||||
Ok(self.as_slice_unsafe())
|
||||
@ -1818,6 +1820,8 @@ where
|
||||
#[allow(clippy::type_complexity)]
|
||||
#[inline]
|
||||
pub fn recv_buf_with_flags(&mut self) -> Result<Option<(ClientId, Tag, Flags, &[u8])>, Error> {
|
||||
// # Safety
|
||||
// No user-provided potentially unsafe parameters.
|
||||
unsafe {
|
||||
Ok(match self.recv()? {
|
||||
Some(msg) => Some((
|
||||
@ -1835,6 +1839,8 @@ where
|
||||
#[allow(clippy::type_complexity)]
|
||||
#[inline]
|
||||
pub fn recv_buf_blocking_with_flags(&mut self) -> Result<(ClientId, Tag, Flags, &[u8]), Error> {
|
||||
// # Safety
|
||||
// No user-provided potentially unsafe parameters.
|
||||
unsafe {
|
||||
let msg = self.recv_blocking()?;
|
||||
Ok((
|
||||
@ -1849,6 +1855,8 @@ where
|
||||
/// Returns the next sender, tag, buf, looping until it becomes available
|
||||
#[inline]
|
||||
pub fn recv_buf_blocking(&mut self) -> Result<(ClientId, Tag, &[u8]), Error> {
|
||||
// # Safety
|
||||
// No user-provided potentially unsafe parameters.
|
||||
unsafe {
|
||||
let msg = self.recv_blocking()?;
|
||||
Ok((
|
||||
@ -1953,6 +1961,8 @@ where
|
||||
/// Marks the containing page as `safe_to_unmap`.
|
||||
/// This indicates, that the page may safely be unmapped by the sender.
|
||||
pub fn mark_safe_to_unmap(&mut self) {
|
||||
// # Safety
|
||||
// No user-provided potentially unsafe parameters.
|
||||
unsafe {
|
||||
(*self.page_mut()).receiver_joined();
|
||||
}
|
||||
@ -3028,6 +3038,9 @@ where
|
||||
#[cfg(any(unix, all(windows, feature = "std")))]
|
||||
#[allow(clippy::unused_self)]
|
||||
fn is_shutting_down(&self) -> bool {
|
||||
// # Safety
|
||||
// No user-provided potentially unsafe parameters.
|
||||
// Volatile read.
|
||||
unsafe { ptr::read_volatile(ptr::addr_of!(LLMP_SIGHANDLER_STATE.shutting_down)) }
|
||||
}
|
||||
|
||||
@ -3091,6 +3104,8 @@ where
|
||||
/// Tell the broker to disconnect this client from it.
|
||||
#[cfg(feature = "std")]
|
||||
fn announce_client_exit(sender: &mut LlmpSender<SP>, client_id: u32) -> Result<(), Error> {
|
||||
// # Safety
|
||||
// No user-provided potentially unsafe parameters.
|
||||
unsafe {
|
||||
let msg = sender
|
||||
.alloc_next(size_of::<LlmpClientExitInfo>())
|
||||
|
@ -242,7 +242,7 @@ pub mod serdeany_registry {
|
||||
/// # Safety
|
||||
/// This may never be called concurrently or at the same time as `register`.
|
||||
/// It dereferences the `REGISTRY` hashmap and adds the given type to it.
|
||||
pub fn finalize() {
|
||||
pub unsafe fn finalize() {
|
||||
unsafe {
|
||||
(*addr_of_mut!(REGISTRY)).finalize();
|
||||
}
|
||||
|
@ -693,6 +693,9 @@ pub mod unix_shmem {
|
||||
/// Create a new [`MmapShMem`]
|
||||
/// This will *NOT* automatically delete the shmem files, meaning that it's user's responsibility to delete all `/dev/shm/libafl_*` after fuzzing
|
||||
pub fn new(map_size: usize, rand_id: u32) -> Result<Self, Error> {
|
||||
// # Safety
|
||||
// No user-provided potentially unsafe parameters.
|
||||
// FFI Calls.
|
||||
unsafe {
|
||||
let mut full_file_name = format!("/libafl_{}_{}", process::id(), rand_id);
|
||||
// leave one byte space for the null byte.
|
||||
@ -765,6 +768,9 @@ pub mod unix_shmem {
|
||||
|
||||
#[allow(clippy::unnecessary_wraps)]
|
||||
fn shmem_from_id_and_size(id: ShMemId, map_size: usize) -> Result<Self, Error> {
|
||||
// # Safety
|
||||
// No user-provided potentially unsafe parameters.
|
||||
// FFI Calls.
|
||||
unsafe {
|
||||
/* map the shared memory segment to the address space of the process */
|
||||
#[cfg(target_vendor = "apple")]
|
||||
|
@ -324,7 +324,9 @@ impl Allocator {
|
||||
continue;
|
||||
}
|
||||
// First poison the memory.
|
||||
unsafe {
|
||||
Self::poison(map_to_shadow!(self, address), allocation.size);
|
||||
}
|
||||
|
||||
// Reset the allocaiton metadata object
|
||||
allocation.size = 0;
|
||||
@ -359,7 +361,11 @@ impl Allocator {
|
||||
}
|
||||
}
|
||||
|
||||
fn unpoison(start: usize, size: usize) {
|
||||
/// Unpoison an area in memory
|
||||
///
|
||||
/// # Safety
|
||||
/// start needs to be a valid address, We need to be able to fill `size / 8` bytes.
|
||||
unsafe fn unpoison(start: usize, size: usize) {
|
||||
unsafe {
|
||||
std::slice::from_raw_parts_mut(start as *mut u8, size / 8).fill(0xff);
|
||||
|
||||
@ -372,8 +378,11 @@ impl Allocator {
|
||||
}
|
||||
}
|
||||
|
||||
/// Poisonn an area in memory
|
||||
pub fn poison(start: usize, size: usize) {
|
||||
/// Poison an area in memory
|
||||
///
|
||||
/// # Safety
|
||||
/// start needs to be a valid address, We need to be able to fill `size / 8` bytes.
|
||||
pub unsafe fn poison(start: usize, size: usize) {
|
||||
unsafe {
|
||||
std::slice::from_raw_parts_mut(start as *mut u8, size / 8).fill(0x0);
|
||||
|
||||
@ -445,8 +454,10 @@ impl Allocator {
|
||||
}
|
||||
|
||||
if unpoison {
|
||||
unsafe {
|
||||
Self::unpoison(shadow_mapping_start, end - start);
|
||||
}
|
||||
}
|
||||
|
||||
(shadow_mapping_start, (end - start) / 8 + 1)
|
||||
}
|
||||
@ -633,6 +644,8 @@ impl Allocator {
|
||||
size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Unpoisons all memory
|
||||
#[cfg(not(target_vendor = "apple"))]
|
||||
pub fn unpoison_all_existing_memory(&mut self) {
|
||||
RangeDetails::enumerate_with_prot(
|
||||
|
@ -216,7 +216,11 @@ impl FridaRuntime for AsanRuntime {
|
||||
|
||||
let target_bytes = input.target_bytes();
|
||||
let slice = target_bytes.as_slice();
|
||||
// # Safety
|
||||
// The ptr and length are correct.
|
||||
unsafe {
|
||||
self.poison(slice.as_ptr() as usize, slice.len());
|
||||
}
|
||||
self.reset_allocations();
|
||||
|
||||
Ok(())
|
||||
@ -282,7 +286,11 @@ impl AsanRuntime {
|
||||
}
|
||||
|
||||
/// Make sure the specified memory is poisoned
|
||||
pub fn poison(&mut self, address: usize, size: usize) {
|
||||
///
|
||||
/// # Safety
|
||||
/// The address needs to be a valid address, the size needs to be correct.
|
||||
/// This will dereference at the address.
|
||||
pub unsafe fn poison(&mut self, address: usize, size: usize) {
|
||||
Allocator::poison(self.allocator.map_to_shadow(address), size);
|
||||
}
|
||||
|
||||
|
@ -1237,8 +1237,10 @@ impl AsanRuntime {
|
||||
res
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// `addr` will get dereferenced.
|
||||
#[inline]
|
||||
pub fn hook_munmap(
|
||||
pub unsafe fn hook_munmap(
|
||||
&mut self,
|
||||
original: extern "C" fn(addr: *const c_void, length: usize) -> i32,
|
||||
addr: *const c_void,
|
||||
|
@ -138,8 +138,11 @@ where
|
||||
}
|
||||
|
||||
impl<S, OT> NyxExecutor<S, OT> {
|
||||
/// convert `trace_bits` ptr into real trace map
|
||||
pub fn trace_bits(self) -> &'static mut [u8] {
|
||||
/// Convert `trace_bits` ptr into real trace map
|
||||
///
|
||||
/// # Safety
|
||||
/// Mutable borrow may only be used once at a time.
|
||||
pub unsafe fn trace_bits(self) -> &'static mut [u8] {
|
||||
unsafe {
|
||||
std::slice::from_raw_parts_mut(self.helper.bitmap_buffer, self.helper.bitmap_size)
|
||||
}
|
||||
|
@ -5,13 +5,13 @@
|
||||
// use std::io::{BufRead, BufReader};
|
||||
use std::{
|
||||
collections::hash_map,
|
||||
env, fs,
|
||||
fs::File,
|
||||
env,
|
||||
fs::{self, File},
|
||||
hash::Hasher,
|
||||
io::{Read, Seek, SeekFrom, Write},
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
ptr::addr_of_mut,
|
||||
sync::{LazyLock, Mutex},
|
||||
};
|
||||
|
||||
//#[rustversion::nightly]
|
||||
@ -30,26 +30,22 @@ use crate::build::QEMU_REVISION;
|
||||
|
||||
const LLVM_VERSION_MAX: i32 = 33;
|
||||
|
||||
static mut CARGO_RPATH: Option<Vec<String>> = None;
|
||||
static CARGO_RPATH: LazyLock<Mutex<Vec<String>>> = LazyLock::new(Mutex::default);
|
||||
static CARGO_RPATH_SEPARATOR: &str = "|";
|
||||
|
||||
// Add to the list of `rpath`s.
|
||||
// Later, print the `cargo::rpath` using [`cargo_propagate_rpath`]
|
||||
pub fn cargo_add_rpath(rpath: &str) {
|
||||
unsafe {
|
||||
if let Some(rpaths) = &mut *addr_of_mut!(CARGO_RPATH) {
|
||||
rpaths.push(rpath.to_string());
|
||||
} else {
|
||||
CARGO_RPATH = Some(vec![rpath.to_string()]);
|
||||
}
|
||||
}
|
||||
CARGO_RPATH.lock().unwrap().push(rpath.to_string());
|
||||
}
|
||||
|
||||
// Print the `rpath`, set via [`cargo_add_rpath`] as `cargo::rpath`
|
||||
pub fn cargo_propagate_rpath() {
|
||||
unsafe {
|
||||
if let Some(cargo_cmds) = &mut *addr_of_mut!(CARGO_RPATH) {
|
||||
let cargo_cmds = CARGO_RPATH.lock().unwrap();
|
||||
if !cargo_cmds.is_empty() {
|
||||
let rpath = cargo_cmds.join(CARGO_RPATH_SEPARATOR);
|
||||
println!("cargo:rpath={rpath}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Must be called from final binary crates
|
||||
|
@ -171,7 +171,9 @@ pub fn make_plugin_meminfo(oi: MemOpIdx, rw: qemu_plugin_mem_rw) -> qemu_plugin_
|
||||
|
||||
// from include/hw/core/cpu.h
|
||||
|
||||
/// # Safety
|
||||
/// Will dereference the `cpu` pointer.
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn cpu_env(cpu: *mut CPUState) -> *mut CPUArchState {
|
||||
pub unsafe fn cpu_env(cpu: *mut CPUState) -> *mut CPUArchState {
|
||||
unsafe { cpu.add(1) as *mut CPUArchState }
|
||||
}
|
||||
|
@ -650,7 +650,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn backdoor_closure(&mut self, hook: BackdoorHookClosure<ET, S>) -> BackdoorHookId {
|
||||
/// # Safety
|
||||
/// Will dereference the hook as [`FatPtr`].
|
||||
pub unsafe fn backdoor_closure(&mut self, hook: BackdoorHookClosure<ET, S>) -> BackdoorHookId {
|
||||
unsafe {
|
||||
let fat: FatPtr = transmute(hook);
|
||||
self.backdoor_hooks
|
||||
@ -689,7 +691,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn backdoor(&mut self, hook: BackdoorHook<ET, S>) -> Option<BackdoorHookId> {
|
||||
/// # Safety
|
||||
/// This can call through to a potentialy unsafe `backtoor_function`
|
||||
pub unsafe fn backdoor(&mut self, hook: BackdoorHook<ET, S>) -> Option<BackdoorHookId> {
|
||||
match hook {
|
||||
Hook::Function(f) => Some(self.backdoor_function(f)),
|
||||
Hook::Closure(c) => Some(self.backdoor_closure(c)),
|
||||
@ -780,6 +784,8 @@ where
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn syscalls_function(&mut self, hook: PreSyscallHookFn<ET, S>) -> PreSyscallHookId {
|
||||
// # Safety
|
||||
// Will dereference the hook as [`FatPtr`].
|
||||
unsafe {
|
||||
self.qemu_hooks
|
||||
.add_pre_syscall_hook(transmute(hook), func_pre_syscall_hook_wrapper::<ET, S>)
|
||||
@ -788,6 +794,8 @@ where
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn syscalls_closure(&mut self, hook: PreSyscallHookClosure<ET, S>) -> PreSyscallHookId {
|
||||
// # Safety
|
||||
// Will dereference the hook as [`FatPtr`].
|
||||
unsafe {
|
||||
let fat: FatPtr = transmute(hook);
|
||||
|
||||
@ -830,6 +838,8 @@ where
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn after_syscalls_function(&mut self, hook: PostSyscallHookFn<ET, S>) -> PostSyscallHookId {
|
||||
// # Safety
|
||||
// Will dereference the hook as [`FatPtr`]. This should be ok.
|
||||
unsafe {
|
||||
self.qemu_hooks
|
||||
.add_post_syscall_hook(transmute(hook), func_post_syscall_hook_wrapper::<ET, S>)
|
||||
@ -869,12 +879,16 @@ where
|
||||
}
|
||||
|
||||
pub fn crash_function(&mut self, hook: fn(&mut EmulatorModules<ET, S>, target_signal: i32)) {
|
||||
// # Safety
|
||||
// Will cast the valid hook to a ptr.
|
||||
self.qemu_hooks.set_crash_hook(crash_hook_wrapper::<ET, S>);
|
||||
self.crash_hooks
|
||||
.push(HookRepr::Function(hook as *const libc::c_void));
|
||||
}
|
||||
|
||||
pub fn crash_closure(&mut self, hook: CrashHookClosure<ET, S>) {
|
||||
// # Safety
|
||||
// Will cast the hook to a [`FatPtr`].
|
||||
unsafe {
|
||||
self.qemu_hooks.set_crash_hook(crash_hook_wrapper::<ET, S>);
|
||||
self.crash_hooks.push(HookRepr::Closure(transmute(hook)));
|
||||
@ -1044,7 +1058,9 @@ where
|
||||
)
|
||||
}
|
||||
|
||||
pub fn backdoor(&mut self, hook: BackdoorHook<ET, S>) -> Option<BackdoorHookId> {
|
||||
/// # Safety
|
||||
/// This will potentially call an unsafe backdoor hook
|
||||
pub unsafe fn backdoor(&mut self, hook: BackdoorHook<ET, S>) -> Option<BackdoorHookId> {
|
||||
self.hooks.backdoor(hook)
|
||||
}
|
||||
|
||||
@ -1052,7 +1068,9 @@ where
|
||||
self.hooks.backdoor_function(hook)
|
||||
}
|
||||
|
||||
pub fn backdoor_closure(&mut self, hook: BackdoorHookClosure<ET, S>) -> BackdoorHookId {
|
||||
/// # Safety
|
||||
/// Calls through to the potentially unsafe `backdoor_closure`
|
||||
pub unsafe fn backdoor_closure(&mut self, hook: BackdoorHookClosure<ET, S>) -> BackdoorHookId {
|
||||
self.hooks.backdoor_closure(hook)
|
||||
}
|
||||
|
||||
@ -1119,6 +1137,8 @@ where
|
||||
}
|
||||
|
||||
pub fn first_exec_all(&mut self, state: &mut S) {
|
||||
// # Safety
|
||||
// We assume that the emulator was initialized correctly
|
||||
unsafe {
|
||||
self.modules_mut()
|
||||
.first_exec_all(Self::emulator_modules_mut_unchecked(), state);
|
||||
@ -1126,6 +1146,8 @@ where
|
||||
}
|
||||
|
||||
pub fn pre_exec_all(&mut self, state: &mut S, input: &S::Input) {
|
||||
// # Safety
|
||||
// We assume that the emulator was initialized correctly
|
||||
unsafe {
|
||||
self.modules_mut()
|
||||
.pre_exec_all(Self::emulator_modules_mut_unchecked(), state, input);
|
||||
@ -1201,8 +1223,10 @@ where
|
||||
self.hooks.syscalls(hook)
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Calls through to the, potentially unsafe, `syscalls_function`
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn syscalls_function(
|
||||
pub unsafe fn syscalls_function(
|
||||
&mut self,
|
||||
hook: fn(
|
||||
&mut EmulatorModules<ET, S>,
|
||||
@ -1221,8 +1245,10 @@ where
|
||||
self.hooks.syscalls_function(hook)
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Calls through to the, potentially unsafe, `syscalls_closure`
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn syscalls_closure(
|
||||
pub unsafe fn syscalls_closure(
|
||||
&mut self,
|
||||
hook: Box<
|
||||
dyn for<'a> FnMut(
|
||||
@ -1248,8 +1274,10 @@ where
|
||||
self.hooks.after_syscalls(hook)
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Calls through to the, potentially unsafe, `after_syscalls_function`
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn after_syscalls_function(
|
||||
pub unsafe fn after_syscalls_function(
|
||||
&mut self,
|
||||
hook: fn(
|
||||
&mut EmulatorModules<ET, S>,
|
||||
@ -1296,7 +1324,9 @@ where
|
||||
self.hooks.crash_function(hook);
|
||||
}
|
||||
|
||||
pub fn crash_closure(&mut self, hook: CrashHookClosure<ET, S>) {
|
||||
/// # Safety
|
||||
/// Calls through to the, potentially unsafe, registered `crash_closure`
|
||||
pub unsafe fn crash_closure(&mut self, hook: CrashHookClosure<ET, S>) {
|
||||
self.hooks.crash_closure(hook);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ use core::{
|
||||
};
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
use std::ptr;
|
||||
#[cfg(emulation_mode = "systemmode")]
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use libafl::{
|
||||
corpus::Corpus,
|
||||
@ -17,14 +19,14 @@ use libafl::{
|
||||
},
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::UsesInput,
|
||||
observers::{ObserversTuple, UsesObservers},
|
||||
state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState},
|
||||
Error, ExecutionProcessor, HasScheduler,
|
||||
};
|
||||
#[cfg(feature = "fork")]
|
||||
use libafl::{
|
||||
events::EventManager, executors::InProcessForkExecutor, state::HasLastReportTime, HasMetadata,
|
||||
events::EventManager, executors::InProcessForkExecutor, inputs::UsesInput,
|
||||
state::HasLastReportTime, HasMetadata,
|
||||
};
|
||||
#[cfg(feature = "fork")]
|
||||
use libafl_bolts::shmem::ShMemProvider;
|
||||
@ -72,8 +74,11 @@ pub unsafe fn inproc_qemu_crash_handler(
|
||||
}
|
||||
|
||||
#[cfg(emulation_mode = "systemmode")]
|
||||
pub(crate) static mut BREAK_ON_TMOUT: bool = false;
|
||||
pub(crate) static BREAK_ON_TMOUT: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
/// # Safety
|
||||
/// Can call through the `unix_signal_handler::inproc_timeout_handler`.
|
||||
/// Calling this method multiple times concurrently can lead to race conditions.
|
||||
#[cfg(emulation_mode = "systemmode")]
|
||||
pub unsafe fn inproc_qemu_timeout_handler<E, EM, OF, Z>(
|
||||
signal: Signal,
|
||||
@ -89,7 +94,7 @@ pub unsafe fn inproc_qemu_timeout_handler<E, EM, OF, Z>(
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
{
|
||||
if BREAK_ON_TMOUT {
|
||||
if BREAK_ON_TMOUT.load(Ordering::Acquire) {
|
||||
libafl_exit_request_timeout();
|
||||
} else {
|
||||
libafl::executors::hooks::unix::unix_signal_handler::inproc_timeout_handler::<E, EM, OF, Z>(
|
||||
@ -157,11 +162,15 @@ where
|
||||
}
|
||||
};
|
||||
|
||||
// # Safety
|
||||
// We assume our crash handlers to be safe/quit after execution.
|
||||
unsafe {
|
||||
inner
|
||||
.exposed_executor_state_mut()
|
||||
.modules_mut()
|
||||
.crash_closure(Box::new(handler));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(emulation_mode = "systemmode")]
|
||||
{
|
||||
@ -185,9 +194,7 @@ where
|
||||
|
||||
#[cfg(emulation_mode = "systemmode")]
|
||||
pub fn break_on_timeout(&mut self) {
|
||||
unsafe {
|
||||
BREAK_ON_TMOUT = true;
|
||||
}
|
||||
BREAK_ON_TMOUT.store(true, Ordering::Release);
|
||||
}
|
||||
|
||||
pub fn inner_mut(
|
||||
|
@ -543,19 +543,19 @@ static mut CALLSTACKS: Option<ThreadLocal<UnsafeCell<Vec<GuestAddr>>>> = None;
|
||||
#[derive(Debug)]
|
||||
pub struct FullBacktraceCollector {}
|
||||
|
||||
impl Default for FullBacktraceCollector {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl FullBacktraceCollector {
|
||||
pub fn new() -> Self {
|
||||
/// # Safety
|
||||
/// This accesses the global [`CALLSTACKS`] variable and may not be called concurrently.
|
||||
pub unsafe fn new() -> Self {
|
||||
unsafe { (*addr_of_mut!(CALLSTACKS)) = Some(ThreadLocal::new()) };
|
||||
Self {}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
// # Safety
|
||||
// This accesses the global [`CALLSTACKS`] variable.
|
||||
// While it is racey, it might be fine if multiple clear the vecs concurrently.
|
||||
// TODO: This should probably be rewritten in a safer way.
|
||||
unsafe {
|
||||
for tls in (*addr_of_mut!(CALLSTACKS)).as_mut().unwrap().iter_mut() {
|
||||
(*tls.get()).clear();
|
||||
@ -564,6 +564,9 @@ impl FullBacktraceCollector {
|
||||
}
|
||||
|
||||
pub fn backtrace() -> Option<&'static [GuestAddr]> {
|
||||
// # Safety
|
||||
// This accesses the global [`CALLSTACKS`] variable.
|
||||
// However, the actual variable access is behind a `ThreadLocal` class.
|
||||
unsafe {
|
||||
if let Some(c) = (*addr_of_mut!(CALLSTACKS)).as_mut() {
|
||||
Some(&*c.get_or_default().get())
|
||||
|
@ -269,7 +269,9 @@ impl CmpLogRoutinesModule {
|
||||
self.address_filter.allowed(&addr)
|
||||
}
|
||||
|
||||
extern "C" fn on_call(k: u64, _pc: GuestAddr) {
|
||||
/// # Safety
|
||||
/// Dereferences k as pointer eventually.
|
||||
unsafe extern "C" fn on_call(k: u64, _pc: GuestAddr) {
|
||||
unsafe {
|
||||
if CMPLOG_ENABLED == 0 {
|
||||
return;
|
||||
|
@ -592,13 +592,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub extern "C" fn trace_edge_hitcount(_: *const (), id: u64) {
|
||||
// # Safety
|
||||
// Calling this concurrently for the same id is racey and may lose updates.
|
||||
pub unsafe extern "C" fn trace_edge_hitcount(_: *const (), id: u64) {
|
||||
unsafe {
|
||||
EDGES_MAP[id as usize] = EDGES_MAP[id as usize].wrapping_add(1);
|
||||
}
|
||||
}
|
||||
|
||||
pub extern "C" fn trace_edge_single(_: *const (), id: u64) {
|
||||
// # Safety
|
||||
// Worst case we set the byte to 1 multiple times..
|
||||
unsafe {
|
||||
EDGES_MAP[id as usize] = 1;
|
||||
}
|
||||
@ -649,14 +653,19 @@ where
|
||||
Some(id)
|
||||
}
|
||||
|
||||
pub extern "C" fn trace_edge_hitcount_ptr(_: *const (), id: u64) {
|
||||
/// # Safety
|
||||
/// Increases id at `EDGES_MAP_PTR` - potentially racey if called concurrently.
|
||||
pub unsafe extern "C" fn trace_edge_hitcount_ptr(_: *const (), id: u64) {
|
||||
unsafe {
|
||||
let ptr = EDGES_MAP_PTR.add(id as usize);
|
||||
*ptr = (*ptr).wrapping_add(1);
|
||||
}
|
||||
}
|
||||
|
||||
pub extern "C" fn trace_edge_single_ptr(_: *const (), id: u64) {
|
||||
/// # Safety
|
||||
/// Fine.
|
||||
/// Worst case we set the byte to 1 multiple times.
|
||||
pub unsafe extern "C" fn trace_edge_single_ptr(_: *const (), id: u64) {
|
||||
unsafe {
|
||||
let ptr = EDGES_MAP_PTR.add(id as usize);
|
||||
*ptr = 1;
|
||||
@ -708,7 +717,9 @@ where
|
||||
Some(id)
|
||||
}
|
||||
|
||||
pub extern "C" fn trace_block_transition_hitcount(_: *const (), id: u64) {
|
||||
/// # Safety
|
||||
/// Dereferences the global `PREV_LOC` variable. May not be called concurrently.
|
||||
pub unsafe extern "C" fn trace_block_transition_hitcount(_: *const (), id: u64) {
|
||||
unsafe {
|
||||
PREV_LOC.with(|prev_loc| {
|
||||
let x = ((*prev_loc.get() ^ id) as usize) & (EDGES_MAP_SIZE_MAX - 1);
|
||||
@ -719,7 +730,9 @@ pub extern "C" fn trace_block_transition_hitcount(_: *const (), id: u64) {
|
||||
}
|
||||
}
|
||||
|
||||
pub extern "C" fn trace_block_transition_single(_: *const (), id: u64) {
|
||||
/// # Safety
|
||||
/// Dereferences the global `PREV_LOC` variable. May not be called concurrently.
|
||||
pub unsafe extern "C" fn trace_block_transition_single(_: *const (), id: u64) {
|
||||
unsafe {
|
||||
PREV_LOC.with(|prev_loc| {
|
||||
let x = ((*prev_loc.get() ^ id) as usize) & (EDGES_MAP_SIZE_MAX - 1);
|
||||
|
@ -479,6 +479,9 @@ impl AsanGiovese {
|
||||
}
|
||||
|
||||
pub fn alloc_insert(&mut self, pc: GuestAddr, start: GuestAddr, end: GuestAddr) {
|
||||
// # Safety
|
||||
// Will access the global [`FullBacktraceCollector`].
|
||||
// Calling this function concurrently might be racey.
|
||||
let backtrace = FullBacktraceCollector::backtrace()
|
||||
.map(|r| {
|
||||
let mut v = r.to_vec();
|
||||
@ -504,6 +507,9 @@ impl AsanGiovese {
|
||||
}
|
||||
|
||||
pub fn alloc_free(&mut self, qemu: Qemu, pc: GuestAddr, addr: GuestAddr) {
|
||||
// # Safety
|
||||
// Will access the global [`FullBacktraceCollector`].
|
||||
// Calling this function concurrently might be racey.
|
||||
let mut chunk = None;
|
||||
self.alloc_map_mut(addr, |interval, item| {
|
||||
chunk = Some(*interval);
|
||||
@ -796,13 +802,20 @@ impl AsanModule {
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// The `ASan` error report accesses [`FullBacktraceCollector`]
|
||||
#[must_use]
|
||||
pub fn with_asan_report(
|
||||
pub unsafe fn with_asan_report(
|
||||
rt: Pin<Box<AsanGiovese>>,
|
||||
filter: StdAddressFilter,
|
||||
options: QemuAsanOptions,
|
||||
) -> Self {
|
||||
Self::with_error_callback(rt, filter, Box::new(asan_report), options)
|
||||
Self::with_error_callback(
|
||||
rt,
|
||||
filter,
|
||||
Box::new(|rt, qemu, pc, err| unsafe { asan_report(rt, qemu, pc, err) }),
|
||||
options,
|
||||
)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
@ -1518,9 +1531,12 @@ mod addr2line_legacy {
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Will access the global [`FullBacktraceCollector`].
|
||||
/// Calling this function concurrently might be racey.
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub fn asan_report(rt: &AsanGiovese, qemu: Qemu, pc: GuestAddr, err: AsanError) {
|
||||
pub unsafe fn asan_report(rt: &AsanGiovese, qemu: Qemu, pc: GuestAddr, err: AsanError) {
|
||||
let mut regions = HashMap::new();
|
||||
for region in qemu.mappings() {
|
||||
if let Some(path) = region.path() {
|
||||
|
@ -549,7 +549,7 @@ create_hook_types!(
|
||||
EdgeExec,
|
||||
fn(&mut EmulatorModules<ET, S>, Option<&mut S>, id: u64),
|
||||
Box<dyn for<'a> FnMut(&'a mut EmulatorModules<ET, S>, Option<&'a mut S>, u64)>,
|
||||
extern "C" fn(*const (), id: u64)
|
||||
unsafe extern "C" fn(*const (), id: u64)
|
||||
);
|
||||
create_hook_id!(Edge, libafl_qemu_remove_edge_hook, true);
|
||||
create_gen_wrapper!(edge, (src: GuestAddr, dest: GuestAddr), u64, 1, EdgeHookId);
|
||||
@ -746,7 +746,7 @@ impl QemuHooks {
|
||||
&self,
|
||||
data: T,
|
||||
addr: GuestAddr,
|
||||
callback: extern "C" fn(T, GuestAddr),
|
||||
callback: unsafe extern "C" fn(T, GuestAddr),
|
||||
invalidate_block: bool,
|
||||
) -> InstructionHookId {
|
||||
unsafe {
|
||||
|
@ -1083,7 +1083,9 @@ pub mod pybind {
|
||||
self.qemu.flush_jit();
|
||||
}
|
||||
|
||||
fn set_hook(&self, addr: GuestAddr, hook: PyObject) {
|
||||
/// # Safety
|
||||
/// Removes a hooke from `PY_GENERIC_HOOKS` -> may not be called concurrently!
|
||||
unsafe fn set_hook(&self, addr: GuestAddr, hook: PyObject) {
|
||||
unsafe {
|
||||
let hooks = &mut *core::ptr::addr_of_mut!(PY_GENERIC_HOOKS);
|
||||
let idx = hooks.len();
|
||||
@ -1097,7 +1099,9 @@ pub mod pybind {
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_hooks_at(&self, addr: GuestAddr) -> usize {
|
||||
/// # Safety
|
||||
/// Removes a hooke from `PY_GENERIC_HOOKS` -> may not be called concurrently!
|
||||
unsafe fn remove_hooks_at(&self, addr: GuestAddr) -> usize {
|
||||
unsafe {
|
||||
let hooks = &mut *core::ptr::addr_of_mut!(PY_GENERIC_HOOKS);
|
||||
hooks.retain(|(a, _)| *a != addr);
|
||||
|
@ -338,7 +338,9 @@ pub mod pybind {
|
||||
self.qemu.unmap(addr, size).map_err(PyValueError::new_err)
|
||||
}
|
||||
|
||||
fn set_syscall_hook(&self, hook: PyObject) {
|
||||
/// # Safety
|
||||
/// Accesses the global `PY_SYSCALL_HOOK` and may not be called concurrently.
|
||||
unsafe fn set_syscall_hook(&self, hook: PyObject) {
|
||||
unsafe {
|
||||
(*core::ptr::addr_of_mut!(PY_SYSCALL_HOOK)) = Some(hook);
|
||||
}
|
||||
|
@ -7,6 +7,14 @@
|
||||
feature = "sancov_ctx"
|
||||
))]
|
||||
use alloc::borrow::Cow;
|
||||
#[cfg(any(
|
||||
feature = "sancov_pcguard_edges",
|
||||
feature = "sancov_pcguard_hitcounts",
|
||||
feature = "sancov_ngram4",
|
||||
feature = "sancov_ctx"
|
||||
))]
|
||||
#[cfg(not(feature = "pointer_maps"))]
|
||||
use core::ptr::addr_of;
|
||||
use core::ptr::addr_of_mut;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
|
||||
@ -16,16 +24,19 @@ use crate::{ACCOUNTING_MAP_SIZE, DDG_MAP_SIZE, EDGES_MAP_SIZE_IN_USE, EDGES_MAP_
|
||||
|
||||
/// The map for edges.
|
||||
#[no_mangle]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static mut __afl_area_ptr_local: [u8; EDGES_MAP_SIZE_MAX] = [0; EDGES_MAP_SIZE_MAX];
|
||||
pub use __afl_area_ptr_local as EDGES_MAP;
|
||||
|
||||
/// The map for data dependency
|
||||
#[no_mangle]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static mut __ddg_area_ptr_local: [u8; DDG_MAP_SIZE] = [0; DDG_MAP_SIZE];
|
||||
pub use __ddg_area_ptr_local as DDG_MAP;
|
||||
|
||||
/// The map for accounting mem writes.
|
||||
#[no_mangle]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static mut __afl_acc_memop_ptr_local: [u32; ACCOUNTING_MAP_SIZE] = [0; ACCOUNTING_MAP_SIZE];
|
||||
pub use __afl_acc_memop_ptr_local as ACCOUNTING_MEMOP_MAP;
|
||||
|
||||
@ -60,6 +71,8 @@ pub use __ddg_area_ptr as DDG_MAP_PTR;
|
||||
/// Return Tokens from the compile-time token section
|
||||
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
|
||||
pub fn autotokens() -> Result<Tokens, Error> {
|
||||
// # Safety
|
||||
// All values are checked before dereferencing.
|
||||
unsafe {
|
||||
if __token_start.is_null() || __token_stop.is_null() {
|
||||
Ok(Tokens::default())
|
||||
@ -73,6 +86,7 @@ pub fn autotokens() -> Result<Tokens, Error> {
|
||||
/// The actual size we use for the map of edges.
|
||||
/// This is used for forkserver backend
|
||||
#[no_mangle]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static mut __afl_map_size: usize = EDGES_MAP_SIZE_IN_USE;
|
||||
|
||||
#[cfg(any(
|
||||
@ -182,7 +196,7 @@ pub fn edges_max_num() -> usize {
|
||||
}
|
||||
#[cfg(not(feature = "pointer_maps"))]
|
||||
{
|
||||
EDGES_MAP.len()
|
||||
(*addr_of!(EDGES_MAP)).len()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,11 +23,12 @@ extern "C" {
|
||||
|
||||
/// Calls the (native) libfuzzer initialize function.
|
||||
/// Returns the value returned by the init function.
|
||||
/// # Note
|
||||
///
|
||||
/// # Safety
|
||||
/// Calls the libfuzzer-style init function which is native code.
|
||||
#[allow(clippy::similar_names)]
|
||||
#[allow(clippy::must_use_candidate)] // nobody uses that return code...
|
||||
pub fn libfuzzer_initialize(args: &[String]) -> i32 {
|
||||
pub unsafe fn libfuzzer_initialize(args: &[String]) -> i32 {
|
||||
let args: Vec<String> = args.iter().map(|x| x.clone() + "\0").collect();
|
||||
let argv: Vec<*const u8> = args.iter().map(|x| x.as_bytes().as_ptr()).collect();
|
||||
assert!(argv.len() < i32::MAX as usize);
|
||||
@ -40,9 +41,10 @@ pub fn libfuzzer_initialize(args: &[String]) -> i32 {
|
||||
}
|
||||
|
||||
/// Call a single input of a libfuzzer-style cpp-harness
|
||||
/// # Note
|
||||
///
|
||||
/// # Safety
|
||||
/// Calls the libfuzzer harness. We actually think the target is unsafe and crashes eventually, that's why we do all this fuzzing.
|
||||
#[allow(clippy::must_use_candidate)]
|
||||
pub fn libfuzzer_test_one_input(buf: &[u8]) -> i32 {
|
||||
pub unsafe fn libfuzzer_test_one_input(buf: &[u8]) -> i32 {
|
||||
unsafe { LLVMFuzzerTestOneInput(buf.as_ptr(), buf.len()) }
|
||||
}
|
||||
|
@ -27,10 +27,13 @@ pub unsafe fn extra_counters() -> Vec<OwnedMutSlice<'static, u8>> {
|
||||
}
|
||||
|
||||
/// Initialize the sancov `8-bit-counters` - usually called by `llvm`.
|
||||
///
|
||||
/// # Safety
|
||||
/// Start and stop are being dereferenced.
|
||||
#[no_mangle]
|
||||
#[allow(clippy::cast_sign_loss)]
|
||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||
pub extern "C" fn __sanitizer_cov_8bit_counters_init(start: *mut u8, stop: *mut u8) {
|
||||
pub unsafe extern "C" fn __sanitizer_cov_8bit_counters_init(start: *mut u8, stop: *mut u8) {
|
||||
unsafe {
|
||||
let counter_maps = &mut *addr_of_mut!(COUNTERS_MAPS);
|
||||
for existing in counter_maps {
|
||||
|
@ -3,7 +3,11 @@
|
||||
#[rustversion::nightly]
|
||||
#[cfg(any(feature = "sancov_ngram4", feature = "sancov_ngram8"))]
|
||||
use core::simd::num::SimdUint;
|
||||
use core::{mem::align_of, slice};
|
||||
use core::{
|
||||
mem::align_of,
|
||||
ptr::{addr_of, addr_of_mut},
|
||||
slice,
|
||||
};
|
||||
|
||||
#[cfg(any(
|
||||
feature = "sancov_ngram4",
|
||||
@ -186,7 +190,7 @@ unsafe fn update_ngram(pos: usize) -> usize {
|
||||
let mut reduced = pos;
|
||||
#[cfg(feature = "sancov_ngram4")]
|
||||
{
|
||||
let prev_array_4 = &mut *core::ptr::addr_of_mut!(PREV_ARRAY_4);
|
||||
let prev_array_4 = &mut *addr_of_mut!(PREV_ARRAY_4);
|
||||
*prev_array_4 = prev_array_4.rotate_elements_right::<1>();
|
||||
prev_array_4.shl_assign(SHR_4);
|
||||
prev_array_4.as_mut_array()[0] = pos as u32;
|
||||
@ -194,7 +198,7 @@ unsafe fn update_ngram(pos: usize) -> usize {
|
||||
}
|
||||
#[cfg(feature = "sancov_ngram8")]
|
||||
{
|
||||
let prev_array_8 = &mut *core::ptr::addr_of_mut!(PREV_ARRAY_8);
|
||||
let prev_array_8 = &mut *addr_of_mut!(PREV_ARRAY_8);
|
||||
*prev_array_8 = prev_array_8.rotate_elements_right::<1>();
|
||||
prev_array_8.shl_assign(SHR_8);
|
||||
prev_array_8.as_mut_array()[0] = pos as u32;
|
||||
@ -253,14 +257,15 @@ pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard(guard: *mut u32) {
|
||||
}
|
||||
#[cfg(not(feature = "pointer_maps"))]
|
||||
{
|
||||
let edges_map = &mut *addr_of_mut!(EDGES_MAP);
|
||||
#[cfg(feature = "sancov_pcguard_edges")]
|
||||
{
|
||||
*EDGES_MAP.get_unchecked_mut(pos) = 1;
|
||||
*(edges_map).get_unchecked_mut(pos) = 1;
|
||||
}
|
||||
#[cfg(feature = "sancov_pcguard_hitcounts")]
|
||||
{
|
||||
let val = (*EDGES_MAP.get_unchecked(pos)).wrapping_add(1);
|
||||
*EDGES_MAP.get_unchecked_mut(pos) = val;
|
||||
let val = (*edges_map.get_unchecked(pos)).wrapping_add(1);
|
||||
*edges_map.get_unchecked_mut(pos) = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -273,7 +278,7 @@ pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard(guard: *mut u32) {
|
||||
pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard_init(mut start: *mut u32, stop: *mut u32) {
|
||||
#[cfg(feature = "pointer_maps")]
|
||||
if EDGES_MAP_PTR.is_null() {
|
||||
EDGES_MAP_PTR = core::ptr::addr_of_mut!(EDGES_MAP) as *mut u8;
|
||||
EDGES_MAP_PTR = addr_of_mut!(EDGES_MAP) as *mut u8;
|
||||
}
|
||||
|
||||
if start == stop || *start != 0 {
|
||||
@ -290,8 +295,9 @@ pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard_init(mut start: *mut u32
|
||||
}
|
||||
#[cfg(not(feature = "pointer_maps"))]
|
||||
{
|
||||
let edges_map_len = (*addr_of!(EDGES_MAP)).len();
|
||||
MAX_EDGES_FOUND = MAX_EDGES_FOUND.wrapping_add(1);
|
||||
assert!((MAX_EDGES_FOUND <= EDGES_MAP.len()), "The number of edges reported by SanitizerCoverage exceed the size of the edges map ({}). Use the LIBAFL_EDGES_MAP_SIZE_IN_USE env to increase it at compile time.", EDGES_MAP.len());
|
||||
assert!((MAX_EDGES_FOUND <= edges_map_len), "The number of edges reported by SanitizerCoverage exceed the size of the edges map ({edges_map_len}). Use the LIBAFL_EDGES_MAP_SIZE_IN_USE env to increase it at compile time.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -314,7 +320,7 @@ unsafe extern "C" fn __sanitizer_cov_pcs_init(pcs_beg: *const usize, pcs_end: *c
|
||||
"Unaligned PC Table - start: {pcs_beg:x?} end: {pcs_end:x?}"
|
||||
);
|
||||
|
||||
let pc_tables = &mut *core::ptr::addr_of_mut!(PC_TABLES);
|
||||
let pc_tables = &mut *addr_of_mut!(PC_TABLES);
|
||||
pc_tables.push(slice::from_raw_parts(pcs_beg as *const PcTableEntry, len));
|
||||
}
|
||||
|
||||
@ -345,7 +351,7 @@ pub fn sanitizer_cov_pc_table<'a>() -> impl Iterator<Item = &'a [PcTableEntry]>
|
||||
// SAFETY: Once PCS_BEG and PCS_END have been initialized, will not be written to again. So
|
||||
// there's no TOCTOU issue.
|
||||
unsafe {
|
||||
let pc_tables = &*core::ptr::addr_of!(PC_TABLES);
|
||||
let pc_tables = &*addr_of!(PC_TABLES);
|
||||
pc_tables.iter().copied()
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user