Skip to content

Ledger-Donjon/absolution

Repository files navigation

Absolution

Absolution lets you specify an invariant for a program’s global state and fuzz its entrypoints from states uniformly sampled from that invariant. This helps surface bugs in any interleaving of calls, assuming the fuzzer can explore the space sufficiently.

How it works

  1. Parse globals from your C translation unit(s) using aro.
  2. Build flattened globals containing fields, padding, and domains.
  3. Optionally apply a .zon invariant to constrain field values (per-element .values / .pointers, or whole-field blobs with .whole_values on array-shaped fields; see USAGE.md).
  4. Emit fuzzer.c with sampling, invariant checking, and libFuzzer entrypoint.
  5. Emit a symbol redefinition file for objcopy (handles static globals across translation units).
  6. Write an optional seed file sized to the required random bytes.

Requirements

  • Zig 0.16.0 (per build.zig.zon)
  • C toolchain with libFuzzer support (e.g., clang -fsanitize=fuzzer)
  • objcopy (GNU binutils or llvm-objcopy) — for static symbol redefinition

Quick start

# Build absolution
zig build -Doptimize=ReleaseFast

# Show CLI help
./zig-out/bin/absolution -h

# Generate fuzzer sources from one or more translation units
./zig-out/bin/absolution \
  -t path/to/module_a.c \
  -t path/to/module_b.c \
  --entry MyTestOneInput \
  --out fuzzer.c \
  --redef fuzzer.redef \
  --seed fuzzer.seed \
  -- -I path/to/include -DMY_DEFINE=42

# Compile targets, apply objcopy, link, and run
clang -g -c module_a.c -o module_a.o
clang -g -c module_b.c -o module_b.o
# (apply objcopy --redefine-sym / --globalize-symbol per fuzzer.redef)
clang -g -fsanitize=fuzzer,address fuzzer.c harness.c module_a.o module_b.o -o fuzzer
mkdir -p corpus && cp fuzzer.seed corpus/
./fuzzer corpus/

CMake integration

Absolution ships CMake modules for find_package(Absolution). After installing, add fuzzing to an existing CMake project with a single function call:

find_package(Absolution REQUIRED)

absolution_add_fuzzer(
    NAME fuzz_my_target
    TARGETS src/module_a.c src/module_b.c
    HARNESS fuzz/my_harness.c
    ENTRY MyTestOneInput
    INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/include"
    COMPILE_DEFINITIONS "MY_DEFINE=42"
)

This creates a CMake target that handles the full pipeline: run absolution, compile objects, apply objcopy symbol redefinitions, and link the final fuzzer binary with sanitizers.

See example/protocol_parser/ for a complete working example with multiple translation units.

Testing

zig build test                          # Run unit tests
zig run scripts/integration.zig         # Integration tests
zig run scripts/integration.zig -- foo  # Run only tests matching "foo"

Documentation

About

Build fuzzer with in-depth state manipulation

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Contributors