Skip to content
Development
Skill

/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

From plugin
low-level-dev-skills
159142 skills
Install
$ npx -y skills add mohitmishra786/low-level-dev-skills --skill fuzzing --agent claude-code

How 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.md
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

Read more
Ships withlow-level-dev-skills

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.

Get the whole plugin
Stats
172
Stars
24
Forks
Maintained
Maintenance
JavaScript
Language
MIT
License
1mo ago
Last commit
5mo ago
Created

Repo: mohitmishra786/low-level-dev-skills

Other skills on low-level-dev-skills.