libfuzzer
In-process, coverage-guided fuzzer for C/C++ projects using the LLVM toolchain.
Install
mkdir -p .claude/skills/libfuzzer && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/4192" && unzip -o skill.zip -d .claude/skills/libfuzzer && rm skill.zipInstalls to .claude/skills/libfuzzer
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Coverage-guided fuzzer built into LLVM for C/C++ projects. Use for fuzzing C/C++ code that can be compiled with Clang.Key capabilities
- →Perform coverage-guided fuzzing on C/C++ target functions
- →Inject instrumentation via Clang for defect detection
- →Generate test harnesses compatible with AFL++
- →Analyze input data streams for crash-triggering patterns
- →Integrate into standard LLVM compilation pipelines
How it works
Links a fuzzer target directly into the binary, using coverage feedback to intelligently mutate inputs until a crash or bug is found.
Inputs & outputs
When to use libfuzzer
- →Fuzzing C++ target functions
- →Setting up coverage-guided test harnesses
- →Integrating fuzzing into build pipelines
About this skill
libFuzzer
libFuzzer is an in-process, coverage-guided fuzzer that is part of the LLVM project. It's the recommended starting point for fuzzing C/C++ projects due to its simplicity and integration with the LLVM toolchain. While libFuzzer has been in maintenance-only mode since late 2022, it is easier to install and use than its alternatives, has wide support, and will be maintained for the foreseeable future.
When to Use
| Fuzzer | Best For | Complexity |
|---|---|---|
| libFuzzer | Quick setup, single-project fuzzing | Low |
| AFL++ | Multi-core fuzzing, diverse mutations | Medium |
| LibAFL | Custom fuzzers, research projects | High |
| Honggfuzz | Hardware-based coverage | Medium |
Choose libFuzzer when:
- You need a simple, quick setup for C/C++ code
- Project uses Clang for compilation
- Single-core fuzzing is sufficient initially
- Transitioning to AFL++ later is an option (harnesses are compatible)
Note: Fuzzing harnesses written for libFuzzer are compatible with AFL++, making it easy to transition if you need more advanced features like better multi-core support.
Quick Start
#include <stdint.h>
#include <stddef.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// Validate input if needed
if (size < 1) return 0;
// Call your target function with fuzzer-provided data
my_target_function(data, size);
return 0;
}
Compile and run:
clang++ -fsanitize=fuzzer,address -g -O2 harness.cc target.cc -o fuzz
mkdir corpus/
./fuzz corpus/
Installation
Prerequisites
- LLVM/Clang compiler (includes libFuzzer)
- LLVM tools for coverage analysis (optional)
Linux (Ubuntu/Debian)
apt install clang llvm
For the latest LLVM version:
# Add LLVM repository from apt.llvm.org
# Then install specific version, e.g.:
apt install clang-18 llvm-18
macOS
# Using Homebrew
brew install llvm
# Or using Nix
nix-env -i clang
Windows
Install Clang through Visual Studio. Refer to Microsoft's documentation for setup instructions.
Recommendation: If possible, fuzz on a local x86_64 VM or rent one on DigitalOcean, AWS, or Hetzner. Linux provides the best support for libFuzzer.
Verification
clang++ --version
# Should show LLVM version information
Writing a Harness
Harness Structure
The harness is the entry point for the fuzzer. libFuzzer calls the LLVMFuzzerTestOneInput function repeatedly with different inputs.
#include <stdint.h>
#include <stddef.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// 1. Optional: Validate input size
if (size < MIN_REQUIRED_SIZE) {
return 0; // Reject inputs that are too small
}
// 2. Optional: Convert raw bytes to structured data
// Example: Parse two integers from byte array
if (size >= 2 * sizeof(uint32_t)) {
uint32_t a = *(uint32_t*)(data);
uint32_t b = *(uint32_t*)(data + sizeof(uint32_t));
my_function(a, b);
}
// 3. Call target function
target_function(data, size);
// 4. Always return 0 (non-zero reserved for future use)
return 0;
}
Harness Rules
| Do | Don't |
|---|---|
| Handle all input types (empty, huge, malformed) | Call exit() - stops fuzzing process |
| Join all threads before returning | Leave threads running |
| Keep harness fast and simple | Add excessive logging or complexity |
| Maintain determinism | Use random number generators or read /dev/random |
| Reset global state between runs | Rely on state from previous executions |
| Use narrow, focused targets | Mix unrelated data formats (PNG + TCP) in one harness |
Rationale:
- Speed matters: Aim for 100s-1000s executions per second per core
- Reproducibility: Crashes must be reproducible after fuzzing completes
- Isolation: Each execution should be independent
Using FuzzedDataProvider for Complex Inputs
For complex inputs (strings, multiple parameters), use the FuzzedDataProvider helper:
#include <stdint.h>
#include <stddef.h>
#include "FuzzedDataProvider.h" // From LLVM project
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
FuzzedDataProvider fuzzed_data(data, size);
// Extract structured data
size_t allocation_size = fuzzed_data.ConsumeIntegral<size_t>();
std::vector<char> str1 = fuzzed_data.ConsumeBytesWithTerminator<char>(32, 0xFF);
std::vector<char> str2 = fuzzed_data.ConsumeBytesWithTerminator<char>(32, 0xFF);
// Call target with extracted data
char* result = concat(&str1[0], str1.size(), &str2[0], str2.size(), allocation_size);
if (result != NULL) {
free(result);
}
return 0;
}
Download FuzzedDataProvider.h from the LLVM repository.
Interleaved Fuzzing
Use a single harness to test multiple related functions:
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (size < 1 + 2 * sizeof(int32_t)) {
return 0;
}
uint8_t mode = data[0];
int32_t numbers[2];
memcpy(numbers, data + 1, 2 * sizeof(int32_t));
// Select function based on first byte
switch (mode % 4) {
case 0: add(numbers[0], numbers[1]); break;
case 1: subtract(numbers[0], numbers[1]); break;
case 2: multiply(numbers[0], numbers[1]); break;
case 3: divide(numbers[0], numbers[1]); break;
}
return 0;
}
See Also: For detailed harness writing techniques, patterns for handling complex inputs, structure-aware fuzzing, and protobuf-based fuzzing, see the fuzz-harness-writing technique skill.
Compilation
Basic Compilation
The key flag is -fsanitize=fuzzer, which:
- Links the libFuzzer runtime (provides
mainfunction) - Enables SanitizerCoverage instrumentation for coverage tracking
- Disables built-in functions like
memcmp
clang++ -fsanitize=fuzzer -g -O2 harness.cc target.cc -o fuzz
Flags explained:
-fsanitize=fuzzer: Enable libFuzzer-g: Add debug symbols (helpful for crash analysis)-O2: Production-level optimizations (recommended for fuzzing)-DNO_MAIN: Define macro if your code has amainfunction
With Sanitizers
AddressSanitizer (recommended):
clang++ -fsanitize=fuzzer,address -g -O2 -U_FORTIFY_SOURCE harness.cc target.cc -o fuzz
Multiple sanitizers:
clang++ -fsanitize=fuzzer,address,undefined -g -O2 harness.cc target.cc -o fuzz
See Also: For detailed sanitizer configuration, common issues, ASAN_OPTIONS flags, and advanced sanitizer usage, see the address-sanitizer and undefined-behavior-sanitizer technique skills.
Build Flags
| Flag | Purpose |
|---|---|
-fsanitize=fuzzer | Enable libFuzzer runtime and instrumentation |
-fsanitize=address | Enable AddressSanitizer (memory error detection) |
-fsanitize=undefined | Enable UndefinedBehaviorSanitizer |
-fsanitize=fuzzer-no-link | Instrument without linking fuzzer (for libraries) |
-g | Include debug symbols |
-O2 | Production optimization level |
-U_FORTIFY_SOURCE | Disable fortification (can interfere with ASan) |
Building Static Libraries
For projects that produce static libraries:
- Build the library with fuzzing instrumentation:
export CC=clang CFLAGS="-fsanitize=fuzzer-no-link -fsanitize=address"
export CXX=clang++ CXXFLAGS="$CFLAGS"
./configure --enable-shared=no
make
- Link the static library with your harness:
clang++ -fsanitize=fuzzer -fsanitize=address harness.cc libmylib.a -o fuzz
CMake Integration
project(FuzzTarget)
cmake_minimum_required(VERSION 3.0)
add_executable(fuzz main.cc harness.cc)
target_compile_definitions(fuzz PRIVATE NO_MAIN=1)
target_compile_options(fuzz PRIVATE -g -O2 -fsanitize=fuzzer -fsanitize=address)
target_link_libraries(fuzz -fsanitize=fuzzer -fsanitize=address)
Build with:
cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ .
cmake --build .
Corpus Management
Creating Initial Corpus
Create a directory for the corpus (can start empty):
mkdir corpus/
Optional but recommended: Provide seed inputs (valid example files):
# For a PNG parser:
cp examples/*.png corpus/
# For a protocol parser:
cp test_packets/*.bin corpus/
Benefits of seed inputs:
- Fuzzer doesn't start from scratch
- Reaches valid code paths faster
- Significantly improves effectiveness
Corpus Structure
The corpus directory contains:
- Input files that trigger unique code paths
- Minimized versions (libFuzzer automatically minimizes)
- Named by content hash (e.g.,
a9993e364706816aba3e25717850c26c9cd0d89d)
Corpus Minimization
libFuzzer automatically minimizes corpus entries during fuzzing. To explicitly minimize:
mkdir minimized_corpus/
./fuzz -merge=1 minimized_corpus/ corpus/
This creates a deduplicated, minimized corpus in minimized_corpus/.
See Also: For corpus creation strategies, seed selection, format-specific corpus building, and corpus maintenance, see the fuzzing-corpus technique skill.
Running Campaigns
Basic Run
./fuzz corpus/
This runs until a crash is found or you stop it (Ctrl+C).
Recommended: Continue After Crashes
./fuzz -fork=1 -ignore_crashes=1 corpus/
The -fork and -ignore_crashes flags (experimental but widely used) allow fuzzing to continue after finding crashes.
Common Options
Control input size:
./fuzz -max_len=4000 corpus/
Rule of thumb: 2x the size of minimal realistic input.
Set timeout:
./fuzz -timeout=2 corpus/
Abort test cases that run longer than 2 s
Content truncated.
When not to use it
- →Fuzzing high-level interpreted languages like Python or JS
- →Scenarios requiring hardware-based coverage analysis
Prerequisites
Limitations
- →Limited to single-core fuzzing initially
- →Requires source modification for harness creation
- →Maintenance-only status for the core tool
How it compares
It is an in-process fuzzer, which is faster and easier to deploy than standalone external mutation engines.
Compared to similar skills
libfuzzer side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| libfuzzer (this skill) | 1 | 2mo | Review | Intermediate |
| address-sanitizer | 1 | 2mo | Review | Intermediate |
| aflpp | 1 | 2mo | Review | Advanced |
| libafl | 1 | 2mo | Review | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by trailofbits
View all by trailofbits →You might also like
address-sanitizer
trailofbits
AddressSanitizer detects memory errors during fuzzing. Use when fuzzing C/C++ code to find buffer overflows and use-after-free bugs.
aflpp
trailofbits
AFL++ is a fork of AFL with better fuzzing performance and advanced features. Use for multi-core fuzzing of C/C++ projects.
libafl
trailofbits
LibAFL is a modular fuzzing library for building custom fuzzers. Use for advanced fuzzing needs, custom mutators, or non-standard fuzzing targets.
code-coverage-with-gcov
gadievron
Add gcov code coverage instrumentation to C/C++ projects
unity-mcp-orchestrator
CoplayDev
Orchestrate Unity Editor via MCP (Model Context Protocol) tools and resources. Use when working with Unity projects through MCP for Unity - creating/modifying GameObjects, editing scripts, managing scenes, running tests, or any Unity Editor automation. Provides best practices, tool schemas, and workflow patterns for effective Unity-MCP integration.
game-engine-resources
gmh5225
Guide for game engine development resources including engine source code, plugins, and development guides. Use this skill when researching game engines (Unreal, Unity, Godot, custom engines), engine architecture, or game development frameworks.