Author and run LLVM libFuzzer for C/C++ - in-process coverage-guided fuzzing. Covers harness authoring (LLVMFuzzerTestOneInput entry point), build with -fsanitize=fuzzer,address,undefined, runtime flags (-max_total_time, -runs, -dict, -fork, -workers), corpus + crash-artefact handling, and CI integration. Use for libraries / parsers / decoders in C/C++ where in-process fuzzing of a function is the right scope. Compose with ASan + UBSan from sanitiser-integration-reference and corpus discipline from corpus-management-reference.
74
93%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
This skill wraps LLVM's libFuzzer (per llvm.org/docs/LibFuzzer.html) for C/C++ targets. Composes with:
sanitiser-integration-reference
for ASan + UBSan integrationcorpus-management-reference
for seed / evolved-corpus / crash artefact disciplineDefine the entry point LLVMFuzzerTestOneInput:
#include <cstddef>
#include <cstdint>
#include "your_library.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
your_parser(Data, Size);
return 0;
}Per LLVM docs, the function signature is fixed: takes a const byte buffer + size, returns int (must return 0 for normal execution; non-zero values are reserved).
The fuzzer calls this function repeatedly with mutated Data. The
target's job is to drive the library code under test and let
sanitisers + asserts catch bugs.
Optional one-time setup:
extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
your_library_init();
return 0;
}Standard build flag:
clang -g -O1 \
-fsanitize=fuzzer,address,undefined \
-fno-sanitize-recover=all \
-fno-omit-frame-pointer \
fuzz_target.cc your_library.cc -o fuzz_targetPer sanitiser-integration-reference:
ASan + UBSan is the default pair; add MSan in a separate binary if
needed.
| Tip | Why |
|---|---|
| Keep the target small | Faster iteration; clearer coverage |
| Avoid global state between runs | Cross-input contamination defeats coverage guidance |
| Use the full input | Don't if (Size < 100) return 0; unless the lib requires |
| Avoid expensive I/O / network in the target | Slows iterations |
Use FuzzedDataProvider for structured inputs | Splits Data into typed sub-values |
FuzzedDataProvider (from LLVM's compiler-rt/include/fuzzer/FuzzedDataProvider.h):
#include <fuzzer/FuzzedDataProvider.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
FuzzedDataProvider fdp(Data, Size);
int port = fdp.ConsumeIntegralInRange(1, 65535);
std::string host = fdp.ConsumeRandomLengthString(64);
std::vector<uint8_t> body = fdp.ConsumeRemainingBytes<uint8_t>();
your_request_handler(host, port, body);
return 0;
}mkdir corpus/ seeds/
# Populate seeds/ with hand-curated inputs
./fuzz_target -max_total_time=3600 corpus/ seeds/The first directory is writable (evolved corpus); subsequent are
read-only seeds (per
corpus-management-reference).
Most-used: -max_total_time=N, -runs=N (-1 = infinite), -dict=path,
-fork=N, -workers=N, -merge=1 (corpus minimisation),
-rss_limit_mb=N (default 2048), -timeout=N (per-input, default 1200).
Full table (per llvm.org/docs/LibFuzzer.html):
references/flags-and-ci.md.
./fuzz_target -fork=8 -max_total_time=3600 corpus/ seeds/-fork=N spawns N processes, each with its own corpus subset.
Combine corpora periodically with -merge=1.
./fuzz_target crash-<sha1>
# Sanitiser report prints to stderr; same as the original crashVerify: confirm the replay prints the same sanitiser bug class and top stack frame as the original finding before minimising. If it does not reproduce, the artefact is stale against the current build (target or library rebuilt) - rebuild the target and re-run before proceeding.
Minimise the crash input:
./fuzz_target -minimize_crash=1 -runs=10000 crash-<sha1>
# Writes minimized-from-crash-<sha1> with the smallest reproducerFor structured formats:
# fuzz.dict
"{"
"}"
"["
"]"
"true"
"false"
"null"
"\":\""Invoke: ./fuzz_target -dict=fuzz.dict corpus/.
libFuzzer crash artefacts are saved as:
crash-<sha1> - segfault / sanitiser-detected errorleak-<sha1> - memory leak detected by LSantimeout-<sha1> - exceeded -timeoutoom-<sha1> - RSS exceeded -rss_limit_mbEach file's contents are the input bytes that triggered the crash. Pair with the sanitiser report (stderr) for stack + allocation site.
For automated parsing (e.g., file as a bug), feed the
sanitiser-report output to bug-report-from-failure
(in the qa-defect-management plugin):
./fuzz_target crash-<sha1> 2> sanitiser-report.txt
python scripts/file-bug-from-asan.py sanitiser-report.txt crash-<sha1>Short smoke fuzz (5 min) on every PR: build with
-fsanitize=fuzzer,address,undefined, cache fuzz/corpus, run
./fuzz_target -max_total_time=300 fuzz/corpus fuzz/seeds, and upload
crash-* / leak-* / timeout-* / oom-* artifacts. Full workflow:
references/flags-and-ci.md.
For long-running campaigns, ossfuzz-integration
is the canonical infrastructure.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
LLVMFuzzerTestOneInput with global state mutation | Cross-input contamination breaks coverage signal | Reset state per call or use LLVMFuzzerInitialize |
| Fuzz target without ASan + UBSan | Catches only crashes; 80%+ of bugs missed | Always compose with sanitisers |
| No corpus minimisation ever | Corpus grows unbounded; cycle time degrades | Weekly -merge=1 |
| Crash committed without minimisation | Large bug-report attachments | Always -minimize_crash=1 |
| Single huge fuzz target | Slow iterations; coverage attribution opaque | Split into multiple targets per function |
Ignoring -rss_limit_mb OOMs | False crash class | Set limit explicit; or disable allocator-related target paths |
| No dictionary for structured formats | Fuzzer slowly rediscovers grammar | Always supply -dict= for JSON / XML / SQL / proto |
-Q (QEMU) mode or specialised
tools.-fsanitize=fuzzer.-coverage flag or
external llvm-profdata + llvm-cov for line-level coverage.FuzzedDataProvider.h -
github.com/llvm/llvm-project/blob/main/compiler-rt/include/fuzzer/FuzzedDataProvider.h.sanitiser-integration-reference,
corpus-management-reference.afl-plus-plus (out-of-process,
multi-language),
cargo-fuzz-rust (Rust wrapper
around libFuzzer),
atheris-python-fuzzing,
jazzer-jvm-fuzzing,
go-native-fuzzing,
ossfuzz-integration.fuzz-tool-selector.