HarnessMinimizer minimizes crashing C/C++ fuzz harnesses while preserving the crash.
It can be used through a command-line interface
(CLI) and a Python API.
Installation · CLI usage · Arguments · Python API · License
docker build -t '<image-name>' - < Dockerfile
docker run -d --name '<container-name>' --init '<image-name>' sleep infinity
docker exec -it '<container-name>' bashThe image fetches the GitHub main branch.
To select a specific commit, tag, or branch, add --build-arg HARNESSMINIMIZER_REF='<revision>' to docker build.
Docker may reuse a cached checkout; use --no-cache
to fetch again.
Install the Python package and activate its environment using uv.
uv sync
source .venv/bin/activateReplace the absolute paths below with your harness, crash input, target library,
and output locations inside the container, and replace target with the library
name. The harness and crash input can be in different directories. If the harness
opens runtime files using relative paths, run from the working directory those paths require.
Optimized pipeline:
harnessminimizer /path/to/harness.cpp \
--tool treereduce \
--compile-flags="-I/path/to/library/include" \
--link-flags="-L/path/to/library/lib -ltarget" \
--crash-input /path/to/inputs/crash-input \
--pch --amortize-link --no-symbolize --stable \
-o /path/to/output/reduced.cppUnoptimized pipeline:
harnessminimizer /path/to/harness.cpp \
--tool treereduce \
--compile-flags="-I/path/to/library/include" \
--link-flags="-L/path/to/library/lib -ltarget" \
--crash-input /path/to/inputs/crash-input \
--split --symbolize --stable \
-o /path/to/output/reduced.cppThe default is the unoptimized configuration: split compilation with
symbolization on, PCH off, and amortized linking off. HarnessMinimizer
uses treereduce and 60 workers by default. Replace --tool treereduce
with --tool perses, --tool wdd, or --tool cdd to use an optional engine.
Profiling and stable mode are off unless explicitly enabled.
Show available arguments
| Argument | Purpose |
|---|---|
harness |
Required path to the original harness source. |
-o, --output |
Required destination for the reduced harness. |
--crash-input |
Optional crashing input file passed to the harness. |
--compile-flags="..." |
Compiler flags, such as include paths, defines, and language standard. |
--link-flags="..." |
Linker flags, such as library paths, library names, or full archive paths. |
--tool |
Reduction engine: treereduce (default), perses, wdd, or cdd. |
-j, --jobs |
Requested concurrent candidate checks: 1–63, default 60. |
--direct, --split, --pch |
Compile and link in one step; compile then link separately (default); or use precompiled headers with separate compilation and linking. |
--amortize-link |
Reuse a persistent runner and shared/static target libraries. |
--stable |
Repeat engine passes until their stopping conditions are reached. |
--symbolize, --no-symbolize |
Enable symbolized candidate checks (default), or disable them for faster reduction. These flags are mutually exclusive. |
--work-dir |
Directory for intermediate files; a temporary directory is created by default. |
--profile |
Record candidate timings and reduction throughput for diagnostics. |
--debug |
Log candidate compilation and crash-check details. |
Choose only one of --direct, --split, and --pch. --amortize-link requires
split or PCH mode and shared or static target libraries in the link flags.
Use the --compile-flags="..." and --link-flags="..." spelling shown above for
values beginning with -. See harnessminimizer --help for the full option list.
The CLI copies any required generated header files beside the output harness.
Run the same reduction from Python and check that it succeeded before using the result.
from harnessminimizer import ReductionConfig, reduce_with_config
result = reduce_with_config(ReductionConfig(
harness_path="/path/to/harness.cpp",
tool="treereduce",
crash_input="/path/to/inputs/crash-input",
compile_flags="-I/path/to/library/include",
link_flags="-L/path/to/library/lib -ltarget",
compilation_mode="pch",
amortize_link=True,
symbolize=False,
stable=True,
))
if not result.success:
raise RuntimeError("Reduction did not preserve the crash")
print(result.reduced_harness)The API uses the same defaults as the CLI. If you move the returned harness, copy
the files in result.generated_headers alongside it.
Supported reduction engines:
- Treereduce: https://github.com/langston-barrett/treereduce
- Perses, WDD and CDD: https://github.com/uw-pluverse/perses
HarnessMinimizer is distributed as a whole under a dual-license model. You can choose either option:
-
Open-source license (AGPL-3.0-only). Use, modify, and share HarnessMinimizer under the AGPL's terms. If you distribute covered binaries, provide the corresponding source as required by the license. If you run a modified version as a network service, offer its corresponding source to users who interact with it remotely. Full terms: LICENSE.
-
Commercial license. If you cannot or do not want to meet the AGPL requirements for your intended use, obtain a separately negotiated commercial license before proceeding. Contact fuzzanything@gmail.com. This repository does not grant a commercial license.
Third-party code. Upstream license conditions and notices for LLVM's FuzzedDataProvider (Apache-2.0 with LLVM exceptions) and treereduce (MIT) remain applicable under either option. See THIRD_PARTY_NOTICES for details and THIRD_PARTY_LICENSES for the upstream license texts.
Optional Perses engines. Perses is a separate external program under GPL-3.0-or-later. It is not bundled in HarnessMinimizer's source repository or Python packages: users obtain and build it separately, or the Docker build downloads and installs it automatically. HarnessMinimizer invokes its command-line interface. A commercial license for HarnessMinimizer does not grant exceptions to Perses's license.
Acknowledgment. If you use or integrate HarnessMinimizer, we appreciate an acknowledgment in your project documentation or research publications.