Skip to content
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

Parsing tables state transition coverage #1362

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions fuzzers/fuzzbench_tables/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
libpng-*
fuzzer
33 changes: 33 additions & 0 deletions fuzzers/fuzzbench_tables/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[package]
name = "fuzzbench"
version = "0.10.1"
authors = ["Andrea Fioraldi <[email protected]>", "Dominik Maier <[email protected]>"]
edition = "2021"

[features]
default = ["std"]
std = []
no_link_main = ["libafl_targets/libfuzzer_no_link_main"]

[profile.release]
lto = true
codegen-units = 1
opt-level = 3
debug = true

[build-dependencies]
cc = { version = "1.0", features = ["parallel"] }
which = { version = "4.0.2" }

[dependencies]
libafl = { path = "../../libafl/" }
libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "sancov_cmplog", "libfuzzer"] }
# TODO Include it only when building cc
libafl_cc = { path = "../../libafl_cc/" }
clap = { version = "4.0", features = ["default"] }
nix = "0.26"
mimalloc = { version = "*", default-features = false }

[lib]
name = "fuzzbench"
crate-type = ["staticlib"]
106 changes: 106 additions & 0 deletions fuzzers/fuzzbench_tables/Makefile.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
[env]
PROJECT_DIR = { script = ["pwd"] }
CARGO_TARGET_DIR = { value = "${PROJECT_DIR}/target", condition = { env_not_set = ["CARGO_TARGET_DIR"] } }
FUZZER_NAME="fuzzer"

[tasks.unsupported]
script_runner="@shell"
script='''
echo "Cargo-make not integrated yet on this"
'''

# Compilers
[tasks.cxx]
linux_alias = "cxx_unix"
mac_alias = "cxx_unix"
windows_alias = "unsupported"

[tasks.cxx_unix]
command = "cargo"
args = ["build" , "--release"]

[tasks.cc]
linux_alias = "cc_unix"
mac_alias = "cc_unix"
windows_alias = "unsupported"

[tasks.cc_unix]
command = "cargo"
args = ["build" , "--release"]

# fuzz.o File
[tasks.fuzz_o]
linux_alias = "fuzz_o_unix"
mac_alias = "fuzz_o_unix"
windows_alias = "unsupported"

[tasks.fuzz_o_unix]
command = "${CARGO_TARGET_DIR}/release/libafl_cc"
args = ["--libafl-no-link", "-O3", "-c", "fuzz.c", "-o", "fuzz.o"]
dependencies = ["cc", "cxx"]

# Fuzzer
[tasks.fuzzer]
linux_alias = "fuzzer_unix"
mac_alias = "fuzzer_unix"
windows_alias = "unsupported"

[tasks.fuzzer_unix]
command = "${CARGO_TARGET_DIR}/release/libafl_cxx"
args = ["--libafl", "fuzz.o", "-o", "${FUZZER_NAME}", "-lm", "-lz"]
dependencies = ["cc", "cxx", "fuzz_o"]

# Run
[tasks.run]
linux_alias = "run_unix"
mac_alias = "run_unix"
windows_alias = "unsupported"

[tasks.run_unix]
script_runner="@shell"
script='''
rm -rf libafl_unix_shmem_server || true
mkdir in || true
echo a > in/a
./${FUZZER_NAME} -o out -i in
'''
dependencies = ["fuzzer"]


# Test
[tasks.test]
linux_alias = "test_unix"
mac_alias = "test_unix"
windows_alias = "unsupported"

[tasks.test_unix]
script_runner="@shell"
script='''
rm -rf libafl_unix_shmem_server || true
mkdir in || true
echo a > in/a
# Allow sigterm as exit code
timeout 11s ./${FUZZER_NAME} -o out -i in >fuzz_stdout.log || true
if [ -z "$(grep "objectives: 10" fuzz_stdout.log)" ]; then
echo "Fuzzer does not generate any testcases or any crashes"
exit 1
else
echo "Fuzzer is working"
fi
rm -rf out || true
rm -rf in || true
'''
dependencies = ["fuzzer"]

# Clean
[tasks.clean]
linux_alias = "clean_unix"
mac_alias = "clean_unix"
windows_alias = "unsupported"

[tasks.clean_unix]
script_runner="@shell"
script='''
rm ./${FUZZER_NAME} || true
rm fuzz.o || true
'''
17 changes: 17 additions & 0 deletions fuzzers/fuzzbench_tables/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Fuzzbench Harness
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to have some info in here what exactly this does


This folder contains an example fuzzer tailored for fuzzbench.
It uses the best possible setting, with the exception of a SimpleRestartingEventManager instead of an LlmpEventManager - since fuzzbench is single threaded.
Real fuzz campaigns should consider using multithreaded LlmpEventManager, see the other examples.

## Build

To build this example, run `cargo build --release`.
This will build the fuzzer compilers (`libafl_cc` and `libafl_cpp`) with `src/lib.rs` as fuzzer.
The fuzzer uses the libfuzzer compatibility layer and the SanitizerCoverage runtime functions for coverage feedback.

These can then be used to build libfuzzer harnesses in the software project of your choice.
Finally, just run the resulting binary with `out_dir`, `in_dir`.

In any real-world scenario, you should use `taskset` to pin each client to an empty CPU core, the lib does not pick an empty core automatically (yet).

15 changes: 15 additions & 0 deletions fuzzers/fuzzbench_tables/fuzz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <stdint.h>
#include <stdlib.h>

int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
if (Size >= 8 && *(uint32_t *)Data == 0xaabbccdd) { abort(); }
return 0;
}

/*
int main() {

char buf [10] = {0};
LLVMFuzzerTestOneInput(buf, 10);

}*/
46 changes: 46 additions & 0 deletions fuzzers/fuzzbench_tables/src/bin/libafl_cc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use std::env;

use libafl_cc::{ClangWrapper, CompilerWrapper, LLVMPasses, ToolWrapper};

pub fn main() {
let mut args: Vec<String> = env::args().collect();
if args.len() > 1 {
let mut dir = env::current_exe().unwrap();
let wrapper_name = dir.file_name().unwrap().to_str().unwrap();

let is_cpp = match wrapper_name[wrapper_name.len()-2..].to_lowercase().as_str() {
"cc" => false,
"++" | "pp" | "xx" => true,
_ => panic!("Could not figure out if c or c++ wrapper was called. Expected {dir:?} to end with c or cxx"),
};

dir.pop();

// Must be always present, even without --libafl
args.push("-fsanitize-coverage=trace-pc-guard,trace-cmp".into());

let mut cc = ClangWrapper::new();

#[cfg(any(target_os = "linux", target_vendor = "apple"))]
cc.add_pass(LLVMPasses::AutoTokens);

if let Some(code) = cc
.cpp(is_cpp)
// silence the compiler wrapper output, needed for some configure scripts.
.silence(true)
// add arguments only if --libafl or --libafl-no-link are present
.need_libafl_arg(true)
.parse_args(&args)
.expect("Failed to parse the command line")
.link_staticlib(&dir, "fuzzbench")
.add_pass(LLVMPasses::CmpLogRtn)
.add_pass(LLVMPasses::Tables)
.run()
.expect("Failed to run the wrapped compiler")
{
std::process::exit(code);
}
} else {
panic!("LibAFL CC: No Arguments given");
}
}
5 changes: 5 additions & 0 deletions fuzzers/fuzzbench_tables/src/bin/libafl_cxx.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod libafl_cc;

fn main() {
libafl_cc::main();
}
Loading