An interpreter for Rust's mid-level intermediate representation

Related tags

Security tools miri
Overview

Miri

Actions build status

An experimental interpreter for Rust's mid-level intermediate representation (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 some basic type invariants (a bool that is not 0 or 1, for example, or an invalid enum discriminant)
  • Experimental: Violations of the Stacked Borrows rules governing aliasing for reference types
  • Experimental: Data races (but no weak memory effects)

On top of that, Miri will also tell you about memory leaks: when there is memory still allocated at the end of the execution, and that memory is not reachable from a global static, Miri will raise an error.

You can use Miri to emulate programs on other targets, e.g. to ensure that byte-level data manipulation works correctly both on little-endian and big-endian systems. See cross-interpretation below.

Miri has already discovered some real-world bugs. If you found a bug with Miri, we'd appreciate if you tell us and we'll add it to the list!

However, be aware that Miri will not catch all cases of undefined behavior in your program, and cannot run all programs:

  • There are still plenty of open questions around the basic invariants for some types and when these invariants even have to hold. Miri tries to avoid false positives here, so if your program runs fine in Miri right now that is by no means a guarantee that it is UB-free when these questions get answered.

    In particular, Miri does currently not check that integers/floats are initialized or that references point to valid data.

  • If the program relies on unspecified details of how data is laid out, it will still run fine in Miri -- but might break (including causing UB) on different compiler versions or different platforms.

  • Program execution is non-deterministic when it depends, for example, on where exactly in memory allocations end up, or on the exact interleaving of concurrent threads. Miri tests one of many possible executions of your program. You can alleviate this to some extent by running Miri with different values for -Zmiri-seed, but that will still by far not explore all possible executions.

  • Miri runs the program as a platform-independent interpreter, so the program has no access to most platform-specific APIs or FFI. A few APIs have been implemented (such as printing to stdout) but most have not: for example, Miri currently does not support SIMD or networking.

  • Threading support is not finished yet. E.g., weak memory effects are not emulated and spin loops (without syscalls) just loop forever. There is no threading support on Windows.

Using Miri

Install Miri on Rust nightly via rustup:

rustup +nightly component add miri

If rustup says the miri component is unavailable, that's because not all nightly releases come with all tools. Check out this website to determine a nightly version that comes with Miri and install that using rustup toolchain install nightly-YYYY-MM-DD. Either way, all of the following commands assume the right toolchain is pinned via rustup override set nightly or rustup override set nightly-YYYY-MM-DD. (Alternatively, use cargo +nightly/cargo +nightly-YYYY-MM-DD for each of the following commands.)

Now you can run your project in Miri:

  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 miri test.
  3. If you have a binary project, you can run it through Miri using cargo miri run.

The first time you run Miri, it will perform some extra setup and install some dependencies. It will ask you for confirmation before installing anything.

cargo miri run/test supports the exact same flags as cargo run/test. For example, cargo miri test filter only runs the tests containing filter in their name.

You can pass arguments to Miri via MIRIFLAGS. For example, MIRIFLAGS="-Zmiri-disable-stacked-borrows" cargo miri run runs the program without checking the aliasing of references.

When compiling code via cargo miri, the cfg(miri) config flag is set for code that will be interpret under Miri. You can use this to ignore test cases that fail under Miri because they do things Miri does not support:

#[test]
#[cfg_attr(miri, ignore)]
fn does_not_work_on_miri() {
    tokio::run(futures::future::ok::<_, ()>(()));
}

There is no way to list all the infinite things Miri cannot do, but the interpreter will explicitly tell you when it finds something unsupported:

error: unsupported operation: can't call foreign function: bind
    ...
    = help: this is likely not a bug in the program; it indicates that the program \
            performed an operation that the interpreter does not support

Cross-interpretation: running for different targets

Miri can not only run a binary or test suite for your host target, it can also perform cross-interpretation for arbitrary foreign targets: cargo miri run --target x86_64-unknown-linux-gnu will run your program as if it was a Linux program, no matter your host OS. This is particularly useful if you are using Windows, as the Linux target is much better supported than Windows targets.

You can also use this to test platforms with different properties than your host platform. For example cargo miri test --target mips64-unknown-linux-gnuabi64 will run your test suite on a big-endian target, which is useful for testing endian-sensitive code.

Running Miri on CI

To run Miri on CI, make sure that you handle the case where the latest nightly does not ship the Miri component because it currently does not build. For example, you can use the following snippet to always test with the latest nightly that does come with Miri:

MIRI_NIGHTLY=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri)
echo "Installing latest nightly with Miri: $MIRI_NIGHTLY"
rustup set profile minimal
rustup override set "$MIRI_NIGHTLY"
rustup component add miri

cargo miri test

Common Problems

When using the above instructions, you may encounter a number of confusing compiler errors.

"note: run with RUST_BACKTRACE=1 environment variable to display a backtrace"

You may see this when trying to get Miri to display a backtrace. By default, Miri doesn't expose any environment to the program, so running RUST_BACKTRACE=1 cargo miri test will not do what you expect.

To get a backtrace, you need to disable isolation using -Zmiri-disable-isolation:

RUST_BACKTRACE=1 MIRIFLAGS="-Zmiri-disable-isolation" cargo miri test

"found possibly newer version of crate std which <dependency> depends on"

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.

"found crate std compiled by an incompatible version of rustc"

You may be running cargo miri with a different compiler version than the one used to build the custom libstd that Miri uses, and Miri failed to detect that. Try deleting ~/.cache/miri.

"no mir for std::rt::lang_start_internal"

This means the sysroot you are using was not compiled with Miri in mind. This should never happen when you use cargo miri because that takes care of setting up the sysroot. If you are using miri (the Miri driver) directly, see the contributors' guide for how to use ./miri to best do that.

Miri -Z flags and environment variables

Miri adds its own set of -Z flags, which are usually set via the MIRIFLAGS environment variable:

  • -Zmiri-check-number-validity enables checking of integer and float validity (e.g., they must be initialized and not carry pointer provenance) as part of enforcing validity invariants. This has no effect when -Zmiri-disable-validation is present.
  • -Zmiri-compare-exchange-weak-failure-rate=<rate> changes the failure rate of compare_exchange_weak operations. The default is 0.8 (so 4 out of 5 weak ops will fail). You can change it to any value between 0.0 and 1.0, where 1.0 means it will always fail and 0.0 means it will never fail.
  • -Zmiri-disable-abi-check disables checking function ABI. Using this flag is unsound.
  • -Zmiri-disable-alignment-check disables checking pointer alignment, so you can focus on other failures, but it means Miri can miss bugs in your program. Using this flag is unsound.
  • -Zmiri-disable-data-race-detector disables checking for data races. Using this flag is unsound.
  • -Zmiri-disable-stacked-borrows disables checking the experimental Stacked Borrows aliasing rules. This can make Miri run faster, but it also means no aliasing violations will be detected. Using this flag is unsound (but the affected soundness rules are experimental).
  • -Zmiri-disable-validation disables enforcing validity invariants, which are enforced by default. This is mostly useful to focus on other failures (such as out-of-bounds accesses) first. Setting this flag means Miri can miss bugs in your program. However, this can also help to make Miri run faster. Using this flag is unsound.
  • -Zmiri-disable-isolation disables host isolation. As a consequence, the program has access to host resources such as environment variables, file systems, and randomness.
  • -Zmiri-isolation-error=<action> configures Miri's response to operations requiring host access while isolation is enabled. abort, hide, warn, and warn-nobacktrace are the supported actions. The default is to abort, which halts the machine. Some (but not all) operations also support continuing execution with a "permission denied" error being returned to the program. warn prints a full backtrace when that happen; warn-nobacktrace is less verbose. hide hides the warning entirely.
  • -Zmiri-env-exclude=<var> keeps the var environment variable isolated from the host so that it cannot be accessed by the program. Can be used multiple times to exclude several variables. On Windows, the TERM environment variable is excluded by default.
  • -Zmiri-ignore-leaks disables the memory leak checker, and also allows some remaining threads to exist when the main thread exits.
  • -Zmiri-measureme=<name> enables measureme profiling for the interpreted program. This can be used to find which parts of your program are executing slowly under Miri. The profile is written out to a file with the prefix <name>, and can be processed using the tools in the repository https://github.com/rust-lang/measureme.
  • -Zmiri-panic-on-unsupported will makes some forms of unsupported functionality, such as FFI and unsupported syscalls, panic within the context of the emulated application instead of raising an error within the context of Miri (and halting execution). Note that code might not expect these operations to ever panic, so this flag can lead to strange (mis)behavior.
  • -Zmiri-seed=<hex> configures the seed of the RNG that Miri uses to resolve non-determinism. This RNG is used to pick base addresses for allocations. When isolation is enabled (the default), this is also used to emulate system entropy. The default seed is 0. NOTE: This entropy is not good enough for cryptographic use! Do not generate secret keys in Miri or perform other kinds of cryptographic operations that rely on proper random numbers.
  • -Zmiri-symbolic-alignment-check makes the alignment check more strict. By default, alignment is checked by casting the pointer to an integer, and making sure that is a multiple of the alignment. This can lead to cases where a program passes the alignment check by pure chance, because things "happened to be" sufficiently aligned -- there is no UB in this execution but there would be UB in others. To avoid such cases, the symbolic alignment check only takes into account the requested alignment of the relevant allocation, and the offset into that allocation. This avoids missing such bugs, but it also incurs some false positives when the code does manual integer arithmetic to ensure alignment. (The standard library align_to method works fine in both modes; under symbolic alignment it only fills the middle slice when the allocation guarantees sufficient alignment.)
  • -Zmiri-track-alloc-id=<id> shows a backtrace when the given allocation is being allocated or freed. This helps in debugging memory leaks and use after free bugs.
  • -Zmiri-track-call-id=<id> shows a backtrace when the given call id is assigned to a stack frame. This helps in debugging UB related to Stacked Borrows "protectors".
  • -Zmiri-track-pointer-tag=<tag> shows a backtrace when the given pointer tag is popped from a borrow stack (which is where the tag becomes invalid and any future use of it will error). This helps you in finding out why UB is happening and where in your code would be a good place to look for it.
  • -Zmiri-tag-raw-pointers makes Stacked Borrows assign proper tags even for raw pointers. This can make valid code using int-to-ptr casts fail to pass the checks, but also can help identify latent aliasing issues in code that Miri accepts by default. You can recognize false positives by <untagged> occurring in the message -- this indicates a pointer that was cast from an integer, so Miri was unable to track this pointer. Note that it is not currently guaranteed that code that works with -Zmiri-tag-raw-pointers also works without -Zmiri-tag-raw-pointers, but for the vast majority of code, this will be the case.

Some native rustc -Z flags are also very relevant for Miri:

  • -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.
  • -Zmir-emit-retag controls whether Retag statements are emitted. Miri enables this per default because it is needed for Stacked Borrows.

Moreover, Miri recognizes some environment variables:

  • MIRI_LOG, MIRI_BACKTRACE control logging and backtrace printing during Miri executions, also see "Testing the Miri driver" in CONTRIBUTING.md.
  • MIRIFLAGS (recognized by cargo miri and the test suite) defines extra flags to be passed to Miri.
  • MIRI_LIB_SRC defines the directory where Miri expects the sources of the standard library that it will build and use for interpretation. This directory must point to the library subdirectory of a rust-lang/rust repository checkout. Note that changing files in that directory does not automatically trigger a re-build of the standard library; you have to clear the Miri build cache manually (on Linux, rm -rf ~/.cache/miri).
  • MIRI_SYSROOT (recognized by cargo miri and the test suite) indicates the sysroot to use. To do the same thing with miri directly, use the --sysroot flag.
  • MIRI_TEST_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.

The following environment variables are internal and must not be used by anyone but Miri itself. They are used to communicate between different Miri binaries, and as such worth documenting:

  • MIRI_BE_RUSTC can be set to host or target. It tells the Miri driver to actually not interpret the code but compile it like rustc would. With target, Miri sets some compiler flags to prepare the code for interpretation; with host, this is not done. This environment variable is useful to be sure that the compiled rlibs are compatible with Miri.
  • MIRI_CALLED_FROM_XARGO is set during the Miri-induced xargo sysroot build, which will re-invoke cargo-miri as the rustc to use for this build.
  • MIRI_CALLED_FROM_RUSTDOC when set to any value tells cargo-miri that it is running as a child process of rustdoc, which invokes it twice for each doc-test and requires special treatment, most notably a check-only build before interpretation. This is set by cargo-miri itself when running as a rustdoc-wrapper.
  • MIRI_CWD when set to any value tells the Miri driver to change to the given directory after loading all the source files, but before commencing interpretation. This is useful if the interpreted program wants a different working directory at run-time than at build-time.
  • MIRI_VERBOSE when set to any value tells the various cargo-miri phases to perform verbose logging.

Miri extern functions

Miri provides some extern functions that programs can import to access Miri-specific functionality:

#[cfg(miri)]
extern "Rust" {
    /// Miri-provided extern function to mark the block `ptr` points to as a "root"
    /// for some static memory. This memory and everything reachable by it is not
    /// considered leaking even if it still exists when the program terminates.
    ///
    /// `ptr` has to point to the beginning of an allocated block.
    fn miri_static_root(ptr: *const u8);

    /// Miri-provided extern function to obtain a backtrace of the current call stack.
    /// This returns a boxed slice of pointers - each pointer is an opaque value
    /// that is only useful when passed to `miri_resolve_frame`
    /// The `flags` argument must be `0`.
    fn miri_get_backtrace(flags: u64) -> Box<[*mut ()]>;

    /// Miri-provided extern function to resolve a frame pointer obtained
    /// from `miri_get_backtrace`. The `flags` argument must be `0`,
    /// and `MiriFrame` should be declared as follows:
    ///
    /// ```rust
    /// #[repr(C)]
    /// struct MiriFrame {
    ///     // The name of the function being executed, encoded in UTF-8
    ///     name: Box<[u8]>,
    ///     // The filename of the function being executed, encoded in UTF-8
    ///     filename: Box<[u8]>,
    ///     // The line number currently being executed in `filename`, starting from '1'.
    ///     lineno: u32,
    ///     // The column number currently being executed in `filename`, starting from '1'.
    ///     colno: u32,
    ///     // The function pointer to the function currently being executed.
    ///     // This can be compared against function pointers obtained by
    ///     // casting a function (e.g. `my_fn as *mut ()`)
    ///     fn_ptr: *mut ()
    /// }
    /// ```
    ///
    /// The fields must be declared in exactly the same order as they appear in `MiriFrame` above.
    /// This function can be called on any thread (not just the one which obtained `frame`).
    fn miri_resolve_frame(frame: *mut (), flags: u64) -> MiriFrame;

    /// Miri-provided extern function to begin unwinding with the given payload.
    ///
    /// This is internal and unstable and should not be used; we give it here
    /// just to be complete.
    fn miri_start_panic(payload: *mut u8) -> !;
}

Contributing and getting help

If you want to contribute to Miri, great! Please check out our contribution guide.

For help with running Miri, you can open an issue here on GitHub or use the Miri stream on the Rust Zulip.

History

This project began as part of an undergraduate research course in 2015 by @solson at the University of Saskatchewan. 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.

Bugs found by Miri

Miri has already found a number of bugs in the Rust standard library and beyond, which we collect here.

Definite bugs found:

Violations of Stacked Borrows found that are likely bugs (but Stacked Borrows is currently just an experiment):

License

Licensed under either of

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.

Comments
  • Support unwinding after a panic

    Support unwinding after a panic

    Fixes #658

    This commit adds support for unwinding after a panic. It requires a companion rustc PR to be merged, in order for the necessary hooks to work properly.

    Currently implemented:

    • Selecting between unwind/abort mode based on the rustc Session
    • Properly popping off stack frames, unwinding back the caller
    • Running 'unwind' blocks in Mir terminators

    Not yet implemented:

    • 'Abort' terminators

    This PR was getting fairly large, so I decided to open it for review without implementing 'Abort' terminator support. This could either be added on to this PR, or merged separately.

    I've a test to exercise several different aspects of unwind panicking. Ideally, we would run Miri against the libstd panic tests, but I haven't yet figured out how to do that.

    This depends on https://github.com/rust-lang/rust/pull/60026

    S-blocked-on-rust S-waiting-on-author 
    opened by Aaron1011 56
  • Print spans where tags are created and invalidated

    Print spans where tags are created and invalidated

    5225225 called this "automatic tag tracking" and I think that may be a reasonable description, but I would like to kill tag tracking as a primary use of Miri if possible. Tag tracking isn't always possible; for example if the UB is only detected with isolation off and the failing tag is made unstable by removing isolation. (also it's bad UX to run the tool twice)

    This is just one of the things we can do with https://github.com/rust-lang/miri/pull/2024

    The memory usage of this is shockingly low, I think because the memory usage of Miri is driven by allocations where each byte ends up with its own very large stack. The memory usage in this change is linear with the number of tags, not tags * bytes. If memory usage gets out of control we can cap the number of events we save per allocation, from experience we tend to only use the most recent few in diagnostics but of course there's no guarantee of that so if we can manage to keep everything that would be best.

    In many cases now I can tell exactly what these codebases are doing wrong just from the new outputs here, which I think is extremely cool.

    New helps generated with plain old cargo miri test on rust-argon2 v1.0.0:

    test argon2::tests::single_thread_verification_multi_lane_hash ... error: Undefined Behavior: trying to reborrow <1485898> for Unique permission at alloc110523[0x0], but that tag does not exist in the borrow stack for this location
       --> /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/core/src/mem/manually_drop.rs:89:9
        |
    89  |         slot.value
        |         ^^^^^^^^^^
        |         |
        |         trying to reborrow <1485898> for Unique permission at alloc110523[0x0], but that tag does not exist in the borrow stack for this location
        |         this error occurs as part of a reborrow at alloc110523[0x0..0x20]
        |
        = help: this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental
        = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
    help: <1485898> was created by a retag at offsets [0x0..0x20]
       --> src/memory.rs:42:13
        |
    42  |             vec.push(unsafe { &mut (*ptr) });
        |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    help: <1485898> was later invalidated at offsets [0x0..0x20]
       --> src/memory.rs:42:31
        |
    42  |             vec.push(unsafe { &mut (*ptr) });
        |                               ^^^^^^^^^^^
    

    And with -Zmiri-tag-raw-pointers on slab v0.4.5

    error: Undefined Behavior: trying to reborrow <2915> for Unique permission at alloc1418[0x0], but that tag does not exist in the borrow stack for this location
       --> /tmp/slab-0.4.5/src/lib.rs:835:16
        |
    835 |         match (&mut *ptr1, &mut *ptr2) {
        |                ^^^^^^^^^^
        |                |
        |                trying to reborrow <2915> for Unique permission at alloc1418[0x0], but that tag does not exist in the borrow stack for this location
        |                this error occurs as part of a reborrow at alloc1418[0x0..0x10]
        |
        = help: this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental
        = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
    help: <2915> was created by a retag at offsets [0x0..0x10]
       --> /tmp/slab-0.4.5/src/lib.rs:833:20
        |
    833 |         let ptr1 = self.entries.get_unchecked_mut(key1) as *mut Entry<T>;
        |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    help: <2915> was later invalidated at offsets [0x0..0x20]
       --> /tmp/slab-0.4.5/src/lib.rs:834:20
        |
    834 |         let ptr2 = self.entries.get_unchecked_mut(key2) as *mut Entry<T>;
        |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    

    And without raw pointer tagging, cargo miri test on half v1.8.2

    error: Undefined Behavior: trying to reborrow <untagged> for Unique permission at alloc1340[0x0], but that tag only grants SharedReadOnly permission for this location
       --> /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/core/src/slice/raw.rs:141:9
        |
    141 |         &mut *ptr::slice_from_raw_parts_mut(data, len)
        |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        |         |
        |         trying to reborrow <untagged> for Unique permission at alloc1340[0x0], but that tag only grants SharedReadOnly permission for this location
        |         this error occurs as part of a reborrow at alloc1340[0x0..0x6]
        |
        = help: this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental
        = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
    help: tag was most recently created at offsets [0x0..0x6]
       --> /tmp/half-1.8.2/src/slice.rs:309:22
        |
    309 |         let length = self.len();
        |                      ^^^^^^^^^^
    help: this tag was also created here at offsets [0x0..0x6]
       --> /tmp/half-1.8.2/src/slice.rs:308:23
        |
    308 |         let pointer = self.as_ptr() as *mut u16;
        |                       ^^^^^^^^^^^^^
    

    The second suggestion is close to guesswork, but from experience it tends to be correct (as in, it tends to locate the pointer the user wanted) more often that it doesn't.

    opened by saethlin 47
  • `_mm_movemask_epi8` unexpectedly triggers Undefined Behavior

    `_mm_movemask_epi8` unexpectedly triggers Undefined Behavior

    playground

    use core::arch::x86_64::*;
    
    #[target_feature(enable = "sse2")]
    pub unsafe fn is_ascii_sse2(a: &[u8; 16]) -> bool {
        let a = _mm_loadu_si128(a.as_ptr().cast());
        let m = _mm_movemask_epi8(a);
        m == 0
    }
    
    fn main() {
        assert!(cfg!(target_feature = "sse2"));
        let s = b"helloworld123456";
        assert!(unsafe { is_ascii_sse2(s) });
    }
    
    error: Undefined Behavior: each element of a SIMD mask must be all-0-bits or all-1-bits
        --> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/../../stdarch/crates/core_arch/src/x86/sse2.rs:1381:5
         |
    1381 |     simd_bitmask::<_, u16>(a.as_i8x16()) as u32 as i32
         |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ each element of a SIMD mask must be all-0-bits or all-1-bits
         |
         = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
         = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
         = note: BACKTRACE:
         = note: inside `std::arch::x86_64::_mm_movemask_epi8` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/../../stdarch/crates/core_arch/src/x86/sse2.rs:1381:5
    note: inside `is_ascii_sse2` at src/main.rs:6:13
    

    See also:

    opened by Nugine 42
  • Adding support for external C functions that have integer (or empty) args and/or returns

    Adding support for external C functions that have integer (or empty) args and/or returns

    Starts addressing @https://github.com/rust-lang/miri/issues/11

    Implementation

    Adding support for calling external C functions that have any number of integer arguments (types of integers: i8, i16, i32, i64, u8, u16, u32, u64) and an integer return type (or void). As suggested in @https://github.com/rust-lang/miri/issues/11, the libffi crate is used to dispatch the calls to external C functions.

    Modifications

    Main modifications are to:

    • helper.rs : adding a function call_and_add_external_c_fct_to_context to read the code pointer to the external C function, dispatch the call, and save the return in MIRI internal memory. Handles all conversions between MIRI and C values (using some macros, also defined in this file).
    • foreign_items.rs : handles the calling of call_and_add_external_c_fct_to_context in helper.rs when a foreign item is encountered. Also adds some structs to model C representations of arguments, and the signature of the external C call.

    Testing

    Adds tests for the following external functions which are now supported:

    • int tests:
      • adds 2 to a provided int (no type of int specified, so autocasts)
      • takes the sum of its 12 arguments (tests stack spill)
      • adds 3 to a 16 bit int
      • adds an i16 to an i64
      • returns -10 as an unsigned int
    • void tests
      • void function that prints from C

    Code review

    The code in this PR was reviewed by @maurer on another fork -- thanks!

    S-waiting-on-author 
    opened by emarteca 41
  • Redo cargo-miri logic

    Redo cargo-miri logic

    This rewrite the cargo-miri logic for running the requested crate(s) following what we outlined in https://github.com/rust-lang/miri/issues/739: cargo miri run/test $FLAGS (almost) literally invokes cargo run/test $FLAGS but with some environment variables set so that we can control what happens:

    • RUSTC_WRAPPER is set so that we get invoked instead of rustc. We use that power to mess with the flags being used for the build (things to be interpreted by Miri use a different sysroot), and when we are detecting a binary crate meant to be run by Miri, we grab the info we care about and put it into a JSON file for later use.
    • CARGO_TARGET_$TARGET_RUNNER is set so what we get invoked when cargo wants to run a binary. At that point we take that JSON info from before and use it to invoke Miri.

    Overall this works great! We get all sorts of cargo magic for free, and do not even need cargo-metadata any more. There's one annoying point though, which I have not managed to entirely work around yet: this means we are doing a full build, not just a check-build. Given that our sysroot is MIR-only, I was surprised that this even worked, but still -- this means we are doing more work than we should. So I also added some patching of arguments to make sure --emit does not contain link, and then more patching was required of the --extern flags for the binary because those referenced the .rlib files but now only .rmeta exists, and that is still not fully working because cargo seems to expect those .rmeta files and now triggers a rebuild each time as those files are still missing. My current plan is to make our wrapper create some empty dummy files with the right names, but the amount of hacks we are stacking on top of each other here is getting worrysome.^^ @ehuss your input would be welcome on this issue.

    Due to re-using cargo more literally, this also changes flag parsing to match cargo. So -Zmiri flags now have to be passed via an environment variable (Cc https://github.com/rust-lang/miri/issues/1416).

    This PR is not ready yet, but the parts that are there I think can be reviewed already. TODO:

    • [x] Fix Windows.
    • [x] Figure out how we can do check-only builds without the rebuild problem above. ~~I am also worried about cases where build.rs script might detect check-only builds and then do less work; I think some crates in rustc are doing that and if this is a thing in the wider ecosystem we need to find a way to support this as well.~~ (postponed that until we have a concrete example)
    • [x] Currently cargo runs doctests as well, and they are not run in Miri. We should at least figure out a way to not run them at all (resolving https://github.com/rust-lang/miri/issues/584 is left for a future PR).
    • [x] For some time, detect the old way of passing -Zmiri flags and warn that this will need updating. For some simple situations we can probably make it still support the old way, but I plan to remove those hacks after a bit. This is just to give people and me time to go around and send PRs to all projects that use Miri on CI, and update their use of the flags.
    • [x] Add a test for stdin handling (https://github.com/rust-lang/miri/issues/1505). This should work now but we should be sure.
    • [x] Add a test for cargo env vars (https://github.com/rust-lang/miri/issues/1515).
    • [x] Check if https://github.com/rust-lang/miri/issues/1516 is resolved.
    • [x] Check if https://github.com/rust-lang/miri/issues/1001 and https://github.com/rust-lang/miri/issues/1514 are resolved.
    • [x] Check if https://github.com/rust-lang/miri/issues/1312 is resolved (not sure if it is wort adding a test).
    • [x] Check if https://github.com/rust-lang/miri/issues/1512 is resolved (not sure if it is wort adding a test).

    Fixes https://github.com/rust-lang/miri/issues/700. Fixes https://github.com/rust-lang/miri/issues/739. Fixes https://github.com/rust-lang/miri/issues/1001. Fixes https://github.com/rust-lang/miri/issues/1312 (without a test, as we run without cargo's stdin/stdout wrapping now, as the test for stdin confirms). Fixes https://github.com/rust-lang/miri/issues/1416. Fixes https://github.com/rust-lang/miri/issues/1505. Fixes https://github.com/rust-lang/miri/issues/1512 (without a test, as cargo now does all that handling anyway, which various other tests confirm). Fixes https://github.com/rust-lang/miri/issues/1514. Fixes https://github.com/rust-lang/miri/issues/1516.

    Cc @alecmocatta who reported many of the bugs above; would be great if you could help with the tests e.g. by providing some small examples I could try. r? @oli-obk

    A-cargo 
    opened by RalfJung 41
  • Handle ZST pointer alignment properly

    Handle ZST pointer alignment properly

    Rust nowadays uses align as *const _ for ZST pointers. The reason for this is that some ZSTs do care about their alignment, namely, empty arrays inherit the alignment of their element type: [i32; 0] must be 4-aligned. Using, e.g., a pointer to () as a pointer to [i32; 0] is not, in general, valid.

    Miri currently treats all ZST pointers equal, so it does not properly detect this.

    I suggest to fix this by getting rid of the ZST allocation and doing what rustc does: Using the alignment cast to a pointer. If you agree, I'd be happy to implement this.

    opened by RalfJung 41
  • Get rid of integer allocation

    Get rid of integer allocation

    @eddyb mentioned that there are plans to get rid of the integer allocation (NEVER_ALLOC_ID). This is an attempt to summarize briefly what the plan is, and to document that such a plan exists. (I suppose the "refactor" label would make sense here?)

    The idea is to change the "meaning" of the type Pointer to "pointers that actually point somewhere in memory". Every operation that also works on pointers obtained from integers should use a different type. They could either use PrimVal (but then these methods all have to handle undef...), or a new type that factors the Pointer and Bytes cases out of PrimVal, but cannot be Undef.

    ptr-to-int-cast and their inverse literally become a noop on the data side. There is no longer any need to perform "normalization" in binary_op because all data now has a canonical representation. (The memory already does something like this, somewhat, by not adding any relocations when a pointer from the integer allocation is written to memory.)

    Open questions:

    • What about zero-sized types? We could either keep the ZST allocation, or make allocation return an integer when a ZST is allocated.
    • Which name should the type that's either Pointer or just bytes have? PrimDefVal? I'm not good with names...
    C-enhancement 
    opened by RalfJung 41
  • Weak memory emulation using store buffers

    Weak memory emulation using store buffers

    This implements the second half of the Lidbury & Donaldson paper: weak memory emulation using store buffers. A store buffer is created over a memory range on atomic access. Stores will push store elements into the buffer and loads will search through the buffer in reverse modification order, determine which store elements are valid for the current load, and pick one randomly.

    This implementation will never generate weak memory behaviours forbidden by the C++11 model, but it is incapable of producing all possible weak behaviours allowed by the model. There are certain weak behaviours observable on real hardware but not while using this.

    Note that this implementation does not take into account of C++20's memory model revision to SC accesses and fences introduced by P0668. This implementation is not fully correct under the revised C++20 model and may generate behaviours C++20 disallows.

    Rust follows the C++20 memory model (except for the Consume ordering and some operations not performable through C++'s std::atomic API). It is therefore possible for this implementation to generate behaviours never observable when the same program is compiled and run natively. Unfortunately, no literature exists at the time of writing which proposes an implementable and C++20-compatible relaxed memory model that supports all atomic operation existing in Rust. The closest one is A Promising Semantics for Relaxed-Memory Concurrency by Jeehoon Kang et al. However, this model lacks SC accesses and is therefore unusable by Miri (SC accesses are everywhere in library code).

    Safe/sound Rust allows for more operations on atomic locations than the C++20 atomic API was intended to allow, such as non-atomically accessing a previously atomically accessed location, or accessing previously atomically accessed locations with a differently sized operation (such as accessing the top 16 bits of an AtomicU32). These scenarios are generally left undefined in formalisations of C++ memory model, even though they became possible in C++20 with std::atomic_ref<T>. In Rust, these operations can only be done through a &mut AtomicFoo reference or one derived from it, therefore these operations can only happen after all previous accesses on the same locations. This implementation is adapted to accommodate these.


    TODOs:

    • [x] Add tests cases that actually demonstrate weak memory behaviour (even if they are scheduler dependent)
    • [x] Change {mutex, rwlock, cond, srwlock}_get_or_create_id functions under src/shims to use atomic RMWs instead of separate read -> check if need to create a new one -> write steps
    • [x] Make sure Crossbeam tests still pass (https://github.com/crossbeam-rs/crossbeam/pull/831)
    • [x] Move as much weak-memory related code as possible into weak_memory.rs
    • [x] Remove "weak memory effects are not emulated" warnings
    • [x] Accommodate certain mixed size and mixed atomicity accesses Rust allows on top of the C++ model
    opened by cbeuw 40
  • implement intptrcast model

    implement intptrcast model

    Since right now miri's pointer comparison bails out on &x as *const T < &y as *const T but allows &x as *const T == &y as *const T, I suggest to also allow <. This will not impact ctfe-mode, since ctfe mode disallows any binary ops on pointers into different allocs, even ==.

    It's deterministic between multiple miri runs, doesn't leak HashMap ordering and only depends on optimizations and codegen from rustc (but that's already true for ==).

    Steps to do:

    • [x] Implement force_bits, force_int and basic address assignment.
    • [x] force_bits when doing primitive operations.
    • [x] force_bits when doing casts.
    • [x] force_ptr when creating a non-ZST reference. (Ideally through check_ptr_access? Redundant with validity checks but whatever.) We may need a force_ptr_place method or so; the freeze-sensitive visitor also needs that.
    • [x] Make force_bits infallible (in Miri, not CTFE) -- see https://github.com/rust-lang/miri/issues/841.
    • [ ] ~~force_bits when doing partial loads of a pointer -- and really everywhere we need a ptr, once it is total. (For now let's not do this, also see https://github.com/rust-lang/rust/issues/69488 for a similar problem around partially initialized data.)~~
    • [x] Exploit "real" pointer alignment for alignment checks, but warn when we do. (But also see https://github.com/rust-lang/rust/issues/62420.)
    • [x] Ptr-to-int of a dangling pointer (possible in safe code).
    • [x] Fix the FIXMEs added in https://github.com/rust-lang/miri/pull/803.
    • [x] Audit all remaining uses of to_bits (this includes the to_<int type> methods...), to_ptr and to_bits_or_ptr, all uses of is_ptr and is_bits, and also all uses of force_ptr and force_mplace_ptr (also mplace_access_checked, check_mplace_access) outside of check_ptr_access. Maybe replace to_{bits,ptr} by assert_{bits,ptr}?
    C-project A-engine A-intptrcast 
    opened by oli-obk 40
  • Add file sync shims

    Add file sync shims

    This PR adds shim implementations for these related file syncing functions.

    • fsync, for POSIX targets, backed by File::sync_all()
    • fdatasync, for POSIX targets, backed by File::sync_data()
    • fcntl with command F_FULLFSYNC, for macOS targets, backed by File::sync_all()
    • sync_file_range, for Linux targets, backed by File::sync_data()
    opened by divergentdave 39
  • Optimizing Stacked Borrows (part 1?): Cache locations of Tags in a Borrow Stack

    Optimizing Stacked Borrows (part 1?): Cache locations of Tags in a Borrow Stack

    Before this PR, a profile of Miri under almost any workload points quite squarely at these regions of code as being incredibly hot (each being ~40% of cycles):

    https://github.com/rust-lang/miri/blob/dadcbebfbd017aac2358cf652a4bd71a91694edc/src/stacked_borrows.rs#L259-L269

    https://github.com/rust-lang/miri/blob/dadcbebfbd017aac2358cf652a4bd71a91694edc/src/stacked_borrows.rs#L362-L369

    This code is one of at least three reasons that stacked borrows analysis is super-linear: These are both linear in the number of borrows in the stack and they are positioned along the most commonly-taken paths.

    I'm addressing the first loop (which is in Stack::find_granting) by adding a very very simple sort of LRU cache implemented on a VecDeque, which maps recently-looked-up tags to their position in the stack. For Untagged access we fall back to the same sort of linear search. But as far as I can tell there are never enough Untagged items to be significant.

    I'm addressing the second loop by keeping track of the region of stack where there could be items granting Permission::Unique. This optimization is incredibly effective because Read access tends to dominate and many trips through this code path now skip the loop entirely.

    These optimizations result in pretty enormous improvements: Without raw pointer tagging, mse 34.5s -> 2.4s, serde1 5.6s -> 3.6s With raw pointer tagging, mse 35.3s -> 2.4s, serde1 5.7s -> 3.6s

    And there is hardly any impact on memory usage: Memory usage on mse 844 MB -> 848 MB, serde1 184 MB -> 184 MB (jitter on these is a few MB).

    S-waiting-on-author 
    opened by saethlin 37
  • Miri does not properly check return-position `noalias`

    Miri does not properly check return-position `noalias`

    See https://github.com/rust-lang/unsafe-code-guidelines/issues/385 for details and discussion, this just tracks the fact that we have some LLVM UB that is not checked by Miri.

    C-bug A-stacked-borrows I-misses-UB 
    opened by RalfJung 0
  • Add test ensuring that drop terminator of no-drop type is a NOP

    Add test ensuring that drop terminator of no-drop type is a NOP

    In https://github.com/rust-lang/rust/pull/103957 we realized that Miri's treatment of Drop terminators subtly differed from that of the codegen backends. That got fixed, but we don't have a test for that. Not sure if a test is even possible, but we custom_mir it might be?

    Cc @JakobDegen

    opened by RalfJung 1
  • assertion failed: dest.layout.ty.is_integral()

    assertion failed: dest.layout.ty.is_integral()

    from src/test/ui/simd/simd-bitmask.rs

    //run-pass
    //ignore-endian-big behavior of simd_select_bitmask is endian-specific
    #![feature(repr_simd, platform_intrinsics)]
    
    extern "platform-intrinsic" {
        fn simd_bitmask<T, U>(v: T) -> U;
    }
    
    #[derive(Copy, Clone)]
    #[repr(simd)]
    struct Simd<T, const N: usize>([T; N]);
    
    fn main() {
        unsafe {
            let v = Simd::<i8, 4>([-1, 0, -1, 0]);
            let _a: [u8; 1] = simd_bitmask(v);
        }
    
    }
    
    
    thread 'rustc' panicked at 'assertion failed: dest.layout.ty.is_integral()', src/tools/miri/src/shims/intrinsics/simd.rs:550:17
    stack backtrace:
       0:     0x7efe47365a7a - std::backtrace_rs::backtrace::libunwind::trace::h06c3ddb908575635
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
       1:     0x7efe47365a7a - std::backtrace_rs::backtrace::trace_unsynchronized::h8bfc3753e1cc3345
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
       2:     0x7efe47365a7a - std::sys_common::backtrace::_print_fmt::h3c304feda98d6679
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/std/src/sys_common/backtrace.rs:65:5
       3:     0x7efe47365a7a - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h98af9289a7a29dc2
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/std/src/sys_common/backtrace.rs:44:22
       4:     0x7efe473c87ae - core::fmt::write::h02538848739b7e2a
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/core/src/fmt/mod.rs:1208:17
       5:     0x7efe47355f45 - std::io::Write::write_fmt::h4aac2f2c3f0128af
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/std/src/io/mod.rs:1682:15
       6:     0x7efe47365845 - std::sys_common::backtrace::_print::h2e2acfe71f2fdb67
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/std/src/sys_common/backtrace.rs:47:5
       7:     0x7efe47365845 - std::sys_common::backtrace::print::h5bf077c253fab052
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/std/src/sys_common/backtrace.rs:34:9
       8:     0x7efe4736858f - std::panicking::default_hook::{{closure}}::h0ceeeedebdf177d0
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/std/src/panicking.rs:267:22
       9:     0x7efe473682cb - std::panicking::default_hook::h7d6f04e84940bd1d
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/std/src/panicking.rs:286:9
      10:     0x7efe4a640511 - rustc_driver[3622bb61b1ebe64a]::DEFAULT_HOOK::{closure#0}::{closure#0}
      11:     0x7efe47368dcd - <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call::hc60f5ae29562b326
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/alloc/src/boxed.rs:2032:9
      12:     0x7efe47368dcd - std::panicking::rust_panic_with_hook::hce0f8648dbfb386b
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/std/src/panicking.rs:692:13
      13:     0x7efe47368b02 - std::panicking::begin_panic_handler::{{closure}}::h6ffcdb3a218d0ebe
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/std/src/panicking.rs:577:13
      14:     0x7efe47365f2c - std::sys_common::backtrace::__rust_end_short_backtrace::hc576a427f61fdaa5
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/std/src/sys_common/backtrace.rs:137:18
      15:     0x7efe47368852 - rust_begin_unwind
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/std/src/panicking.rs:575:5
      16:     0x7efe473c5193 - core::panicking::panic_fmt::habc1ee4a9702013e
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/core/src/panicking.rs:64:14
      17:     0x7efe473c526d - core::panicking::panic::h73f802489c27713b
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/core/src/panicking.rs:111:5
      18:     0x565111e3a7cf - <rustc_const_eval[60209f501fc07249]::interpret::eval_context::InterpCx<miri[df45d2962384a2a4]::machine::MiriMachine> as miri[df45d2962384a2a4]::shims::intrinsics::simd::EvalContextExt>::emulate_simd_intrinsic
      19:     0x565111de0bf9 - <rustc_const_eval[60209f501fc07249]::interpret::eval_context::InterpCx<miri[df45d2962384a2a4]::machine::MiriMachine>>::eval_fn_call
      20:     0x565111e166a8 - <rustc_const_eval[60209f501fc07249]::interpret::eval_context::InterpCx<miri[df45d2962384a2a4]::machine::MiriMachine> as miri[df45d2962384a2a4]::concurrency::thread::EvalContextExt>::run_threads
      21:     0x565111ec1e1d - miri[df45d2962384a2a4]::eval::eval_entry
      22:     0x565111d1d0e4 - <rustc_interface[299971c75fff0058]::passes::QueryContext>::enter::<<miri[2cc0a1151e659598]::MiriCompilerCalls as rustc_driver[3622bb61b1ebe64a]::Callbacks>::after_analysis::{closure#0}, ()>
      23:     0x565111d22263 - <miri[2cc0a1151e659598]::MiriCompilerCalls as rustc_driver[3622bb61b1ebe64a]::Callbacks>::after_analysis
      24:     0x7efe498d1661 - <rustc_interface[299971c75fff0058]::interface::Compiler>::enter::<rustc_driver[3622bb61b1ebe64a]::run_compiler::{closure#1}::{closure#2}, core[62c015fcd585be4a]::result::Result<core[62c015fcd585be4a]::option::Option<rustc_interface[299971c75fff0058]::queries::Linker>, rustc_errors[19d12f94925af316]::ErrorGuaranteed>>
      25:     0x7efe498cc658 - rustc_span[ea560f4838c45ec0]::with_source_map::<core[62c015fcd585be4a]::result::Result<(), rustc_errors[19d12f94925af316]::ErrorGuaranteed>, rustc_interface[299971c75fff0058]::interface::run_compiler<core[62c015fcd585be4a]::result::Result<(), rustc_errors[19d12f94925af316]::ErrorGuaranteed>, rustc_driver[3622bb61b1ebe64a]::run_compiler::{closure#1}>::{closure#0}::{closure#0}>
      26:     0x7efe498cc145 - <scoped_tls[6f6de2f0677d8068]::ScopedKey<rustc_span[ea560f4838c45ec0]::SessionGlobals>>::set::<rustc_interface[299971c75fff0058]::interface::run_compiler<core[62c015fcd585be4a]::result::Result<(), rustc_errors[19d12f94925af316]::ErrorGuaranteed>, rustc_driver[3622bb61b1ebe64a]::run_compiler::{closure#1}>::{closure#0}, core[62c015fcd585be4a]::result::Result<(), rustc_errors[19d12f94925af316]::ErrorGuaranteed>>
      27:     0x7efe498cb732 - std[688abfdbcfe52504]::sys_common::backtrace::__rust_begin_short_backtrace::<rustc_interface[299971c75fff0058]::util::run_in_thread_pool_with_globals<rustc_interface[299971c75fff0058]::interface::run_compiler<core[62c015fcd585be4a]::result::Result<(), rustc_errors[19d12f94925af316]::ErrorGuaranteed>, rustc_driver[3622bb61b1ebe64a]::run_compiler::{closure#1}>::{closure#0}, core[62c015fcd585be4a]::result::Result<(), rustc_errors[19d12f94925af316]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[62c015fcd585be4a]::result::Result<(), rustc_errors[19d12f94925af316]::ErrorGuaranteed>>
      28:     0x7efe49f03aba - <<std[688abfdbcfe52504]::thread::Builder>::spawn_unchecked_<rustc_interface[299971c75fff0058]::util::run_in_thread_pool_with_globals<rustc_interface[299971c75fff0058]::interface::run_compiler<core[62c015fcd585be4a]::result::Result<(), rustc_errors[19d12f94925af316]::ErrorGuaranteed>, rustc_driver[3622bb61b1ebe64a]::run_compiler::{closure#1}>::{closure#0}, core[62c015fcd585be4a]::result::Result<(), rustc_errors[19d12f94925af316]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[62c015fcd585be4a]::result::Result<(), rustc_errors[19d12f94925af316]::ErrorGuaranteed>>::{closure#1} as core[62c015fcd585be4a]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
      29:     0x7efe47372dc3 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::h16c8b1a5112fc07f
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/alloc/src/boxed.rs:2000:9
      30:     0x7efe47372dc3 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::h0cc5ff4fc4b4dcff
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/alloc/src/boxed.rs:2000:9
      31:     0x7efe47372dc3 - std::sys::unix::thread::Thread::new::thread_start::ha7c6dff74603472f
                                   at /rustc/935dc07218b4bf6e20231e44eb9263b612fd649b/library/std/src/sys/unix/thread.rs:108:17
      32:     0x7efe471058fd - <unknown>
      33:     0x7efe47187a60 - <unknown>
      34:                0x0 - <unknown>
    
    error: internal compiler error: unexpected panic
    
    note: the compiler unexpectedly panicked. this is a bug.
    
    note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md
    
    note: rustc 1.68.0-nightly (935dc0721 2022-12-19) running on x86_64-unknown-linux-gnu
    
    note: compiler flags: --crate-type bin -C embed-bitcode=no -C debuginfo=2 -C incremental=[REDACTED] -C target-cpu=native
    
    note: some of the compiler flags provided by cargo are hidden
    
    query stack during panic:
    end of query stack
    
    Miri caused an ICE during evaluation. Here's the interpreter backtrace at the time of the panic:
    note: the place in the program where the ICE was triggered
      --> src/main.rs:16:27
       |
    16 |         let _a: [u8; 1] = simd_bitmask(v);
       |                           ^^^^^^^^^^^^^^^
       |
       = note: inside `main` at src/main.rs:16:27: 16:42
       = note: inside `<fn() as std::ops::FnOnce<()>>::call_once - shim(fn())` at /home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:507:5: 507:71
       = note: inside `std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()>` at /home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys_common/backtrace.rs:121:18: 121:21
       = note: inside closure at /home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs:166:18: 166:82
       = note: inside `std::ops::function::impls::<impl std::ops::FnOnce<()> for &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>::call_once` at /home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:606:13: 606:31
       = note: inside `std::panicking::r#try::do_call::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at /home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:483:40: 483:43
       = note: inside `std::panicking::r#try::<i32, &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>` at /home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:447:19: 447:81
       = note: inside `std::panic::catch_unwind::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at /home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:137:14: 137:33
       = note: inside closure at /home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs:148:48: 148:73
       = note: inside `std::panicking::r#try::do_call::<[closure@std::rt::lang_start_internal::{closure#2}], isize>` at /home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:483:40: 483:43
       = note: inside `std::panicking::r#try::<isize, [closure@std::rt::lang_start_internal::{closure#2}]>` at /home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:447:19: 447:81
       = note: inside `std::panic::catch_unwind::<[closure@std::rt::lang_start_internal::{closure#2}], isize>` at /home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:137:14: 137:33
       = note: inside `std::rt::lang_start_internal` at /home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs:148:20: 148:98
       = note: inside `std::rt::lang_start::<()>` at /home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs:165:17: 170:6
    
    warning: 1 warning emitted
    
    opened by matthiaskrgr 9
  • per-toolchain cache of std

    per-toolchain cache of std

    would be nice if miri was able to have separate caches for its std build for cargo +master miri... and cargo +nightly miri... for example, to avoid frequent rebuilds when experimenting with different toolchains at the same time.

    A-cargo E-easy 
    opened by matthiaskrgr 5
  • Miri could respect `-Zbox-noalias=no` for `-Zmiri-retag-fields=scalar`

    Miri could respect `-Zbox-noalias=no` for `-Zmiri-retag-fields=scalar`

    -Zmiri-retag-fields=scalar is roughly explained as retagging where rustc emits noalias attributes. For this to be accurate, Box shouldn't cause retagging when -Zbox-noalias=no, since setting this (experimental) rustc flag disables emitting noalias for Box.

    opened by CAD97 1
  • Experiment idea: `-Zmiri-unique-library-types` to control treating `Box` and `Vec` as `Uniq` retaggers

    Experiment idea: `-Zmiri-unique-library-types` to control treating `Box` and `Vec` as `Uniq` retaggers

    Currently, rustc tags Box as noalias, so the default behavior of Miri is to treat moving Box as a Uniq SB retag, invalidating any pointers to its interior.

    [Raw]Vec is built on the same internal ptr::Unique. It has been considered if treating Vec as Uniq as well, though the fallout from doing so is very likely (and iirc, there was an experiment showing it to be) to make more programs UB than with Box.

    Would it be possible/reasonable to expose a miri flag to treat Vec's pointer as unique? This wouldn't have any impact without also setting -Zmiri-retag-fields=all since Vec is larger than a scalar pair, but I'd like to be able to put Miri into super pedantic mode when testing my own unsafe code which should ideally be valid even under this extremely strict interpretation.

    In short, I would like a (combination of) flags that allows the following snippet to be diagnosed as UB. By my understanding of the current SB rules, under the strictest form (always doing field retagging, ptr::Unique is unique), it is. Even if this is stricter than we end up actually adopting, I think having the ability to diagnose this as potential UB is a useful tool in making the decision, since it allows us to quantify how much crater-visible miri-testable code (doesn't have other issues and) is using Vec as a stand-in for RFC3336<Pin<Vec<_>>>.

    let mut v = vec![0];
    let p = addr_of!(v[0]);
    let v = v;
    &*p;
    

    The flag could also allow more crates to benefit from Miri testing coverage with field retagging even if they're implicitly relying on -Zbox-noalias=no, if it allows opting out of Uniq retagging on Box (though obviously doing so would currently be unsound).

    opened by CAD97 3
Owner
The Rust Programming Language
The Rust Programming Language
A high level language for SELinux policy

Introduction Cascade is a project to build a new high level language for defining SELinux policy. The overall structure of the language is essentially

Daniel Burgener 42 Dec 14, 2022
Rust mid-level IR Abstract Interpreter

MIRAI MIRAI is an abstract interpreter for the Rust compiler's mid-level intermediate representation (MIR). It is intended to become a widely used sta

Facebook Experimental 793 Jan 2, 2023
Rust mid-level IR Abstract Interpreter

MIRAI MIRAI is an abstract interpreter for the Rust compiler's mid-level intermediate representation (MIR). It is intended to become a widely used sta

Meta Experimental 789 Dec 26, 2022
a simple compiled language i made in rust. it uses intermediate representation (IR) instead of an abstract syntax tree (AST).

a simple compiled language i made in rust. it uses intermediate representation (IR) instead of an abstract syntax tree (AST).

null 4 Oct 3, 2022
TTVM Intermediate Representation driver

ttir - TTVM IR Driver ttir is driver for the TTVM IR located in ttvm. Usage Run the following command in your shell: cargo install ttir Features Easy

maDeveloper 1 Nov 2, 2021
Bril: A Compiler Intermediate Representation for Learning

Bril: A Compiler Intermediate Representation for Learning Bril (the Big Red Intermediate Language) is a compiler IR made for teaching CS 6120, a grad

Lesley Lai 0 Dec 5, 2022
PyQIR is a set of APIs for generating, parsing, and evaluating Quantum Intermediate Representation (QIR).

PyQIR PyQIR is a set of APIs for generating, parsing, and evaluating Quantum Intermediate Representation (QIR). It consists of the following component

QIR Alliance 37 Dec 31, 2022
An Intermediate Representation which can be compiled into WebAssembly

WebAssembly Intermediate Representation This is an Intermediate Representation which can be compiled into WebAssembly. The source code is in an experi

Blue Forest 2 Dec 7, 2022
A compiler to convert Cairo's intermediate representation "Sierra" code to MLIR.

Cairo Sierra to MLIR compiler A compiler to convert Cairo's intermediate representation "Sierra" code to MLIR. Documentation There is an mdbook in the

Lambdaclass 5 Mar 16, 2023
Easy c̵̰͠r̵̛̠ö̴̪s̶̩̒s̵̭̀-t̶̲͝h̶̯̚r̵̺͐e̷̖̽ḁ̴̍d̶̖̔ ȓ̵͙ė̶͎ḟ̴͙e̸̖͛r̶̖͗ë̶̱́ṉ̵̒ĉ̷̥e̷͚̍ s̷̹͌h̷̲̉a̵̭͋r̷̫̊ḭ̵̊n̷̬͂g̵̦̃ f̶̻̊ơ̵̜ṟ̸̈́ R̵̞̋ù̵̺s̷̖̅ţ̸͗!̸̼͋

Rust S̵̓i̸̓n̵̉ I̴n̴f̶e̸r̵n̷a̴l mutability! Howdy, friendly Rust developer! Ever had a value get m̵̯̅ð̶͊v̴̮̾ê̴̼͘d away right under your nose just when

null 294 Dec 23, 2022
A pure, low-level tensor program representation enabling tensor program optimization via program rewriting

Glenside is a pure, low-level tensor program representation which enables tensor program optimization via program rewriting, using rewriting frameworks such as the egg equality saturation library.

Gus Smith 45 Dec 28, 2022
The best Intermediate Rust course out there!

Ultimate Rust 2: Intermediate Concepts This is the companion repository for the Ultimate Rust 2: Intermediate Concepts (the followup to the popular Ul

Nathan Stocks 155 Jan 4, 2023
A bit-packed k-mer representation (and relevant utilities) for rust

K-mer class for rust The purpose of this repository is to build a simple library that exposes a bit-packed k-mer class for use in rust-based bioinform

COMBINE lab 41 Dec 15, 2022
Simple and efficient time representation in Rust.

timens-rs Simple and efficient timestamp representation. The main objective being interoperability with OCaml Core_kernel.Time_ns. A significant part

Laurent Mazare 7 Oct 17, 2022
CBOR: Concise Binary Object Representation

CBOR 0x(4+4)9 0x49 “The Concise Binary Object Representation (CBOR) is a data format whose design goals include the possibility of extremely small cod

quininer 37 Dec 27, 2022
An efficient method of heaplessly converting numbers into their string representations, storing the representation within a reusable byte array.

NumToA #![no_std] Compatible with Zero Heap Allocations The standard library provides a convenient method of converting numbers into strings, but thes

Michael Murphy 42 Sep 6, 2022
SelfOrgMap 5 Nov 4, 2020
A Rust proc-macro crate which derives functions to compile and parse back enums and structs to and from a bytecode representation

Bytecode A simple way to derive bytecode for you Enums and Structs. What is this This is a crate that provides a proc macro which will derive bytecode

null 4 Sep 3, 2022
This crate allows to generate a flat binary with the memory representation of an ELF.

flatelf Library This crate allows to generate a flat binary with the memory representation of an ELF. It also allows to generate a FLATELF with the fo

Roi Martin 3 Sep 29, 2022
A Rust trait to convert numbers of any type and size to their English representation.

num2english This Rust crate provides the NumberToEnglish trait which can be used to convert any* number to its string representation in English. It us

Travis A. Wagner 6 Mar 8, 2023