Map
โ†‘Supply Chain Security

appsec.guide โ€” Fuzzing Chapter (Trail of Bits Testing Handbook)

Wiki summaryfuzzingsecuritytestingreferencetrail-of-bits โ†ณ show in map Markdown
title
appsec.guide โ€” Fuzzing Chapter (Trail of Bits Testing Handbook)
type
summary
summary
Trail of Bits' Testing Handbook fuzzing chapter โ€” terminology, the mutation-based evolutionary algorithm, fuzzer components, and a taxonomy of bug classes; entry point to language-specific subsections
tags
fuzzing, security, testing, reference, trail-of-bits
created
2026-05-12
updated
2026-05-12

The fuzzing chapter of appsec.guide โ€” Trail of Bits' open Testing Handbook. The page itself is the chapter index and a foundational primer; the rest of the chapter splits into language-specific (C/C++, Rust, Go, Python, Ruby) and cross-language subsections.

This summary captures the foundational material here. Sub-chapters (libFuzzer, AFL++, cargo-fuzz, OSS-Fuzz, snapshot fuzzing, etc.) are separate ingests when needed.

Terminology (the vocabulary the rest of the chapter assumes)

  • SUT / target โ€” System Under Test
  • Fuzzer โ€” the program implementing the fuzzing algorithm; fuzzing the activity
  • Test case โ€” a concrete input to the harness (bitstring, AST, structured value)
  • Harness โ€” wraps the SUT, initializes it, integrates it into the testing environment
  • libFuzzer harness โ€” a harness that exposes the LLVMFuzzerTestOneInput entry point
  • Fuzz test โ€” the compiled binary containing harness + SUT
  • Campaign โ€” one start-to-stop execution of the fuzzer
  • Corpus โ€” the evolving set of test cases the campaign maintains
  • Seed corpus โ€” the initial test cases the campaign starts from; individual entries are seeds
  • Fuzzing engine / runtime โ€” the orchestrator (libFuzzer, AFL++, LibAFL, Honggfuzz)
  • Instrumentation โ€” non-functional code added to the SUT to report coverage, sanitizer trips, comparisons, etc.
  • Code coverage โ€” the metric most fuzzers use as their fitness function

The de facto algorithm

Modern coverage-guided fuzzers are evolutionary: maintain a population (corpus), schedule fit members, mutate them, keep offspring that show new fitness, repeat. Fitness is almost always code coverage. See coverage-guided-fuzzing for the concept page; the pseudocode from the handbook:

fn fuzz(corpus) {
  let bug_set = [];
  while let Some(test_case) = schedule(corpus) {
    let offspring = mutate(test_case);
    let observations = execute(offspring);

    if (is_interesting(observations)) { corpus.append(offspring); }
    if (is_bug(observations))         { bug_set.append(offspring); }
  }
  return bug_set;
}

The four customization points (schedule, mutate, execute, is_interesting / is_bug) are what fuzzer engines differ on. LibAFL's composition story is exactly "make all four traits."

What fuzzing finds

The handbook's bug-class taxonomy goes beyond the "memory corruption" reputation:

  • Crashes and panics โ€” UAF, integer overflows, undefined behavior, buffer overflows, memory leaks
  • Invariant violations โ€” business-logic / state-invariant bugs; requires stateful fuzzing (drive the SUT through a sequence of operations rather than one input)
  • Differentials โ€” comparing implementations / platforms / versions; the technique behind most consensus-bug findings, see differential-fuzzing
  • Broken logical properties โ€” round-trip (decode(encode(x)) = x), idempotence (f(f(x)) = f(x)), monotonicity, identity, commutativity, associativity
  • Race conditions โ€” with thread-sanitizer / native race detector

Property checks (round-trip, idempotence, etc.) are the hook for property-based fuzzing โ€” the same mental model as property-based testing (QuickCheck / Hypothesis) but driven by a coverage-guided mutator instead of a random generator.

Why this page is worth keeping in the wiki

The handbook is the right reference to point at when one of the wiki's fuzzing-adjacent pages needs background. It's open, author-bylined, vendor-neutral within fuzzing (the language-specific chapters cover libFuzzer, AFL++, cargo-fuzz, etc. โ€” not just Trail of Bits tools), and reasonably current. Most other fuzzing primers online are either outdated AFL-era walkthroughs or vendor docs that don't generalize.

Sub-chapters (separate ingests when relevant)

  • C/C++ โ€” libFuzzer, AFL++, LibAFL, techniques
  • Rust โ€” cargo-fuzz, techniques
  • Go โ€” covered by gosentry-go-fuzzing-fork in its own right; the handbook's Go section is older / pre-gosentry
  • Python and Ruby
  • Cross-language techniques โ€” harnesses, dictionaries, ASan, environments, FAQ
  • OSS-Fuzz, snapshot fuzzing
  • Static analysis (CodeQL, Semgrep) is referenced from here but lives in a different chapter
  • gosentry-go-fuzzing-fork โ€” the same publisher's Go-specific fuzzing fork; the handbook is the conceptual layer underneath
  • grammar-based-fuzzing โ€” covered as a technique in the C/C++ sub-chapter (Nautilus, AFL++ grammar mode)
  • structure-aware-fuzzing โ€” arbitrary / FuzzedDataProvider; the in-language equivalent of grammars
  • differential-fuzzing โ€” the "Differentials" bug class
  • coverage-guided-fuzzing โ€” the algorithm this page formalizes
  • trail-of-bits โ€” author entity; the handbook is one of their three load-bearing public security resources (alongside the blog and the audit reports)