Skip to content

feat(engine): Fuzz-Harness Generator — export native AFL/honggfuzz test scaffolds - #1305

Merged
Gbangbolaoluwagbemiga merged 1 commit into
HyperSafeD:mainfrom
dykdee:feat/fuzz-harness-generator-415
Aug 1, 2026
Merged

feat(engine): Fuzz-Harness Generator — export native AFL/honggfuzz test scaffolds#1305
Gbangbolaoluwagbemiga merged 1 commit into
HyperSafeD:mainfrom
dykdee:feat/fuzz-harness-generator-415

Conversation

@dykdee

@dykdee dykdee commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Resolves #415 — "[engine] Fuzz-Harness Generator: Export native Afl.rs/honggfuzz test scaffolds".

Adds a new sanctifier harness CLI subcommand that bridges Sanctifier's static analysis (AST-level parsing) to dynamic analysis: given a Soroban contract source file, it generates ready-to-build native fuzz-target scaffolds for afl.rs and/or honggfuzz, one per public contract function.

How it works

  1. sanctifier-core::harness_spec (new module) walks the same #[contractimpl] blocks that contract_discovery already knows about, but additionally extracts each public, non-reserved function's full typed parameter list (name + Rust type, e.g. Address, BytesN<32>, i128, Vec<Address>), skipping the mandatory leading Env parameter.
  2. sanctifier-cli harness subcommand turns that into code, for each requested backend:
    • a #[derive(Arbitrary)] input struct whose fields are <ParamType as SorobanArbitrary>::Prototype — the pattern documented by soroban_sdk::testutils::arbitrary for fuzzing host-managed Soroban types,
    • a main() that builds an Env, registers the contract, builds a client, converts each prototype via .into_val(&env), and calls client.try_<function>(..),
    • a self-contained, workspace-excluded Cargo.toml per backend (mirroring the contracts/*/fuzz/Cargo.toml convention already used in this repo), auto-detecting and path-dependency-linking the analyzed crate when a Cargo.toml is found above the source file (falls back to a // TODO placeholder otherwise).
sanctifier harness contracts/amm-pool/src/lib.rs --output fuzz-harness --target both
# ✅ Generated 12 fuzz target(s) (6 function(s) x 2 backend(s)) in fuzz-harness

cd fuzz-harness/afl && cargo afl build && cargo afl fuzz -i in -o out target/debug/amm_pool_swap
cd fuzz-harness/honggfuzz && cargo hfuzz build && cargo hfuzz run amm_pool_swap

See docs/fuzz-harness-generator.md for full usage, the generated-code shape, and how it relates to the existing hand-written bolero/libFuzzer harnesses documented in docs/contracts-fuzz.md (unchanged — this is a separate, additive generator, not a replacement).

Testing

  • New unit tests in sanctifier-core::harness_spec (8 tests) covering Env-exclusion, generic/reference type rendering, reserved-entrypoint/private-function exclusion, multi-contract files, and positional-fallback naming for unpatternable parameters.
  • New unit tests in sanctifier-cli::commands::harness (7 tests) covering snake-case conversion, manifest rendering (with/without crate detection), and generated source shape for both backends.
  • New end-to-end integration tests in tooling/sanctifier-cli/tests/harness_tests.rs (9 tests) covering: default (both backends), --target afl/--target honggfuzz selection, --function filtering, generated file/manifest content assertions, real crate auto-detection via a sibling Cargo.toml, the "no fuzzable functions" case, and a nonexistent-path error case.
  • Manually verified end-to-end against a real contract in this repo (contracts/amm-pool) — correctly detected the crate name/path and generated 12 valid targets.
  • cargo clippy -p sanctifier-cli --no-deps -- -D warnings is clean for all new code.

Incidental prerequisite fixes (unrelated to #415)

While getting sanctifier-core/sanctifier-cli to build in this environment (no libclang/libz3, so the optional smt feature can't be enabled), I found that both crates currently fail to compile in any feature configuration on main — these are hard compile errors, not environment-specific:

  • SanctifyConfig's two Default-equivalent constructors (sanctifier-core::lib.rs and sanctifier-cli::commands::init.rs) were missing the smt_timeout_ms field that a previous change added to the struct (E0063).
  • noir_parser::parse_function's Ok((...)) accidentally constructed a duplicate NoirFunction, returning a 4-element tuple where (NoirFunction, usize) was expected (E0308) — clearly leftover from a bad merge.

These three one-line/small fixes are included because they block compiling the very crates this feature lives in, in any configuration; they're unrelated to the harness generator itself. I did not go further and fix other pre-existing, unrelated clippy lints/test failures I noticed while investigating (e.g. a dead-code warning in zk_verifier_skippable.rs, or an unrelated failing test in rules::z007_under_constrained) since those are out of scope for this issue.

I also changed has_attr_named/type_to_name/RESERVED_ENTRYPOINTS in contract_discovery.rs from private to pub(crate) so harness_spec can reuse the existing #[contractimpl]-matching logic instead of duplicating it.

Closes #415

Implements HyperSafeD#415 — bridges static analysis to dynamic analysis by
generating ready-to-build fuzz-target scaffolds from a Soroban contract's
public ABI.

New:
- sanctifier-core::harness_spec — walks #[contractimpl] blocks and extracts
  every public, non-reserved function's typed parameter list (name + Rust
  type, e.g. Address, BytesN<32>, i128), excluding the mandatory leading
  Env parameter.
- sanctifier-cli `harness` subcommand — for each function, generates:
  - a #[derive(Arbitrary)] input struct whose fields are
    <ParamType as SorobanArbitrary>::Prototype (the pattern documented by
    soroban_sdk::testutils::arbitrary for fuzzing host-managed types),
  - a main() that registers the contract, builds a client, converts each
    prototype via .into_val(&env), and calls client.try_<fn>(..),
  - one such target per backend (afl.rs and/or honggfuzz via --target),
  - a self-contained, workspace-excluded Cargo.toml per backend (mirroring
    the contracts/*/fuzz/Cargo.toml convention already used in this repo),
    auto-detecting and path-depending on the analyzed crate when a
    Cargo.toml is found above the source file.
- docs/fuzz-harness-generator.md, linked from DOCUMENTATION_INDEX.md and
  the CLI reference in README.md.
- Unit tests (sanctifier-core, sanctifier-cli) and end-to-end integration
  tests (tooling/sanctifier-cli/tests/harness_tests.rs) covering both
  backends, --target/--function filtering, generated file/manifest shape,
  crate auto-detection, and the no-fuzzable-functions case.

Incidental prerequisite fixes (unrelated to HyperSafeD#415, but required for
sanctifier-core/sanctifier-cli to compile at all without the optional
`smt` feature, which needs libz3/libclang):
- lib.rs / init.rs: SanctifyConfig's Default impls were missing the
  smt_timeout_ms field added in a previous change, a hard E0063 compile
  error present regardless of any feature flag.
- noir_parser.rs: parse_function's Ok(..) tuple accidentally constructed
  a duplicate NoirFunction, giving a 4-element tuple where a 2-element
  (NoirFunction, usize) was expected — a hard E0308 error, also
  unconditional.
- contract_discovery.rs: has_attr_named/type_to_name/RESERVED_ENTRYPOINTS
  changed from private to pub(crate) so harness_spec can reuse them
  instead of duplicating the same #[contractimpl] attribute-matching
  logic.

Closes HyperSafeD#415
@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

@dykdee is attempting to deploy a commit to the gbangbolaoluwagbemiga's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Jul 30, 2026

Copy link
Copy Markdown

@dykdee Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@dykdee

dykdee commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Hello repo maintainer, please can you approve the workflows quickly? the issue is fixed but you have not attended to the case.

@Gbangbolaoluwagbemiga
Gbangbolaoluwagbemiga merged commit bf1b66d into HyperSafeD:main Aug 1, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[engine] Fuzz-Harness Generator: Export native Afl.rs/honggfuzz test scaffolds

2 participants