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
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
Compile and run:
Installation
Prerequisites
- LLVM/Clang compiler (includes libFuzzer)
- LLVM tools for coverage analysis (optional)
Linux (Ubuntu/Debian)
For the latest LLVM version:
macOS
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
Writing a Harness
Harness Structure
The harness is the entry point for the fuzzer. libFuzzer calls the LLVMFuzzerTestOneInput function repeatedly with different inputs.
Harness Rules
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:
Download FuzzedDataProvider.h from the LLVM repository.
Interleaved Fuzzing
Use a single harness to test multiple related functions:
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
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):
Multiple sanitizers:
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
Building Static Libraries
For projects that produce static libraries:
- Build the library with fuzzing instrumentation:
- Link the static library with your harness:
CMake Integration
Build with:
Corpus Management
Creating Initial Corpus
Create a directory for the corpus (can start empty):
Optional but recommended: Provide seed inputs (valid example files):
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:
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
This runs until a crash is found or you stop it (Ctrl+C).
Recommended: Continue After Crashes
The -fork and -ignore_crashes flags (experimental but widely used) allow fuzzing to continue after finding crashes.
Common Options
Control input size:
Rule of thumb: 2x the size of minimal realistic input.
Set timeout:
Abort test cases that run longer than 2 seconds.
Use a dictionary:
Close stdout/stderr (speed up fuzzing):
See all options:
Multi-Core Fuzzing
Option 1: Jobs and workers (recommended):
-jobs=4: Run 4 sequential campaigns-workers=4: Process jobs in parallel with 4 processes- Test cases are shared between jobs
Option 2: Fork mode:
Note: For serious multi-core fuzzing, consider switching to AFL++, Honggfuzz, or LibAFL.
Re-executing Test Cases
Re-run a single crash:
Test all inputs in a directory without fuzzing:
Interpreting Output
When fuzzing runs, you'll see statistics like:
On crash:
The crash is saved to ./crash-<hash> with the input shown in hex, UTF-8, and Base64.
Reproducibility: Use -seed=<value> to reproduce a fuzzing campaign (single-core only).
Fuzzing Dictionary
Dictionaries help the fuzzer discover interesting inputs faster by providing hints about the input format.
Dictionary Format
Create a text file with quoted strings (one per line):
Using a Dictionary
Generating a Dictionary
From header files:
From man pages:
From binary strings:
Using LLMs: Ask ChatGPT or similar to generate a dictionary for your format (e.g., "Generate a libFuzzer dictionary for a JSON parser").
See Also: For advanced dictionary generation, format-specific dictionaries, and dictionary optimization strategies, see the fuzzing-dictionaries technique skill.
Coverage Analysis
While libFuzzer shows basic coverage stats (cov: N), detailed coverage analysis requires additional tools.
Source-Based Coverage
1. Recompile with coverage instrumentation:
2. Run fuzzer to collect coverage:
3. Merge coverage data:
4. Generate coverage report:
5. Generate HTML report:
Improving Coverage
Tips:
- Provide better seed inputs in corpus
- Use dictionaries for format-aware fuzzing
- Check if harness properly exercises target
- Consider structure-aware fuzzing for complex formats
- Run longer campaigns (days/weeks)
See Also: For detailed coverage analysis techniques, identifying coverage gaps, systematic coverage improvement, and comparing coverage across fuzzers, see the coverage-analysis technique skill.
Sanitizer Integration
AddressSanitizer (ASan)
ASan detects memory errors like buffer overflows and use-after-free bugs. Highly recommended for fuzzing.
Enable ASan:
Example ASan output:
Configure ASan with environment variables:
Important flags:
verbosity=1: Show ASan is activedetect_leaks=0: Disable leak detection (leaks reported at end)abort_on_error=1: Callabort()instead of_exit()on errors
Drawbacks:
- 2-4x slowdown
- Requires ~20TB virtual memory (disable memory limits:
-rss_limit_mb=0) - Best supported on Linux
See Also: For comprehensive ASan configuration, common pitfalls, symbolization, and combining with other sanitizers, see the address-sanitizer technique skill.
UndefinedBehaviorSanitizer (UBSan)
UBSan detects undefined behavior like integer overflow, null pointer dereference, etc.
Enable UBSan:
Combine with ASan:
MemorySanitizer (MSan)
MSan detects uninitialized memory reads. More complex to use (requires rebuilding all dependencies).
Common Sanitizer Issues
Real-World Examples
Example 1: Fuzzing libpng
libpng is a widely-used library for reading/writing PNG images. Bugs can lead to security issues.
1. Get source code:
2. Install dependencies:
3. Compile with fuzzing instrumentation:
4. Get a harness (or write your own):
5. Prepare corpus and dictionary:
6. Link and compile fuzzer:
7. Run fuzzing campaign:
Example 2: Simple Division Bug
Harness that finds a division-by-zero bug:
Compile and fuzz:
The fuzzer will quickly find inputs causing a crash.
Advanced Usage
Tips and Tricks
Structure-Aware Fuzzing
For highly structured inputs (e.g., complex protocols, file formats), use libprotobuf-mutator:
- Define input structure using Protocol Buffers
- libFuzzer mutates protobuf messages (structure-preserving mutations)
- Harness converts protobuf to native format
See structure-aware fuzzing documentation for details.
Custom Mutators
libFuzzer allows custom mutators for specialized fuzzing:
Performance Tuning
Troubleshooting
Related Skills
Technique Skills
Related Fuzzers
Resources
Official Documentation
- LLVM libFuzzer Documentation - Official reference
- libFuzzer Tutorial by Google - Step-by-step guide
- SanitizerCoverage - Coverage instrumentation details
Advanced Topics
- Structure-Aware Fuzzing with libprotobuf-mutator
- Split Inputs in libFuzzer
- FuzzedDataProvider Header
Example Projects
- OSS-Fuzz - Continuous fuzzing for open-source projects (many libFuzzer examples)
- AFL++ Dictionary Collection - Reusable dictionaries

