Files
ghostty/test/fuzz-libghostty

AFL++ Fuzzer for Libghostty

This directory contains an AFL++ fuzzing harness for libghostty-vt (Zig module). At the time of writing this README, it only fuzzes the VT parser, but it can be extended to cover other components of libghostty as well.

Prerequisites

Install AFL++ so that afl-cc and afl-fuzz are on your PATH.

  • macOS (Homebrew): brew install aflplusplus
  • Linux: build from source or use your distro's package (e.g. apt install afl++ on Debian/Ubuntu).

Building

From this directory (test/fuzz-libghostty):

zig build

This compiles a Zig static library (with the fuzz harness in src/lib.zig), emits LLVM bitcode, then links it with src/main.c using afl-cc to produce the instrumented binary at zig-out/bin/ghostty-fuzz.

Running the Fuzzer

The build system has a convenience step that invokes afl-fuzz with the correct arguments:

zig build run

This is equivalent to:

afl-fuzz -i corpus/initial -o afl-out -- zig-out/bin/ghostty-fuzz @@

You may want to run afl-fuzz directly with different options for your own experimentation.

The fuzzer runs indefinitely. Let it run for as long as you like; meaningful coverage is usually reached within a few hours, but longer runs can find deeper bugs. Press ctrl+c to stop the fuzzer when you're done.

Finding Crashes and Hangs

After (or during) a run, results are written to afl-out/default/:


afl-out/default/
├── crashes/ # Inputs that triggered crashes
├── hangs/ # Inputs that triggered hangs/timeouts
└── queue/ # All interesting inputs (the evolved corpus)

Each file in crashes/ or hangs/ is a raw byte file that triggered the issue. The filename encodes metadata about how it was found (e.g. id:000000,sig:06,...).

Reproducing a Crash

Replay any crashing input by passing it directly to the harness:

# Via command-line argument
zig-out/bin/ghostty-fuzz afl-out/default/crashes/<filename>