2018-11-14 01:23:43 -06:00
|
|
|
# Miri [![Build Status](https://travis-ci.org/solson/miri.svg?branch=master)](https://travis-ci.org/solson/miri) [![Windows build status](https://ci.appveyor.com/api/projects/status/github/solson/miri?svg=true)](https://ci.appveyor.com/project/solson63299/miri)
|
2016-02-02 04:47:28 -06:00
|
|
|
|
2016-04-13 19:41:37 -05:00
|
|
|
|
2018-11-13 06:28:09 -06:00
|
|
|
An experimental interpreter for [Rust][rust]'s
|
|
|
|
[mid-level intermediate representation][mir] (MIR). It can run binaries and
|
|
|
|
test suites of cargo projects and detect certain classes of undefined behavior,
|
|
|
|
for example:
|
|
|
|
|
|
|
|
* Out-of-bounds memory accesses and use-after-free
|
|
|
|
* Invalid use of uninitialized data
|
|
|
|
* Violation of intrinsic preconditions (an [`unreachable_unchecked`] being
|
|
|
|
reached, calling [`copy_nonoverlapping`] with overlapping ranges, ...)
|
|
|
|
* Not sufficiently aligned memory accesses and references
|
|
|
|
* Violation of basic type invariants (a `bool` that is not 0 or 1, for example,
|
|
|
|
or an invalid enum discriminant)
|
|
|
|
* WIP: Violations of the rules governing aliasing for reference types
|
|
|
|
|
|
|
|
[rust]: https://www.rust-lang.org/
|
|
|
|
[mir]: https://github.com/rust-lang/rfcs/blob/master/text/1211-mir.md
|
|
|
|
[`unreachable_unchecked`]: https://doc.rust-lang.org/stable/std/hint/fn.unreachable_unchecked.html
|
|
|
|
[`copy_nonoverlapping`]: https://doc.rust-lang.org/stable/std/ptr/fn.copy_nonoverlapping.html
|
2016-02-02 04:47:28 -06:00
|
|
|
|
2018-11-16 03:01:54 -06:00
|
|
|
|
2018-08-14 02:35:00 -05:00
|
|
|
## Running Miri on your own project('s test suite)
|
|
|
|
|
2018-11-25 15:17:48 -06:00
|
|
|
Install Miri as a cargo subcommand:
|
|
|
|
|
|
|
|
```sh
|
2018-12-28 11:16:55 -06:00
|
|
|
cargo +nightly install --force --git https://github.com/solson/miri miri
|
2018-11-25 15:17:48 -06:00
|
|
|
```
|
|
|
|
|
2018-11-30 02:23:44 -06:00
|
|
|
If this does not work, try using the nightly version given in
|
|
|
|
[this file](https://raw.githubusercontent.com/solson/miri/master/rust-version). CI
|
|
|
|
should ensure that this nightly always works.
|
|
|
|
|
|
|
|
You have to use a consistent Rust version for building miri and your project, so
|
|
|
|
remember to either always specify the nightly version manually (like in the
|
|
|
|
example above), overriding it in your project directory as well, or use `rustup
|
|
|
|
default nightly` (or `rustup default nightly-YYYY-MM-DD`) to globally make
|
|
|
|
`nightly` the default toolchain.
|
|
|
|
|
2018-12-19 04:16:19 -06:00
|
|
|
Now you can run your project in Miri:
|
2018-11-25 11:27:24 -06:00
|
|
|
|
|
|
|
1. Run `cargo clean` to eliminate any cached dependencies. Miri needs your
|
|
|
|
dependencies to be compiled the right way, that would not happen if they have
|
|
|
|
previously already been compiled.
|
|
|
|
2. To run all tests in your project through Miri, use `cargo +nightly miri test`.
|
|
|
|
3. If you have a binary project, you can run it through Miri using `cargo
|
|
|
|
+nightly miri run`.
|
2018-10-15 13:45:55 -05:00
|
|
|
|
2019-02-07 06:07:47 -06:00
|
|
|
When running code via `cargo miri`, the `miri` config flag is set. You can
|
2018-12-19 04:16:19 -06:00
|
|
|
use this to exclude test cases that will fail under Miri because they do things
|
|
|
|
Miri does not support:
|
|
|
|
|
|
|
|
```rust
|
2019-02-07 06:07:47 -06:00
|
|
|
#[cfg(not(miri))]
|
2018-12-19 04:16:19 -06:00
|
|
|
#[test]
|
|
|
|
fn does_not_work_on_miri() {
|
|
|
|
let x = 0u8;
|
|
|
|
assert!(&x as *const _ as usize % 4 < 4);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2018-10-20 11:31:15 -05:00
|
|
|
### Common Problems
|
|
|
|
|
2018-10-23 10:21:19 -05:00
|
|
|
When using the above instructions, you may encounter a number of confusing compiler
|
2018-10-20 11:31:15 -05:00
|
|
|
errors.
|
|
|
|
|
|
|
|
#### "found possibly newer version of crate `std` which `<dependency>` depends on"
|
|
|
|
|
2018-11-25 11:27:24 -06:00
|
|
|
Your build directory may contain artifacts from an earlier build that have/have
|
|
|
|
not been built for Miri. Run `cargo clean` before switching from non-Miri to
|
|
|
|
Miri builds and vice-versa.
|
2018-10-20 11:31:15 -05:00
|
|
|
|
|
|
|
#### "found crate `std` compiled by an incompatible version of rustc"
|
|
|
|
|
2018-10-23 10:21:19 -05:00
|
|
|
You may be running `cargo miri` with a different compiler version than the one
|
2018-11-25 11:27:24 -06:00
|
|
|
used to build the custom libstd that Miri uses, and Miri failed to detect that.
|
2018-11-27 04:46:09 -06:00
|
|
|
Try deleting `~/.cache/miri`.
|
2018-08-14 02:35:00 -05:00
|
|
|
|
2018-11-30 02:23:44 -06:00
|
|
|
## Development and Debugging
|
2018-10-15 02:21:29 -05:00
|
|
|
|
2018-11-30 02:23:44 -06:00
|
|
|
If you want to hack on miri yourself, great! Here are some resources you might
|
|
|
|
find useful.
|
2018-10-24 08:32:51 -05:00
|
|
|
|
2018-11-30 02:23:44 -06:00
|
|
|
### Using a nightly rustc
|
2018-10-15 02:21:29 -05:00
|
|
|
|
2019-02-05 08:03:11 -06:00
|
|
|
Miri heavily relies on internal rustc interfaces to execute MIR. Still, some
|
2018-11-30 02:23:44 -06:00
|
|
|
things (like adding support for a new intrinsic) can be done by working just on
|
2019-02-05 08:03:11 -06:00
|
|
|
the Miri side.
|
2018-11-30 02:23:44 -06:00
|
|
|
|
2019-02-05 08:03:11 -06:00
|
|
|
To prepare, make sure you are using a nightly Rust compiler. The most
|
|
|
|
convenient way is to install Miri using cargo, then you can easily run it on
|
|
|
|
other projects:
|
2018-11-30 02:23:44 -06:00
|
|
|
|
|
|
|
```sh
|
2019-02-05 08:03:11 -06:00
|
|
|
cargo +nightly install --path "$DIR" --force # or the nightly in `rust-version`
|
|
|
|
cargo +nightly miri setup
|
2018-11-30 02:23:44 -06:00
|
|
|
```
|
|
|
|
|
2019-02-05 08:03:11 -06:00
|
|
|
If you want to use a different libstd (not the one that comes with the
|
|
|
|
nightly), you can do that by running
|
2018-11-30 02:23:44 -06:00
|
|
|
|
|
|
|
```sh
|
2019-02-05 08:03:11 -06:00
|
|
|
XARGO_RUST_SRC=~/src/rust/rustc/src/ cargo +nightly miri setup
|
2018-11-30 02:23:44 -06:00
|
|
|
```
|
|
|
|
|
2019-02-05 08:03:11 -06:00
|
|
|
Either way, you can now do `cargo +nightly miri run` to run Miri with your
|
|
|
|
local changes on whatever project you are debugging.
|
|
|
|
|
|
|
|
(We are giving `+nightly` explicitly here all the time because it is important
|
|
|
|
that all of these commands get executed with the same toolchain.)
|
|
|
|
|
|
|
|
`cargo miri setup` should end in printing the directory where the libstd was
|
2019-02-05 14:35:15 -06:00
|
|
|
built. For the next step to work, set that as your `MIRI_SYSROOT` environment
|
|
|
|
variable:
|
2019-02-05 08:03:11 -06:00
|
|
|
|
|
|
|
```sh
|
|
|
|
export MIRI_SYSROOT=~/.cache/miri/HOST # or whatever the previous command said
|
|
|
|
```
|
|
|
|
|
2019-02-05 14:35:15 -06:00
|
|
|
### Testing Miri
|
|
|
|
|
|
|
|
Instead of running an entire project using `cargo miri`, you can also use the
|
|
|
|
Miri "driver" directly to run just a single file. That can be easier during
|
|
|
|
debugging.
|
2018-11-30 02:23:44 -06:00
|
|
|
|
|
|
|
```sh
|
2018-12-23 07:21:15 -06:00
|
|
|
cargo run tests/run-pass/format.rs # or whatever test you like
|
2018-11-30 02:23:44 -06:00
|
|
|
```
|
|
|
|
|
|
|
|
You can also run the test suite with `cargo test --release`. `cargo test
|
|
|
|
--release FILTER` only runs those tests that contain `FILTER` in their filename
|
|
|
|
(including the base directory, e.g. `cargo test --release fail` will run all
|
|
|
|
compile-fail tests). We recommend using `--release` to make test running take
|
|
|
|
less time.
|
|
|
|
|
|
|
|
Now you are set up! You can write a failing test case, and tweak miri until it
|
|
|
|
fails no more.
|
2018-12-23 07:21:15 -06:00
|
|
|
You can get a trace of which MIR statements are being executed by setting the
|
|
|
|
`MIRI_LOG` environment variable. For example:
|
|
|
|
|
|
|
|
```sh
|
|
|
|
MIRI_LOG=info cargo run tests/run-pass/vecs.rs
|
|
|
|
```
|
|
|
|
|
|
|
|
Setting `MIRI_LOG` like this will configure logging for miri itself as well as
|
|
|
|
the `rustc::mir::interpret` and `rustc_mir::interpret` modules in rustc. You
|
|
|
|
can also do more targeted configuration, e.g. to debug the stacked borrows
|
|
|
|
implementation:
|
|
|
|
```sh
|
|
|
|
MIRI_LOG=rustc_mir::interpret=info,miri::stacked_borrows cargo run tests/run-pass/vecs.rs
|
|
|
|
```
|
|
|
|
|
|
|
|
In addition, you can set `MIRI_BACKTRACE=1` to get a backtrace of where an
|
|
|
|
evaluation error was originally created.
|
|
|
|
|
2018-11-30 02:23:44 -06:00
|
|
|
|
|
|
|
### Using a locally built rustc
|
2018-07-15 16:17:06 -05:00
|
|
|
|
2018-08-14 02:35:00 -05:00
|
|
|
Since the heart of Miri (the main interpreter engine) lives in rustc, working on
|
2018-11-30 02:23:44 -06:00
|
|
|
Miri will often require using a locally built rustc. The bug you want to fix
|
|
|
|
may actually be on the rustc side, or you just need to get more detailed trace
|
2018-12-23 07:21:15 -06:00
|
|
|
of the execution than what is possible with release builds -- in both cases, you
|
|
|
|
should develop miri against a rustc you compiled yourself, with debug assertions
|
|
|
|
(and hence tracing) enabled.
|
2018-07-15 16:17:06 -05:00
|
|
|
|
2018-11-30 02:23:44 -06:00
|
|
|
The setup for a local rustc works as follows:
|
2018-11-09 04:48:10 -06:00
|
|
|
```sh
|
2018-07-15 16:17:06 -05:00
|
|
|
git clone https://github.com/rust-lang/rust/ rustc
|
|
|
|
cd rustc
|
|
|
|
cp config.toml.example config.toml
|
2018-11-09 04:48:10 -06:00
|
|
|
# Now edit `config.toml` and set `debug-assertions = true` and `test-miri = true`.
|
|
|
|
# The latter is important to build libstd with the right flags for miri.
|
2018-11-30 02:23:44 -06:00
|
|
|
# This step can take 30 minutes and more.
|
2018-07-15 16:17:06 -05:00
|
|
|
./x.py build src/rustc
|
2018-11-30 02:23:44 -06:00
|
|
|
# If you change something, you can get a faster rebuild by doing
|
|
|
|
./x.py --keep-stage 0 build src/rustc
|
2018-07-15 16:17:06 -05:00
|
|
|
# You may have to change the architecture in the next command
|
|
|
|
rustup toolchain link custom build/x86_64-unknown-linux-gnu/stage2
|
2018-11-30 02:23:44 -06:00
|
|
|
# Now cd to your Miri directory, then configure rustup
|
2018-07-15 16:17:06 -05:00
|
|
|
rustup override set custom
|
|
|
|
```
|
|
|
|
|
2018-11-30 02:31:09 -06:00
|
|
|
With this, you should now have a working development setup! See
|
|
|
|
["Testing Miri"](#testing-miri) above for how to proceed.
|
2018-10-31 04:16:50 -05:00
|
|
|
|
2019-02-05 14:35:15 -06:00
|
|
|
Running `cargo miri` in this setup is a bit more complicated, because the Miri
|
|
|
|
binary you just created does not actually run without some enviroment variables.
|
|
|
|
But you can contort cargo into calling `cargo miri` the right way for you:
|
|
|
|
|
|
|
|
```sh
|
|
|
|
# in some other project's directory, to run `cargo miri test`:
|
|
|
|
MIRI_SYSROOT=$(rustc +custom --print sysroot) cargo +custom run --manifest-path /path/to/miri/Cargo.toml --bin cargo-miri --release -- miri test
|
|
|
|
```
|
|
|
|
|
2018-12-12 04:03:42 -06:00
|
|
|
### Miri `-Z` flags and environment variables
|
2018-11-30 02:23:44 -06:00
|
|
|
|
2018-12-12 04:03:42 -06:00
|
|
|
Several `-Z` flags are relevant for Miri:
|
2018-11-30 02:23:44 -06:00
|
|
|
|
|
|
|
* `-Zmir-opt-level` controls how many MIR optimizations are performed. miri
|
|
|
|
overrides the default to be `0`; be advised that using any higher level can
|
|
|
|
make miri miss bugs in your program because they got optimized away.
|
|
|
|
* `-Zalways-encode-mir` makes rustc dump MIR even for completely monomorphic
|
|
|
|
functions. This is needed so that miri can execute such functions, so miri
|
|
|
|
sets this flag per default.
|
|
|
|
* `-Zmiri-disable-validation` is a custom `-Z` flag added by miri. It disables
|
|
|
|
enforcing the validity invariant, which is enforced by default. This is
|
|
|
|
mostly useful for debugging; it means miri will miss bugs in your program.
|
2018-07-15 16:17:06 -05:00
|
|
|
|
2018-12-12 04:03:42 -06:00
|
|
|
Moreover, Miri recognizes some environment variables:
|
|
|
|
|
|
|
|
* `MIRI_SYSROOT` (recognized by `miri`, `cargo miri` and the test suite)
|
|
|
|
indicates the sysroot to use.
|
|
|
|
* `MIRI_TARGET` (recognized by the test suite) indicates which target
|
|
|
|
architecture to test against. `miri` and `cargo miri` accept the `--target`
|
|
|
|
flag for the same purpose.
|
|
|
|
|
2016-06-19 01:04:11 -05:00
|
|
|
## Contributing and getting help
|
2016-04-14 03:21:32 -05:00
|
|
|
|
2016-06-19 01:04:11 -05:00
|
|
|
Check out the issues on this GitHub repository for some ideas. There's lots that
|
|
|
|
needs to be done that I haven't documented in the issues yet, however. For more
|
2018-11-30 15:23:20 -06:00
|
|
|
ideas or help with running or hacking on Miri, you can open an issue here on
|
|
|
|
GitHub or contact us (`oli-obk` and `RalfJ`) on the [Rust Zulip].
|
|
|
|
|
|
|
|
[Rust Zulip]: https://rust-lang.zulipchat.com
|
2016-02-02 04:47:28 -06:00
|
|
|
|
2018-11-13 07:16:08 -06:00
|
|
|
## History
|
|
|
|
|
|
|
|
This project began as part of an undergraduate research course in 2015 by
|
2018-11-14 01:23:43 -06:00
|
|
|
@solson at the [University of Saskatchewan][usask]. There are [slides] and a
|
|
|
|
[report] available from that project. In 2016, @oli-obk joined to prepare miri
|
|
|
|
for eventually being used as const evaluator in the Rust compiler itself
|
|
|
|
(basically, for `const` and `static` stuff), replacing the old evaluator that
|
|
|
|
worked directly on the AST. In 2017, @RalfJung did an internship with Mozilla
|
|
|
|
and began developing miri towards a tool for detecting undefined behavior, and
|
|
|
|
also using miri as a way to explore the consequences of various possible
|
|
|
|
definitions for undefined behavior in Rust. @oli-obk's move of the miri engine
|
|
|
|
into the compiler finally came to completion in early 2018. Meanwhile, later
|
|
|
|
that year, @RalfJung did a second internship, developing miri further with
|
|
|
|
support for checking basic type invariants and verifying that references are
|
|
|
|
used according to their aliasing restrictions.
|
2018-11-13 07:16:08 -06:00
|
|
|
|
|
|
|
[usask]: https://www.usask.ca/
|
2018-11-14 01:23:43 -06:00
|
|
|
[slides]: https://solson.me/miri-slides.pdf
|
|
|
|
[report]: https://solson.me/miri-report.pdf
|
2018-11-13 07:16:08 -06:00
|
|
|
|
2016-02-02 04:47:28 -06:00
|
|
|
## License
|
|
|
|
|
|
|
|
Licensed under either of
|
|
|
|
* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0)
|
|
|
|
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
|
|
|
http://opensource.org/licenses/MIT) at your option.
|
|
|
|
|
|
|
|
### Contribution
|
|
|
|
|
|
|
|
Unless you explicitly state otherwise, any contribution intentionally submitted
|
|
|
|
for inclusion in the work by you shall be dual licensed as above, without any
|
|
|
|
additional terms or conditions.
|