-
-
Notifications
You must be signed in to change notification settings - Fork 46
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
Add fuzz testing to Module
/ParseOutput
#3
Conversation
Current failing fuzz run: ❯ cargo fuzz run statements
Compiling ezno-parser v0.0.1 (/Users/calebjasik-defined/Github/ezno/parser)
Compiling ezno-parser-fuzz v0.0.0 (/Users/calebjasik-defined/Github/ezno/parser/fuzz)
Finished release [optimized + debuginfo] target(s) in 1m 06s
Finished release [optimized + debuginfo] target(s) in 0.02s
Running `target/aarch64-apple-darwin/release/statements -artifact_prefix=/Users/calebjasik-defined/Github/ezno/parser/fuzz/artifacts/statements/ /Users/calebjasik-defined/Github/ezno/parser/fuzz/corpus/statements`
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 1060211075
INFO: Loaded 1 modules (243109 inline 8-bit counters): 243109 [0x105754220, 0x10578f7c5),
INFO: Loaded 1 PC tables (243109 PCs): 243109 [0x10578f7c8,0x105b45218),
INFO: 63 files found in /Users/calebjasik-defined/Github/ezno/parser/fuzz/corpus/statements
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: seed corpus: files: 63 min: 1b max: 4b total: 177b rss: 64Mb
thread '<unnamed>' panicked at 'internal error: entered unreachable code', /Users/calebjasik-defined/Github/ezno/parser/src/expressions/template_literal.rs:143:22
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
==86685== ERROR: libFuzzer: deadly signal
thread '<unnamed>' panicked at 'internal error: entered unreachable code', /Users/calebjasik-defined/Github/ezno/parser/src/expressions/template_literal.rs:143:22
thread '<unnamed>' panicked at 'internal error: entered unreachable code', /Users/calebjasik-defined/Github/ezno/parser/src/expressions/template_literal.rs:143:22
thread '<unnamed>' panicked at 'internal error: entered unreachable code', /Users/calebjasik-defined/Github/ezno/parser/src/expressions/template_literal.rs:143:22
────────────────────────────────────────────────────────────────────────────────
Error: Fuzz target exited with signal: 6 (SIGABRT)
|
Wow this is awesome. I don't know a huge amount about testing practises and even less about fuzz testing, so I am learning some interesting things here. So as I am learning this checks that the parsing (and lexing step) doesn't panic at runtime for a set of random string inputs. So it should bring up problems like out of bounds indexing, unhandled character codes or places which I think are It looks like the template literal parsing assumes that the lexing produces a certain sequence of tokens but another token has crept in there? Will merge this and fix afterwards! This test fuzzes parsing You have also added it being printed back to a string and then reparsed so it doubles up as testing that the string output has the same logic as parsing! I wonder how often the string ends up being valid code? but still nice. This is great addition to enforcing stability, so eager to merge. Just a few things before I merge:
Other comments were helpful and are okay! Are there any objections to a squash merge? |
ParseOutput
Module
/ParseOutput
the |
I think https://google.github.io/clusterfuzzlite/ is the best option for CI other than just running the fuzz tests with a max fuzz time.. |
parser/fuzz/Cargo.toml
Outdated
|
||
# Prevent this from interfering with workspaces | ||
[workspace] | ||
members = ["."] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line makes me believe it shouldn't be added to the larger workspace.
If only rust-analyzer was smarter 😭
Another alternative here is to simply take the corpus entries as generated and make unit tests with them. This is ultimately one of the benefits of this fuzzer is that you can use it to generate test cases automatically, and since most bugs are discovered merely by hitting the code (having trouble finding a citation for this, but it's empirically true). As it stands, this fuzzer will have trouble "solving" the grammar since it mutates text rather than mutating source code, and will have difficulty exploring the full program without grammar inference. For an example of a fuzzer which generates (mostly) valid ASTs, you should see: https://github.com/boa-dev/boa/tree/main/fuzz There are a lot of great options for fuzzing with Rust, but ultimately, I would recommend using this particular parser as a testcase generator for unit tests, then switch over to CI fuzzing with a grammar-aware fuzzer once you move beyond the parsing phase. Given that you have most of what you need already to do this, it should be fairly quick work. 🙂 |
I submitted a PR to @jasikpark's repo with a structured fuzzer. It will find different bugs than the string-based fuzzer, so they operate as different testing tools. Also, given that there doesn't seem to be much unsafe in this crate, you can safely gain quite a bit of speed by executing cargo fuzz with |
Add structured fuzzer based on boa
use pretty_assertions::assert_eq; | ||
|
||
fn do_fuzz(data: common::FuzzSource) -> Corpus { | ||
let input = data.source; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be valid JS code in this instance, so we should have fewer Corpus:Reject
s / failed parses
Awesome, so looking at the latest commits it is reusing the fuzzing tests from boa. And (for reasons) they don't publish it as a library. So So @VTCAKAVSMoACE s changes mean that the fuzzing input is strings that may be actual JS syntax? Is there a way to see some examples of that? Is there a need for both Once I understand that it will be nearly to merge. I will do a few things just before:
|
My changes should always be valid JS syntax. This will help you find other problems in your code that are more high-level issues; where @jasikpark's fuzzer will generally find lexing issues,
You can view the source code triggering the bug after the crash or by using |
Should probably run the fuzz tests with a timeout and with For now, they will almost certainly be failing; as a general rule, fuzzing will find unbelievably specific problems 😅 |
Awesome, I am windows (which as I have just found out, cargo-fuzz doesn't work on) so just wanted to see the output. I think the commands I should be running in the CI are then: (with the cargo fuzz run statements -- -s none -timeout 120 || true
cargo fuzz run structured -- -s none -timeout 120 || true I have added the README and am just wondering before I press the merge button whether Even though merging will show red lights on main, it's fine as it is only highlighting existing errors, not introducing new ones. From there can make issues for the errors it has found, then begin work on those. Will check back in on it tomorrow morning 😄 |
Here are the full commands I recommend:
You can review all of the available options here: https://llvm.org/docs/LibFuzzer.html#options |
…ctured` This also uses the timeout commands that VTCAKAVSMoACE recommended for CI
If we run the fuzzers concurrently, it will take 240s for the fuzzer step in CI.. ig that's fine if they aren't required + they're catching stuff rn |
Ah it should be fine. It currently takes 7 mins in sequence, which isn't terrible. Thanks for the file rename and the README additions. The CI still needs some adjustment. It should run the two fuzzing tests in parallel. That would also allow GH actions to show a red cross for the failings. It currently dumps a lot of other information, don't know if there is a way to just the important lines. But that is a different issue only for CI and needs some other stuff, so will open that separately. This looks good to go! Ezno's parser now has fuzzing tests 🎉 |
First off: Thanks for working on this project! I'm excited to see where this goes 😁!
This PR adds a
cargo-fuzz
fuzzer forParseOutput
Seemed like a good first-step at adding some fuzz testing validation to the project :p
The methodology is that code printed out by the project should parse correctly a second time if it parsed correctly the first time.
I'm currently hitting an
unimplemented!()
match arm in testing, so I'll have to learn how to debug rust to be of help w/ a bugfix.To run the fuzzer:
cargo install cargo-fuzz rustup default nightly cd parser/fuzz cargo fuzz run statements
This fuzzer is a clone of the unit test in https://github.com/kaleidawave/ezno/blob/main/parser/tests/statements.rs