/fuzzing
Fuzzing skill for automated input-driven bug finding in C/C++. Use when setting up libFuzzer or AFL++ fuzz targets, defining fuzz entry points around parsing or I/O boundaries, integrating fuzzing into CI, managing corpora, or combining fuzzing with sanitizers. Activates on
$ npx -y skills add mohitmishra786/low-level-dev-skills --skill fuzzing --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/fuzzing
Context preview
The summary Claude sees to decide when to auto-load this skill.
Fuzzing skill for automated input-driven bug finding in C/C++. Use when setting up libFuzzer or AFL++ fuzz targets, defining fuzz entry points around parsing or I/O boundaries, integrating fuzzing into CI, managing corpora, or combining fuzzing with sanitizers. Activates on
SKILL.md
fuzzing.SKILL.mdname: fuzzing
description: Fuzzing skill for automated input-driven bug finding in C/C++. Use when setting up libFuzzer or AFL++ fuzz targets, defining fuzz entry points around parsing or I/O boundaries, integrating fuzzing into CI, managing corpora, or combining fuzzing with sanitizers. Activates on queries about libFuzzer, AFL, afl-fuzz, fuzz targets, corpus management, coverage-guided fuzzing, or OSS-Fuzz integration.
Fuzzing
Purpose
Guide agents through setting up and running coverage-guided fuzz testing: libFuzzer (in-process) and AFL++ (fork-based), with sanitizer integration and CI pipeline setup.
Triggers
- "How do I fuzz-test my parser/deserializer?"
- "What is a fuzz target / how do I write one?"
- "How do I set up libFuzzer?"
- "How do I use AFL++ on my program?"
- "How do I run fuzzing in CI?"
- "Fuzzer found a crash — how do I reproduce it?"
Workflow
1. Write a fuzz target (libFuzzer)
A fuzz target is a function that accepts arbitrary bytes and exercises the code under test.
// fuzz_parser.c
#include <stdint.h>
#include <stddef.h>
#include "myparser.h"
// Entry point called by libFuzzer with random data
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// Must not abort/exit on invalid input (that's expected)
// Must not read outside [data, data+size)
MyParser *p = parser_create();
if (p) {
parser_feed(p, (const char *)data, size);
parser_destroy(p);
}
return 0; // Always return 0 (non-zero means discard input)
}Key rules:
- Never call `abort()`, `exit()`, or use global state that persists across calls
- Handle all inputs gracefully (crash = bug found)
- Keep the target fast: the fuzzer calls it millions of times
2. Build with libFuzzer
# Clang (libFuzzer is built into Clang)
clang -fsanitize=fuzzer,address -g -O1 \
fuzz_parser.c myparser.c -o fuzz_parser
# With UBSan too
clang -fsanitize=fuzzer,address,undefined -g -O1 \
fuzz_parser.c myparser.c -o fuzz_parser`-fsanitize=fuzzer` links libFuzzer and provides `main()`. Do not provide your own `main()` in the fuzz target.
3. Run libFuzzer
# Create corpus directory
mkdir -p corpus
# Seed with known-good inputs (greatly accelerates coverage)
cp tests/inputs/* corpus/
# Run the fuzzer
./fuzz_parser corpus/ -max_len=65536 -timeout=10
# Run for a time limit
./fuzz_parser corpus/ -max_total_time=3600
# Run with specific number of jobs (parallel)
./fuzz_parser corpus/ -jobs=4 -workers=4
# Minimise a corpus (remove redundant inputs)
./fuzz_parser -merge=1 corpus_min/ corpus/
Common flags:
| Flag | Default | Effect | |------|---------|--------| | `-max_len=N` | 4096 | Max input size in bytes | | `-timeout=N` | 1200 | Kill if single run takes > N seconds | | `-max_total_time=N` | 0 (forever) | Total fuzzing time | | `-runs=N` | -1 (infinite) | Total number of runs | | `-dict=file` | none | Dictionary of interesting tokens | | `-jobs=N` | 1 | Parallel jobs (each writes its own log) | | `-merge=1` | off | Merge mode: minimise corpus |
4. Reproduce a crash
libFuzzer writes crash inputs to files named `crash-<hash>`, `oom-<hash>`, `timeout-<hash>`.
# Reproduce
./fuzz_parser crash-abc123
# Debug with GDB
gdb ./fuzz_parser
(gdb) run crash-abc123
5. AFL++ setup
AFL++ is a fork-based fuzzer that works on arbitrary programs (not just those with a fuzz entry point).
# Install
apt install afl++ # or build from source
# Instrument the target
CC=afl-clang-fast CXX=afl-clang-fast++ \
cmake -S . -B build-afl -DCMAKE_BUILD_TYPE=Debug
cmake --build build-afl
# Or compile directly
afl-clang-fast -g -O1 -o prog_afl main.c myparser.c
# Create input corpus
mkdir -p afl-input afl-output
echo "hello" > afl-input/seed1
# Run
afl-fuzz -i afl-input -o afl-output -- ./prog_afl @@
# @@ is replaced with the input file path
# For stdin-based programs: remove @@
afl-fuzz -i afl-input -o afl-output -- ./prog_afl
6. AFL++ with persistent mode (faster)
Persistent mode avoids `fork()` per input — much faster for library fuzzing:
// In your harness:
#include "myparser.h"
int main(int argc, char **argv) {
while (__AFL_LOOP(1000)) {
// Read input
unsigned char *buf = NULL;
ssize_t len = read(0, &buf, MAX_SIZE); // or use afl_custom_mutator
parser_feed((char*)buf, len);
free(buf);
}
return 0;
}7. Corpus management
# AFL++ corpus minimisation
afl-cmin -i afl-output/default/queue -o corpus_min -- ./prog_afl @@
# Merge libFuzzer corpora from multiple runs
./fuzz_parser -merge=1 merged_corpus/ run1_corpus/ run2_corpus/
# Show coverage (libFuzzer)
./fuzz_parser corpus/ -runs=0 -print_coverage=1
8. CI integration
# GitHub Actions example
- name: Build fuzz targets
run: |
clang -fsanitize=fuzzer,address,undefined -g -O1 \
fuzz_parser.c myparser.c -o fuzz_parser
- name: Short fuzz run (regression check)
run: |
./fuzz_parser corpus/ -max_total_time=60 -error_exitcode=1
# Also run known crash inputs if any:
ls known_crashes/ 2>/dev/null | xargs -I{} ./fuzz_parser known_crashes/{}For long-duration fuzzing, use OSS-Fuzz or ClusterFuzz infrastructure.
9. Structure-aware fuzzing (libFuzzer)
// Custom mutator hook — preserve format invariants
size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
size_t MaxSize, unsigned int Seed) {
// Delegate to default mutator then fix up structure
Size = LLVMFuzzerMutate(Data, Size, MaxSize);
if (Size >= 4)
fix_checksum(Data, Size);
return Size;
}
// Register custom crossover for structured inputs
extern "C" size_t LLVMFuzzerCustomCrossOver(
const uint8_t *Data1, size_t Size1,
const uint8_t *Data2, size_t Size2,
uint8_t *Out, size_t MaxOutSize, unsigned int Seed);Use when naive bit-flipping breaks checksums/headers before reaching
Read more
name: fuzzing description: Fuzzing skill for automated input-driven bug finding in C/C++. Use when setting up libFuzzer or AFL++ fuzz targets, defining fuzz entry points around parsing or I/O boundaries, integrating fuzzing into CI, managing corpora, or combining fuzzing with sanitizers. Activates on queries about libFuzzer, AFL, afl-fuzz, fuzz targets, corpus management, coverage-guided fuzzing, or OSS-Fuzz integration.
Fuzzing
Purpose
Guide agents through setting up and running coverage-guided fuzz testing: libFuzzer (in-process) and AFL++ (fork-based), with sanitizer integration and CI pipeline setup.
Triggers
- "How do I fuzz-test my parser/deserializer?"
- "What is a fuzz target / how do I write one?"
- "How do I set up libFuzzer?"
- "How do I use AFL++ on my program?"
- "How do I run fuzzing in CI?"
- "Fuzzer found a crash — how do I reproduce it?"
Workflow
1. Write a fuzz target (libFuzzer)
A fuzz target is a function that accepts arbitrary bytes and exercises the code under test.
// fuzz_parser.c
#include <stdint.h>
#include <stddef.h>
#include "myparser.h"
// Entry point called by libFuzzer with random data
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// Must not abort/exit on invalid input (that's expected)
// Must not read outside [data, data+size)
MyParser *p = parser_create();
if (p) {
parser_feed(p, (const char *)data, size);
parser_destroy(p);
}
return 0; // Always return 0 (non-zero means discard input)
}Key rules:
- Never call `abort()`, `exit()`, or use global state that persists across calls
- Handle all inputs gracefully (crash = bug found)
- Keep the target fast: the fuzzer calls it millions of times
2. Build with libFuzzer
# Clang (libFuzzer is built into Clang)
clang -fsanitize=fuzzer,address -g -O1 \
fuzz_parser.c myparser.c -o fuzz_parser
# With UBSan too
clang -fsanitize=fuzzer,address,undefined -g -O1 \
fuzz_parser.c myparser.c -o fuzz_parser`-fsanitize=fuzzer` links libFuzzer and provides `main()`. Do not provide your own `main()` in the fuzz target.
3. Run libFuzzer
# Create corpus directory mkdir -p corpus # Seed with known-good inputs (greatly accelerates coverage) cp tests/inputs/* corpus/ # Run the fuzzer ./fuzz_parser corpus/ -max_len=65536 -timeout=10 # Run for a time limit ./fuzz_parser corpus/ -max_total_time=3600 # Run with specific number of jobs (parallel) ./fuzz_parser corpus/ -jobs=4 -workers=4 # Minimise a corpus (remove redundant inputs) ./fuzz_parser -merge=1 corpus_min/ corpus/
Common flags:
| Flag | Default | Effect | |------|---------|--------| | `-max_len=N` | 4096 | Max input size in bytes | | `-timeout=N` | 1200 | Kill if single run takes > N seconds | | `-max_total_time=N` | 0 (forever) | Total fuzzing time | | `-runs=N` | -1 (infinite) | Total number of runs | | `-dict=file` | none | Dictionary of interesting tokens | | `-jobs=N` | 1 | Parallel jobs (each writes its own log) | | `-merge=1` | off | Merge mode: minimise corpus |
4. Reproduce a crash
libFuzzer writes crash inputs to files named `crash-<hash>`, `oom-<hash>`, `timeout-<hash>`.
# Reproduce ./fuzz_parser crash-abc123 # Debug with GDB gdb ./fuzz_parser (gdb) run crash-abc123
5. AFL++ setup
AFL++ is a fork-based fuzzer that works on arbitrary programs (not just those with a fuzz entry point).
# Install apt install afl++ # or build from source # Instrument the target CC=afl-clang-fast CXX=afl-clang-fast++ \ cmake -S . -B build-afl -DCMAKE_BUILD_TYPE=Debug cmake --build build-afl # Or compile directly afl-clang-fast -g -O1 -o prog_afl main.c myparser.c # Create input corpus mkdir -p afl-input afl-output echo "hello" > afl-input/seed1 # Run afl-fuzz -i afl-input -o afl-output -- ./prog_afl @@ # @@ is replaced with the input file path # For stdin-based programs: remove @@ afl-fuzz -i afl-input -o afl-output -- ./prog_afl
6. AFL++ with persistent mode (faster)
Persistent mode avoids `fork()` per input — much faster for library fuzzing:
// In your harness:
#include "myparser.h"
int main(int argc, char **argv) {
while (__AFL_LOOP(1000)) {
// Read input
unsigned char *buf = NULL;
ssize_t len = read(0, &buf, MAX_SIZE); // or use afl_custom_mutator
parser_feed((char*)buf, len);
free(buf);
}
return 0;
}7. Corpus management
# AFL++ corpus minimisation afl-cmin -i afl-output/default/queue -o corpus_min -- ./prog_afl @@ # Merge libFuzzer corpora from multiple runs ./fuzz_parser -merge=1 merged_corpus/ run1_corpus/ run2_corpus/ # Show coverage (libFuzzer) ./fuzz_parser corpus/ -runs=0 -print_coverage=1
8. CI integration
# GitHub Actions example
- name: Build fuzz targets
run: |
clang -fsanitize=fuzzer,address,undefined -g -O1 \
fuzz_parser.c myparser.c -o fuzz_parser
- name: Short fuzz run (regression check)
run: |
./fuzz_parser corpus/ -max_total_time=60 -error_exitcode=1
# Also run known crash inputs if any:
ls known_crashes/ 2>/dev/null | xargs -I{} ./fuzz_parser known_crashes/{}For long-duration fuzzing, use OSS-Fuzz or ClusterFuzz infrastructure.
9. Structure-aware fuzzing (libFuzzer)
// Custom mutator hook — preserve format invariants
size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
size_t MaxSize, unsigned int Seed) {
// Delegate to default mutator then fix up structure
Size = LLVMFuzzerMutate(Data, Size, MaxSize);
if (Size >= 4)
fix_checksum(Data, Size);
return Size;
}
// Register custom crossover for structured inputs
extern "C" size_t LLVMFuzzerCustomCrossOver(
const uint8_t *Data1, size_t Size1,
const uint8_t *Data2, size_t Size2,
uint8_t *Out, size_t MaxOutSize, unsigned int Seed);Use when naive bit-flipping breaks checksums/headers before reaching
A curated suite of AI agent skills for systems and low-level programming — C/C++, Rust, Zig, GPU, bare-metal firmware, Linux kernel/driver development, computer architecture, compiler internals, HPC, and more.
Repo: mohitmishra786/low-level-dev-skills
Other skills on low-level-dev-skills.
- /custom-allocators
Custom allocator skill for memory allocation strategies. Use when implementing pool/slab/arena allocators, tuning jemalloc/mimalloc, writing Rust GlobalAlloc, or benchmarking allocator performance. Activates on queries about jemalloc, mimalloc, tcmalloc, arena allocator,
Open skill - /numa-programming
NUMA programming skill for multi-socket memory locality. Use when detecting NUMA topology, binding processes with numactl, using libnuma API, building NUMA-aware data structures, or measuring remote access penalties. Activates on queries about numactl, libnuma, NUMA topology,
Open skill - /af-xdp
AF_XDP skill for high-performance XDP sockets. Use when creating AF_XDP sockets, configuring UMEM and XSK rings, XDP_REDIRECT programs, copy vs zero-copy mode, or comparing with DPDK. Activates on queries about AF_XDP, xsk_umem, XDP_REDIRECT, libbpf xsk, or zero-copy XDP.
Open skill - /dpdk
DPDK skill for userspace packet I/O. Use when initializing EAL, configuring PMD drivers, using mbuf pools and rte_ring, setting up huge pages, RSS, or testpmd validation. Activates on queries about DPDK, EAL, rte_eth_rx_burst, hugepages, PMD, or testpmd.
Open skill - /io-uring
io_uring skill for Linux async I/O. Use when building high-performance servers with liburing, multi-shot operations, provided buffers, fixed files, zero-copy send, or tokio-uring. Activates on queries about io_uring, SQE/CQE, liburing, IORING_OP_PROVIDE_BUFFERS, or io_uring vs
Open skill - /adc-dac-baremetal
Bare-metal ADC and DAC skill. Use when configuring analog sampling, DMA-driven ADC, calibration, or DAC output on MCUs. Activates on queries about ADC bare-metal, sampling time, DMA ADC, or DAC channel setup.
Open skill

