HN
Today

Tips for more effective fuzz testing with AFL++

Fuzz testing, particularly with AFL++, is an incredibly effective yet often underutilized method for uncovering software defects, with the author claiming "everything is broken" and bugs are everywhere. This article provides eight practical, deep-dive tips for C/C++ developers to significantly enhance the effectiveness of their fuzzing efforts. It offers actionable advice to catch even subtle bugs missed by standard approaches, making it a must-read for anyone serious about software security and stability.

12
Score
0
Comments
#4
Highest Rank
13h
on Front Page
First Seen
Nov 1, 8:00 PM
Last Seen
Nov 2, 8:00 AM
Rank Over Time
5644568899101112

The Lowdown

The author, having fuzzed roughly 1,000 projects over six years, asserts that fuzz testing is a powerful, yet neglected, tool for finding software defects. Using AFL++ on source-available C/C++ targets on glibc-based Linux, the author presents a checklist of eight expert tips to improve fuzzing efficacy, complementing official documentation. These techniques can reveal bugs even in programs previously fuzzed.

  • Configure Sanitizers and Assertions: Employ Address Sanitizer (ASan) and Undefined Behavior Sanitizer (UBSan) with specific ASAN_OPTIONS like detect_stack_use_after_return=1 and max_malloc_fill_size=$((1<<30)) to increase sensitivity to defects beyond default settings. For C++, consider -D_GLIBCXX_DEBUG.
  • Prefer Persistent Mode: Utilize AFL++'s persistent mode (afl-gcc-fast, afl-clang-fast) for up to an order of magnitude speed increase, using a custom template (fuzztmpl.c) for efficiency.
  • Fuzz Any Function: Include target source files directly in the fuzzer's translation unit (TU) to simplify build configurations, bypass public interfaces, and test arbitrary internal or static functions, even allowing hacks to remove main functions or substitute symbols.
  • Isolate Fuzz Tests: Ensure tests are independent by resetting all global state between runs, including strtok buffers, and filling uninitialized heap memory with patterns to prevent interference and aid reproducibility.
  • Do Not Test Directly on the Fuzz Test Buffer: Avoid passing __AFL_FUZZ_TESTCASE_BUF directly to the target; instead, copy it into a sized buffer to properly detect read overflows with ASan and handle null termination.
  • Don't Bother Freeing Memory: Generally, skip explicit memory freeing in fuzz tests as AFL++ resets the target process, aiding isolation and reducing unnecessary work. This applies unless the target is memory-hungry or non-memory resources (like file descriptors) are exhausted.
  • Use a Memory File Descriptor to Back Named Paths: For interfaces requiring named file paths, use memfd_create and its /proc path (e.g., /proc/self/fd/3) to provide input. This enables parallel fuzzing, prevents disk wear, and avoids cleanup, or use fdmemopen for FILE * interfaces.
  • Configure the Target for Smaller Buffers: Reduce