Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various improvements to differential fuzzing #4845

Merged

Conversation

alexcrichton
Copy link
Member

I separated out a few commits below to the differential fuzzer which I was working on recently. The main changes are:

  • A start function is now allowed. Support was added to wasmi to run the start function.
  • Fuzzing now can continue if no engines match the current test case. This is only applicable if ALLOWED_ENGINES is set.
  • Unstable proposals like memory64 should be less likely to get generated, ideally improving the rate of usage of engines like v8 and wasmi.
  • A bug related to stack overflow was fixed where if one engine stack overflows it may have inconsistent state with the other so the fuzz test case needs to be discarded from then on.

* Support modules with a `start` function
* Implement trap-matching to ensure that wasmi and Wasmtime both report
  the same flavor of trap.
Locally I was attempting to run against just one wasm engine with
`ALLOWED_ENGINES=wasmi` but the fuzzer quickly panicked because the
generated test case didn't match wasmi's configuration. This commit
updates engine-selection in the differential fuzzer to return `None` if
no engine is applicable, throwing out the test case. This won't be hit
at all with oss-fuzz-based runs but for local runs it'll be useful to
have.
* De-prioritize unstable wasm proposals such as multi-memory and
  memory64 by making them more unlikely with `Unstructured::ratio`.
* Allow fuzzing multi-table (reference types) and multi-memory by
  avoiding setting their maximums to 1 in `set_differential_config`.
* Update selection of the pooling strategy to unconditionally support
  the selected module config rather than the other way around.
This commit fixes an issue found via local fuzzing where engines were
reporting different results but the underlying reason for this was that
one engine was hitting stack overflow before the other. To fix the
underlying issue I updated the execution to check for stack overflow
and, if hit, it discards the entire fuzz test case from then on.

The rationale behind this is that each engine can have unique limits for
stack overflow. One test case I was looking at for example would stack
overflow at less than 1000 frames with epoch interruption enabled but
would stack overflow at more than 1000 frames with it disabled. This
means that the state after the trap started to diverge and it looked
like the engines produced different results.

While I was at it I also improved the "function call returned a trap"
case to compare traps to make sure the same trap reason popped out.
@alexcrichton alexcrichton requested a review from abrown September 2, 2022 03:12
@github-actions github-actions bot added the fuzzing Issues related to our fuzzing infrastructure label Sep 2, 2022
@github-actions
Copy link

github-actions bot commented Sep 2, 2022

Subscribe to Label Action

cc @fitzgen

This issue or pull request has been labeled: "fuzzing"

Thus the following users have been cc'd because of the following labels:

  • fitzgen: fuzzing

To subscribe or unsubscribe from this label, edit the .github/subscribe-to-label.json configuration file.

Learn more.

Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

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

These changes make sense on their own in context, but I have some concerns about our larger approach with this differential fuzzing that I think we should address in follow ups.

Comment on lines +39 to +41
if config.config.max_memories > 1 {
bail!("wasmi does not support multi-memory");
}
Copy link
Member

Choose a reason for hiding this comment

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

Instead of bailing out when an engine doesn't support a config, can we have a pre-pass where the engine is given mutable access to the config to turn off anything that it doesn't support? This just seems like better use of fuzzing time than rejecting iterations and bailing out.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah I've come around to feeling this way as well, I'll work on refactoring to enable this

Comment on lines +57 to +59
if engines.is_empty() {
return Ok(None);
}
Copy link
Member

Choose a reason for hiding this comment

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

Slightly surprised we would ever have a case where we can't run the test case in Wasmtime. What is even the point at that time?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the issue this is addressing is if testing Wasmtime against Wasmtime has been disabled using the ALLOWED_ENGINES environment variable.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah yeah this is only applicable when you're doing something like ALLOWED_ENGINES=wasmi locally where I was trying to only differentially-execute against wasmi

@alexcrichton alexcrichton merged commit 10dbb19 into bytecodealliance:main Sep 2, 2022
@alexcrichton alexcrichton deleted the improve-differential-fuzzing branch September 2, 2022 19:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fuzzing Issues related to our fuzzing infrastructure
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants