Skip to content

Add fuzz_with_reset! macro for resettable state in persistent mode#697

Open
lrubasze wants to merge 17 commits intorust-fuzz:masterfrom
lrubasze:fuzz-with-reset
Open

Add fuzz_with_reset! macro for resettable state in persistent mode#697
lrubasze wants to merge 17 commits intorust-fuzz:masterfrom
lrubasze:fuzz-with-reset

Conversation

@lrubasze
Copy link
Copy Markdown
Contributor

@lrubasze lrubasze commented Feb 6, 2026

Summary

Adds fuzz_with_reset! macro that accepts a reset closure called after each iteration in AFL++ persistent mode. This addresses the stability drop caused by static initialization (OnceLock, lazy_static, once_cell::Lazy) that only executes on the first iteration.

Replaces the removed reset_lazy_static feature (a0173de) with a general-purpose solution — users provide their own reset logic instead of depending on an unmaintained crate.

Changes

  • afl/src/lib.rs: Add fuzz_with_reset() function, refactor fuzz() to delegate to it, add fuzz_with_reset! / fuzz_with_reset_nohook! macros
  • afl/examples/reset_demo.rs: Example demonstrating the problem and fix (USE_RESET=1 env var toggles reset)
  • cargo-afl/tests/integration.rs: Integration test for fuzz_with_reset!
  • README.md: Document the feature

Stability comparison from the reset_demo example

Mode Stability (Linux/x86_64) Stability (macOS/aarch64)
Without reset ~65% ~49%
With reset ~96% ~85%

Implements #406

Note: the example uses Mutex<Option<T>> instead of OnceLock/OnceCell because those types do not support resetting out-of-the-box.

@smoelius
Copy link
Copy Markdown
Member

smoelius commented Feb 6, 2026

Thanks, @lrubasze. I will try to review this over the weekend.

As you probably noticed, something weird is going on with LLVM 22. I would like to get that figure out first.

Copy link
Copy Markdown
Member

@smoelius smoelius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lrubasze Thanks a lot for doing this. I left some comments.

.arg("--manifest-path")
.arg("../afl/Cargo.toml")
.assert()
.success();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you calling cargo afl build here to ensure the example is built with instrumentation? Note that in CI, the examples are built with instrumentation before cargo-afl's tests are run:

- name: Build examples (with AFL instrumentation)
run: cargo run -- afl build --examples -vv
- name: Run tests
run: cargo test -p cargo-afl -vv

So explicitly building the examples with instrumentation should not be necessary.

Aside: I hate the way afl.rs's tests work. Ideally, one could just run cargo test. But I haven't figured out a good way to make that work yet.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will refactor that accordingly.

Yeah, current approach is not very convenient.
One way to make cargo test self-contained would be to move integration tests into a separate crate (e.g. afl-tests). Its build.rs could run cargo afl build --examples, avoiding the circular dependency. But that's out of scope for this PR.

@lrubasze
Copy link
Copy Markdown
Contributor Author

@smoelius I believe all comments are covered. Let me know if there's anything else you wish to improve.

@smoelius
Copy link
Copy Markdown
Member

@lrubasze Just FYI, I am not ignoring you. I just want to run a few more tests before I merge.

@lrubasze
Copy link
Copy Markdown
Contributor Author

@lrubasze Just FYI, I am not ignoring you. I just want to run a few more tests before I merge.

No worries!

Note that it took me only 2 years to proceed with this implementation after reporting the issue 😅

@smoelius
Copy link
Copy Markdown
Member

@lrubasze Could you please squash your changes down to one commit? Then I will merge.

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.

2 participants