
* introduce disabled field to Testcase * separate executor's processing of execution (adding to corpus/solution/discarding) and execution of input * introduce add_disabled_input function * enable splicing mutators to fetch disabled inputs * reset modified example * clean up * update docs * update docs for count_with_disabled * fix random_corpus_id for splicing mutator not considering disabled entries * fmt * update docs * clippy * fix corpus_btreemap not working * fix clippy warnings * fix python bindings * typo in count_with_disabled implementations * fix certain splicing mutators not considering disabled inputs * rename count_with_disabled to count_all * introduce count_disabled function * update docs for count_all, count_disabled and count * * introduce get_from_all and nth_from_all for corpus implementations so get() and nth() do not silently fetch disabled entries. * remove boolean flag from random_corpus_id which allowed inclusion of disabled ids and make it into a new function random_corpus_id_with_disabled * update docs * remove boolean is_disabled flag from corpus::insert and make it into a separate function insert_disabled * rename do_insert to _insert * make get_from_all inline for cached and inmemory * add missing functions implementation for PythonCorpus prevent writing feedback when adding disabled testcases * fix nth_from_all overfetching enabled corpus entries * fix clippy & rename execute_with_res to execute_no_process * refactor _insert for corpus_btreemap * make LibfuzzerCorpus and ArtifactCorpus to accomodate disabled entries * fix typo * fix missing docs for map field * fix clippy * test * (hopefully) fix CachedOnDiskCorpus using incorrect corpus when caching testcase * fix typo in inmemory_ondisk leading to fetching disabled entry from enabled corpus --------- Co-authored-by: aarnav <aarnav@srlabs.de> Co-authored-by: Dominik Maier <domenukk@gmail.com>
libafl_libfuzzer
libafl_libfuzzer
is a shim for libFuzzer which may be used in place of libFuzzer in most contexts.
It can be used both as a direct shim for existing libFuzzer-compatible targets which are simply linked with libFuzzer
(e.g., clang -fsanitize=fuzzer
) and as a Rust crate for libfuzzer-sys
-based harnesses.
Background
libafl_libfuzzer
was first developed as a shim in light of the de-facto deprecation of libFuzzer.
Given the widespread use of libFuzzer and that LibAFL already supported most of the instrumentation used by libFuzzer,
we sought to develop a replacement which could directly replace it without much additional effort from the end user.
To do so, libafl_libfuzzer
provides the same interface and uses the same instrumentation as libFuzzer so that
libFuzzer users can change over to a more modern LibAFL-based runtime without needing extensive changes to their
fuzzing environment or updating their harnesses.
Usage
libafl_libfuzzer
currently has known support for Rust, C, and C++ targets on Linux and macOS.
Windows is not currently supported, as we do not currently test or develop for Windows machines, but we will happily
hear what issues you face and patch them as possible.
For both cases, you should install a recent nightly version of Rust via rustup
and add the llvm-tools
component
with rustup component add llvm-tools
.
Usage with Rust harnesses
To use libafl_libfuzzer
on Rust harnesses which use libfuzzer-sys
, all you need to do is change the following line
in your Cargo.toml:
libfuzzer-sys = { version = "...", features = ["your", "features", "here"] }
to
libfuzzer-sys = { version = "0.11.0", features = ["your", "features", "here"], package = "libafl_libfuzzer" }
If, in the case that you want to work with experimental changes, the libfuzzer-best
branch contains the current
experimental best version of libafl_libfuzzer
.
To use the experimental version, use:
libfuzzer-sys = { git = "https://github.com/AFLplusplus/LibAFL.git", branch = "libfuzzer-best", features = ["your", "features", "here"], package = "libafl_libfuzzer" }
As this branch generally offers the highest performance version of libafl_libfuzzer
, we recommend the latter.
Remember to cargo update
often if using the experimental changes, and please submit an issue
if you encounter problems while using libfuzzer-best
!
macOS
On macOS, you will need to add weak linking for some functions in a build.rs
file:
fn main() {
for func in [
"_libafl_main",
"_LLVMFuzzerCustomMutator",
"_LLVMFuzzerCustomCrossOver",
] {
println!("cargo:rustc-link-arg=-Wl,-U,{func}");
}
}
Caveats
Like harnesses built with libfuzzer-sys
, Rust targets which build other libraries (e.g. C/C++ FFI) may not
automatically apply instrumentation.
In addition to installing clang, you may also wish to set the following environmental variables:
CC=clang
CXX=clang++
CFLAGS='-fsanitize=fuzzer-no-link'
CXXFLAGS='-fsanitize=fuzzer-no-link'
Usage as a standalone library (for C/C++/etc.)
The runtime for libafl_libfuzzer
may be used standalone as a direct replacement for libFuzzer with other targets as
well.
To do so, ensure a recent nightly version of Rust is installed, then enter the
libafl_libfuzzer_runtime
folder and build the runtime with the following command:
./build.sh
The static library will be available at libFuzzer.a
in the libafl_libfuzzer_runtime
directory.
If you encounter build failures without clear error outputs that help you resolve the issue, please submit an issue.
This library may now be used in place of libFuzzer.
To do so, change your CFLAGS/CXXFLAGS from -fsanitize=fuzzer
to:
-fsanitize=fuzzer-no-link -L/path/to/libafl_libfuzzer_runtime -lFuzzer
Alternatively, you may directly overwrite the system libFuzzer library and use -fsanitize=fuzzer
as normal.
This changes per system, but on my machine is located at /usr/lib64/clang/16/lib/linux/libclang_rt.fuzzer-x86_64.a
.
Caveats
This standalone library is not compatible with Rust targets; you must instead use the crate-based dependency.
This is due to potential symbol conflict between your harness and the fuzzer runtime, which is resolved by additional
build steps provided in the libafl_libfuzzer
crate itself.
Flags
You can pass additional flags to the libFuzzer runtime in cargo-fuzz
like so:
cargo fuzz run fuzz_target -- -extra_flag=1
When the runtime is used standalone, flags may be passed just like normal libFuzzer.
You will commonly need this for flags such as -ignore_crashes=1
and -timeout=5
. In addition
to partial support of libfuzzer flags, libafl_libfuzzer
offers:
-dedup=n
, withn
= 1 enabling deduplication of crashes by stacktrace.-grimoire=n
, withn
set to 0 or 1 disabling or enabling grimoire mutations, respectively.- if not specified explicitly,
libafl_libfuzzer
will select based on whether existing inputs are UTF-8 - you should disable grimoire if your target is not string-like
- if not specified explicitly,
-report=n
, withn
= 1 causinglibafl_libfuzzer
to emit a report on the corpus content.-skip_tracing=n
, withn
= 1 causinglibafl_libfuzzer
to disable cmplog tracing.- you should do this if your target performs many comparisons on memory sequences which are not contained in the input
-tui=n
, withn
= 1 enabling a graphical terminal interface.- experimental; some users report inconsistent behaviour with tui enabled
Supported flags from libfuzzer
-merge
-minimize_crash
-artifact_prefix
-timeout
- unlike libfuzzer,
libafl_libfuzzer
supports partial second timeouts (e.g.-timeout=.5
)
- unlike libfuzzer,
-dict
-fork
and-jobs
- in
libafl_libfuzzer
, these are synonymous
- in
-ignore_crashes
,-ignore_ooms
, and-ignore_timeouts
- note that setting
-tui=1
enables these flags by default, so you'll need to explicitly mention-ignore_...=0
to disable them
- note that setting
-rss_limit_mb
and-malloc_limit_mb
-ignore_remaining_args
-shrink
-runs
-close_fd_mask