| name | libfuzzer-pipeline |
| description | Use this skill for the complete end-to-end LibFuzzer workflow: writing harnesses, generating seeds, and building OSS-Fuzz-compatible packages — all in one go. Trigger when the user mentions doing the full fuzzing pipeline, or phrases like "从零开始对这个库进行fuzz", "complete fuzzing setup", "fuzz this library end to end", "set up fuzzing for X", "全流程", "write harnesses and package them", "prepare this library for oss-fuzz", or when the user has a C/C++ library and wants to go from source code all the way to distributable fuzz binaries. Also trigger when the user mentions two or more of: harness writing, seed generation, packaging, oss-fuzz — as this signals they want the full pipeline, not just one step. Use this skill proactively when the user's goal is to produce a complete, ready-to-deploy fuzz setup for a library, even if they only describe the end goal ("I want to fuzz libpng" / "我想对 cJSON 做模糊测试").
|
LibFuzzer Full Pipeline
This skill orchestrates three sub-skills to take a C/C++ library from source code
to ready-to-deploy OSS-Fuzz packages in one continuous workflow:
Stage 0 │ (this skill) │ Understand the library + build into build_harness/
↓ │ │
Stage 1 │ libfuzzer-harness-writer │ Write fuzz harnesses (.c/.cpp files)
↓ │ │
Stage 2 │ libfuzzer-seed-generator │ Generate initial seed corpora
↓ │ │
Stage 3 │ libfuzzer-oss-packager │ Compile + package into sanitizer zips
The three sub-skills are not duplicated here — when entering each stage, read
the corresponding SKILL.md and follow it completely before moving on.
Sub-skill locations
| Stage | Skill name | SKILL.md path |
|---|
| 1 — Harness writing | libfuzzer-harness-writer | ~/.claude/skills/libfuzzer-harness-writer/SKILL.md |
| 2 — Seed generation | libfuzzer-seed-generator | (in example-skills, find with find ~/.claude -name SKILL.md -path "*seed-generator*") |
| 3 — OSS-Fuzz packaging | libfuzzer-oss-packager | ~/.claude/skills/libfuzzer-oss-packager/SKILL.md |
Stage 0 — Understand the library and build it
This stage always runs first, even if harnesses already exist. Building the
library baseline into build_harness/ gives every subsequent stage a clean,
consistent artifact to reference — symbol export, smoke-test compilation, and
the packager's build-script template all depend on it.
0a. Read the library source
- Read all public header files (
.h) to understand the API surface
- Read
CMakeLists.txt / Makefile / configure.ac to understand the build system
- Read
oss-fuzz/projects/<libname>/build.sh if it exists — this is the
canonical recipe for building the library for fuzzing; follow it closely
find . -path "*/oss-fuzz/projects/*/build.sh" -o \
-path "*/projects/*/build.sh" 2>/dev/null | head -5
0b. Create build_harness/ and build the library
Create a build_harness/ directory at the project root (sibling to fuzzing/).
Build both the static archive and the shared library into it, following the
oss-fuzz build script as a reference. Typical pattern for CMake:
mkdir -p build_harness && cd build_harness
cmake <source_dir> \
-DBUILD_SHARED_LIBS=ON \
-DENABLE_CJSON_TEST=OFF \
-DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
Adapt the flags to the actual build system. The goal is:
build_harness/lib<name>.a — static archive (used for harness compilation)
build_harness/lib<name>.so — shared library (used for symbol export)
build_harness/include/ or the source headers — include path for compilation
0c. Export symbols to understand the API
nm -D build_harness/lib<name>.so | grep ' T ' | awk '{print $3}' | sort \
> build_harness/exported_symbols.txt
This symbol list feeds directly into Stage 1's gap analysis.
0d. Record the build context
Add these to the continuity note (see "Continuity between stages" below):
build_harness dir: <absolute_path>/build_harness/
static lib: build_harness/lib<name>.a
shared lib: build_harness/lib<name>.so
include dir: <source_dir>/ (or build_harness/include/)
build system: cmake / make / autoconf
oss-fuzz build.sh: <path> (or "not found")
Step 0 — Assess the starting point
Before doing anything else, determine which stages are already complete so you
can pick up from the right place rather than redoing finished work.
Run this survey on the project directory:
find <project_dir> -name "*fuzzer*.c" -o -name "*fuzzer*.cpp" | grep -v "fuzz_main\|afl" | sort
find <project_dir> -type d -name "seeds_*" -o -name "inputs" -o -name "corpus" | xargs ls 2>/dev/null
find . -name "*_libfuzzer_*.zip" -o -name "*fuzzer" -executable 2>/dev/null | sort
Then apply this decision table:
| Harnesses? | Seeds? | Packages? | Start at |
|---|
| No | No | No | Stage 1 |
| Yes | No | No | Stage 2 |
| Yes | Yes | No | Stage 3 |
| Yes | Yes | Yes | Ask user: rebuild everything, or just re-package? |
| Yes | No | Yes | Seeds missing — go back to Stage 2, then re-run Stage 3 |
| Partial | — | — | Tell user which harnesses exist vs. missing; offer to fill gaps (Stage 1), then continue |
Tell the user which stage you're starting from and why, so they can correct you
if the assessment is wrong.
Stage 1 — Write harnesses
Read and follow:
~/.claude/skills/libfuzzer-harness-writer/SKILL.md
What this stage produces: One or more <name>_fuzzer.c (or .cpp) files
placed in the library's fuzzing/ directory, each defining LLVMFuzzerTestOneInput.
Handoff check before moving to Stage 2:
- Every target functional group in the API has at least one harness
- Each harness compiles cleanly with
-fsanitize=fuzzer,address and passes a
5-second smoke test (the sub-skill covers this in its Step 6)
- Note the exact file paths — they feed directly into Stage 2
Stage 2 — Generate seeds
Read and follow:
find ~/.claude -name SKILL.md -path "*seed-generator*" | head -1
(then Read that file)
What this stage produces: One seed directory per harness, named
seeds_<fuzzer_name>/ (or reusing inputs/ for existing corpora), each
containing diverse initial input files.
Context to carry forward from Stage 1:
- The list of harness files and their input format (text JSON / binary / structured)
- Any semantic constraints discovered while writing the harnesses (e.g., "the
parser requires a 4-byte length prefix") — share these with the seed generator
so it can produce valid seeds immediately rather than guessing
Handoff check before moving to Stage 3:
- Every harness has a corresponding seed directory with at least a few files
- Running
<fuzzer_binary> <seed_dir>/ -runs=0 exits cleanly (no immediate crash)
Stage 3 — Package
Read and follow:
~/.claude/skills/libfuzzer-oss-packager/SKILL.md
What this stage produces:
out/
├── <libname>_libfuzzer_address.zip ← ASAN build
└── <libname>_libfuzzer_memory.zip ← MSAN build
Each zip contains: compiled binaries, _seed_corpus.zip per fuzzer, .dict
files (if any), and llvm-symbolizer.
Context to carry forward from Stage 2:
- The exact paths of all seed directories (Stage 2 output) — provide these
to the packager's
SEED_DIRS map so it knows where to find them
- The library name (for the zip filename convention)
Continuity between stages
Each stage leaves behind artifacts that the next stage needs. To avoid
re-discovering things, keep a short running note as you work:
Library: <name>
Source dir: <path>
Fuzzing dir: <path>
build_harness dir: <path>/build_harness/
Static lib: build_harness/lib<name>.a
Shared lib: build_harness/lib<name>.so
Include dir: <path>
oss-fuzz build.sh: <path> (or "not found")
Build system: cmake / make / autoconf
Harnesses found/written:
- cjson_read_fuzzer.c → seeds: fuzzing/inputs/
- cjson_builder_fuzzer.c → seeds: fuzzing/seeds_cjson_builder_fuzzer/
- cjson_mutate_fuzzer.c → seeds: fuzzing/seeds_cjson_mutate_fuzzer/
- cjson_ops_fuzzer.c → seeds: fuzzing/seeds_cjson_ops_fuzzer/
Dict file: fuzzing/json.dict
Output dir: ./out/
Update this note after each stage completes. It prevents you from re-running
discovery commands and keeps the context tight across a long session.
Final checklist
After all three stages are done, verify the complete output before declaring
success:
for ZIP in out/*_libfuzzer_*.zip; do
echo "=== $ZIP ==="
unzip -l "$ZIP" | awk '{print $NF}' | grep -v "^$\|^Name\|^---\|files$" | sort
done
Each zip should contain for every fuzzer:
If anything is missing, return to the relevant stage — the sub-skill for that
stage will tell you exactly how to fix it.