|
| 1 | +# Fuzzing |
| 2 | + |
| 3 | +<!-- date-check: Mar 2023 --> |
| 4 | + |
| 5 | +For the purposes of this guide, *fuzzing* is any testing methodology that |
| 6 | +involves compiling a wide variety of programs in an attempt to uncover bugs in |
| 7 | +rustc. Fuzzing is often used to find internal compiler errors (ICEs). Fuzzing |
| 8 | +can be beneficial, because it can find bugs before users run into them and |
| 9 | +provide small, self-contained programs that make the bug easier to track down. |
| 10 | +However, some common mistakes can reduce the helpfulness of fuzzing and end up |
| 11 | +making contributors' lives harder. To maximize your positive impact on the Rust |
| 12 | +project, please read this guide before reporting fuzzer-generated bugs! |
| 13 | + |
| 14 | +## Guidelines |
| 15 | + |
| 16 | +### In a nutshell |
| 17 | + |
| 18 | +*Please do:* |
| 19 | + |
| 20 | +- Ensure the bug is still present on the latest nightly rustc |
| 21 | +- Include a reasonably minimal, standalone example along with any bug report |
| 22 | +- Include all of the information requested in the bug report template |
| 23 | +- Search for existing reports with the same message and query stack |
| 24 | +- Format the test case with `rustfmt`, if it maintains the bug |
| 25 | + |
| 26 | +*Please don't:* |
| 27 | + |
| 28 | +- Report lots of bugs that use internal features, including but not limited to |
| 29 | + `custom_mir`, `lang_items`, `no_std`, and `rustc_attrs`. |
| 30 | +- Seed your fuzzer with inputs that are known to crash rustc (details below). |
| 31 | + |
| 32 | +### Discussion |
| 33 | + |
| 34 | +If you're not sure whether or not an ICE is a duplicate of one that's already |
| 35 | +been reported, please go ahead and report it and link to issues you think might |
| 36 | +be related. In general, ICEs on the same line but with different *query stacks* |
| 37 | +are usually distinct bugs. |
| 38 | + |
| 39 | +## Building a corpus |
| 40 | + |
| 41 | +When building a corpus, be sure to avoid collecting tests that are already |
| 42 | +known to crash rustc. A fuzzer that is seeded with such tests is more likely to |
| 43 | +generate bugs with the same root cause, wasting everyone's time. The simplest |
| 44 | +way to avoid this is to loop over each file in the corpus, see if it causes an |
| 45 | +ICE, and remove it if so. |
| 46 | + |
| 47 | +To build a corpus, you may want to use: |
| 48 | + |
| 49 | +- The rustc/rust-analyzer/clippy test suites (or even source code) --- though avoid |
| 50 | + tests that are already known to cause failures, which often begin with comments |
| 51 | + like `// failure-status: 101` or `// known-bug: #NNN`. |
| 52 | +- The already-fixed ICEs in [Glacier][glacier] --- though avoid the unfixed |
| 53 | + ones in `ices/`! |
| 54 | + |
| 55 | +## Extra credit |
| 56 | + |
| 57 | +Here are a few things you can do to help the Rust project after filing an ICE. |
| 58 | + |
| 59 | +- Add the minimal test case to [Glacier][glacier] |
| 60 | +- [Bisect][bisect] the bug to figure out when it was introduced |
| 61 | +- Fix unrelated problems with the test case (things like syntax errors or |
| 62 | + borrow-checking errors) |
| 63 | +- Minimize the test case (see below) |
| 64 | + |
| 65 | +[bisect]: https://github.com/rust-lang/cargo-bisect-rustc/blob/master/TUTORIAL.md |
| 66 | + |
| 67 | +## Minimization |
| 68 | + |
| 69 | +It can be helpful to *minimize* the fuzzer-generated input. When minimizing, be |
| 70 | +careful to preserve the original error, and avoid introducing distracting |
| 71 | +problems such as syntax, type-checking, or borrow-checking errors. |
| 72 | + |
| 73 | +There are some tools that can help with minimization. If you're not sure how |
| 74 | +to avoid introducing syntax, type-, and borrow-checking errors while using |
| 75 | +these tools, post both the complete and minimized test cases. Generally, |
| 76 | +*syntax-aware* tools give the best results in the least amount of time. |
| 77 | +[`treereduce-rust`][treereduce] and [picireny][picireny] are syntax-aware. |
| 78 | +`halfempty` is not, but is generally a high-quality tool. |
| 79 | + |
| 80 | +[halfempty]: https://github.com/googleprojectzero/halfempty |
| 81 | +[picireny]: https://github.com/renatahodovan/picireny |
| 82 | +[treereduce]: https://github.com/langston-barrett/treereduce |
| 83 | + |
| 84 | +## Effective fuzzing |
| 85 | + |
| 86 | +When fuzzing rustc, you may want to avoid generating code, since this is mostly |
| 87 | +done by LLVM. Try `--emit=mir` instead. |
| 88 | + |
| 89 | +A variety of compiler flags can uncover different issues. |
| 90 | + |
| 91 | +If you're fuzzing a compiler you built, you may want to build it with `-C |
| 92 | +target-cpu=native` to squeeze out a few more executions per second. |
| 93 | + |
| 94 | +## Existing projects |
| 95 | + |
| 96 | +- [fuzz-rustc][fuzz-rustc] demonstrates how to fuzz rustc with libfuzzer |
| 97 | +- [icemaker][icemaker] runs rustc and other tools on a large number of source |
| 98 | + files with a variety of flags to catch ICEs |
| 99 | +- [tree-splicer][tree-splicer] generates new source files by combining existing |
| 100 | + ones while maintaining correct syntax |
| 101 | + |
| 102 | +[glacier]: https://github.com/rust-lang/glacier |
| 103 | +[fuzz-rustc]: https://github.com/dwrensha/fuzz-rustc |
| 104 | +[icemaker]: https://github.com/matthiaskrgr/icemaker/ |
| 105 | +[tree-splicer]: https://github.com/langston-barrett/tree-splicer/ |
0 commit comments