Save a created event for zero-size reborrows
Currently, we don't save a created event for zero-sized reborrows. Attempting to use something from a zero-sized reborrow is surprisingly common, for example on `minimal-lexical==0.2.1` we previously just emit this:
```
Undefined Behavior: attempting a write access using <187021> at alloc72933[0x0], but that tag does not exist in the borrow stack for this location
--> /root/rust/library/core/src/ptr/mod.rs:1287:9
|
1287 | copy_nonoverlapping(&src as *const T, dst, 1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| attempting a write access using <187021> at alloc72933[0x0], but that tag does not exist in the borrow stack for this location
| this error occurs as part of an access at alloc72933[0x0..0x8]
|
= 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
= note: inside `std::ptr::write::<u64>` at /root/rust/library/core/src/ptr/mod.rs:1287:9
note: inside `minimal_lexical::stackvec::StackVec::push_unchecked` at /root/build/src/stackvec.rs:82:13
--> /root/build/src/stackvec.rs:82:13
|
82 | ptr::write(self.as_mut_ptr().add(self.len()), value);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
... backtrace continues...
```
Which leaves us with the question "where did we make this pointer?" because for every other diagnostic you get a "was created by" note, so I suspect people might be tempted to think there is a Miri bug here. I certainly was.
---
This code duplication is so awful, I'm going to take a look at cleaning it up later. The fact that `ptr_get_alloc_id` can fail in this situation makes things annoying.
Initial work on Miri permissive-exposed-provenance
Miri portions of the changes for portions of a permissive ptr-to-int model for Miri. This is more restrictive than what we currently have so it will probably need a flag once I figure out how to hook that up.
> This implements a form of permissive exposed-address provenance, wherein the only way to expose the address is with a cast to usize (ideally expose_addr). This is more restrictive than C in that stuff like reading the representation bytes (via unions, type-punning, transmute) does not expose the address, only expose_addr. This is less restrictive than C in that a pointer casted from an integer has union provenance of all exposed pointers, not any udi stuff.
There's a few TODOs here, namely related to `fn memory_read` and friends. We pass it the maybe/unreified provenance before `ptr_get_alloc` reifies it into a concrete one, so it doesn't have the `AllocId` (or the SB tag, but that's getting ahead of ourselves). One way this could be fixed is changing `ptr_get_alloc` and (`ptr_try_get_alloc_id` on the rustc side) to return a pointer with the tag fixed up. We could also take in different arguments, but I'm not sure what works best.
The other TODOs here are how permissive this model could be. This currently does not enforce that a ptr-to-int cast happens before the corresponding int-to-ptr (colloquial meaning of happens before, not atomic meaning). Example:
```
let ptr = 0x2000 as *const i32;
let a: i32 = 5;
let a_ptr = &a as *const i32;
// value is 0x2000;
a_ptr as usize;
println!("{}", unsafe { *ptr }); // this is valid
```
We also allow the resulting pointer to dereference different non-contiguous allocations (the "not any udi stuff" mentioned above), which I'm not sure if is allowed by LLVM.
This is the Miri side of https://github.com/rust-lang/rust/pull/95826.
Adjust diagnostics assertion so we don't ICE in setup
Fixes https://github.com/rust-lang/miri/issues/2076 just by handling diagnostics produced during setup. The tracking notes don't have any spans but it's better than an ICE.
It looks like we leak allocations 1..20, and allocations 13..19 don't have any creation notes, and 14 only has a `FreedAlloc` alloc tracking diagnostic.
Make allow_data_races_* public and use it during EnvVars::cleanup
Fixes https://github.com/rust-lang/miri/issues/2020
I've tried for hours now to come up with a test case for this ICE with no luck. I suspect there's something about the way the data race detection works under these conditions that I just don't understand 😩.
But I tried this change out on a handful of crates and I don't see any more ICEs of this form. For whatever reason it seems like `bastion==0.4.5` is a good way to run into this, with the flags
```
MIRIFLAGS="-Zmiri-tag-raw-pointers -Zmiri-panic-on-unsupported -Zmiri-disable-isolation" cargo +miri miri test --no-fail-fast --doc
```
I think all the cases I've run into with this involve both `-Zmiri-panic-on-unsupported` and `-Zmiri-tag-raw-pointers`, so it could be that the combination of an unexpected panic and a machine halt is required.
Pass the correct size to the AllocRange for log_creation
Fixes https://github.com/rust-lang/miri/issues/2127
I guess all I needed was a bit of sleep and reassurance that this diagnostic is the wrong part of that situation.
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.
* Store the local crates in an Rc<[CrateNum]>
* Move all the allocation history into Stacks
* Clean up the implementation of get_logs_relevant_to a bit
Use atomic RMW for `{mutex, rwlock, cond, srwlock}_get_or_create_id` functions
This is required for #1963
`{mutex, rwlock, cond, srwlock}_get_or_create_id()` currently checks whether an ID field is 0 using an atomic read, allocate one and get a new ID if it is, then write it in a separate atomic write. This is fine without weak memory. For instance, in `pthread_mutex_lock` which may be called by two threads concurrently, only one thread can read 0, create and then write a new ID, the later-run thread will always see the newly created ID and never 0.
```rust
fn pthread_mutex_lock(&mut self, mutex_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
let kind = mutex_get_kind(this, mutex_op)?.check_init()?;
let id = mutex_get_or_create_id(this, mutex_op)?;
let active_thread = this.get_active_thread();
```
However, with weak memory behaviour, both threads may read 0: the first thread has to see 0 because nothing else was written to it, and the second thread is not guaranteed to observe the latest value, causing a duplicate mutex to be created and both threads "successfully" acquiring the lock at the same time.
This is a pretty typical pattern requiring the use of atomic RMWs. RMW *always* reads the latest value in a location, so only one thread can create the new mutex and ID, all others scheduled later will see the new ID.
* Pass a ThreadInfo down to grant/access to get the current span lazily
* Rename add_* to log_* for clarity
* Hoist borrow_mut calls out of loops by tweaking the for_each signature
* Explain the parameters of check_protector a bit more
Add a command line flag to avoid printing to stdout and stderr
This is practical for tests that don't actually care about the output and thus don't want it intermingled with miri's warnings, errors or ICEs
fixes#2083
error: useless conversion to the same type: `rustc_const_eval::interpret::Pointer<std::option::Option<machine::Tag>>`
--> src/helpers.rs:668:36
|
668 | this.get_ptr_alloc(ptr.offset(len, this)?.into(), size1, Align::ONE)?.unwrap(); // not a ZST, so we will get a result
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `ptr.offset(len, this)?`
|
= note: `-D clippy::useless-conversion` implied by `-D clippy::all`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
error: useless conversion to the same type: `rustc_const_eval::interpret::Pointer<std::option::Option<machine::Tag>>`
--> src/helpers.rs:678:29
|
678 | this.read_bytes_ptr(ptr.into(), len)
| ^^^^^^^^^^ help: consider removing `.into()`: `ptr`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
error: useless conversion to the same type: `rustc_const_eval::interpret::Pointer<std::option::Option<machine::Tag>>`
--> src/helpers.rs:690:44
|
690 | let alloc = this.get_ptr_alloc(ptr.into(), size2, align2)?.unwrap(); // not a ZST, so we will get a result
| ^^^^^^^^^^ help: consider removing `.into()`: `ptr`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
error: useless conversion to the same type: `rustc_const_eval::interpret::OpTy<machine::Tag>`
--> src/shims/intrinsics.rs:778:42
|
778 | .read_immediate(&this.operand_index(index, i)?.into())?
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `this.operand_index(index, i)?`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
error: useless conversion to the same type: `u32`
--> src/shims/posix/fs.rs:1171:26
|
1171 | builder.mode(mode.into());
| ^^^^^^^^^^^ help: consider removing `.into()`: `mode`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
error: useless conversion to the same type: `std::ffi::OsString`
--> src/shims/env.rs:67:53
|
67 | ecx.machine.env_vars.map.insert(OsString::from(name), var_ptr);
| ^^^^^^^^^^^^^^^^^^^^ help: consider removing `OsString::from()`: `name`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
error: useless conversion to the same type: `rustc_const_eval::interpret::Scalar<machine::Tag>`
--> src/shims/tls.rs:102:44
|
102 | Ok(value.unwrap_or_else(|| Scalar::null_ptr(cx).into()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `Scalar::null_ptr(cx)`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
error: useless conversion to the same type: `u32`
--> src/thread.rs:73:26
|
73 | Scalar::from_u32(u32::try_from(self.0).unwrap())
| ^^^^^^^^^^^^^^^^^^^^^
|
= help: consider removing `u32::try_from()`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
error: the method `validate_lock_acquire` doesn't need a mutable reference
--> src/sync.rs:477:49
|
477 | data_race.validate_lock_acquire(&mut condvar.data_race, waiter.thread);
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::unnecessary-mut-passed` implied by `-D clippy::all`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed
error: single-character string constant used as pattern
--> src/helpers.rs:805:36
|
805 | .map(|crates| crates.split(",").map(|krate| krate.to_string()).collect::<Vec<_>>())
| ^^^ help: try using a `char` instead: `','`
|
= note: `-D clippy::single-char-pattern` implied by `-D clippy::all`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern
error: calling `push_str()` using a single-character string literal
--> src/diagnostics.rs:299:9
|
299 | helps.last_mut().unwrap().1.push_str("\n");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `helps.last_mut().unwrap().1.push('\n')`
|
= note: `-D clippy::single-char-add-str` implied by `-D clippy::all`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#single_char_add_str
error: redundant field names in struct initialization
--> src/helpers.rs:199:34
|
199 | let place = mir::Place { local: local, projection: List::empty() };
| ^^^^^^^^^^^^ help: replace it with: `local`
|
= note: `-D clippy::redundant-field-names` implied by `-D clippy::all`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names
error: redundant field names in struct initialization
--> src/thread.rs:238:13
|
238 | threads: threads,
| ^^^^^^^^^^^^^^^^ help: replace it with: `threads`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names
error: redundant closure
--> src/data_race.rs:787:18
|
787 | .map(|idx| VectorIdx::new(idx))
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `VectorIdx::new`
|
= note: `-D clippy::redundant-closure` implied by `-D clippy::all`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
error: redundant closure
--> src/thread.rs:61:31
|
61 | u32::try_from(id).map(|id_u32| Self(id_u32))
| ^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `Self`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
error: taken reference of right operand
--> src/shims/env.rs:53:63
|
53 | true => !excluded_env_vars.iter().any(|v| v.as_str() == &name),
| ^^^^^^^^^^^^^^-----
| |
| help: use the right value directly: `name`
|
= note: `-D clippy::op-ref` implied by `-D clippy::all`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#op_ref
error: taken reference of right operand
--> src/shims/env.rs:54:71
|
54 | false => config.forwarded_env_vars.iter().any(|v| v.as_str() == &name),
| ^^^^^^^^^^^^^^-----
| |
| help: use the right value directly: `name`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#op_ref
error: question mark operator is useless here
--> src/helpers.rs:86:16
|
86 | return Ok(const_val.check_init()?);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `const_val.check_init()`
|
= note: `-D clippy::needless-question-mark` implied by `-D clippy::all`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
--> src/range_map.rs:66:5
|
66 | pub fn iter<'a>(&'a self, offset: Size, len: Size) -> impl Iterator<Item = (Size, &'a T)> + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::needless-lifetimes` implied by `-D clippy::all`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
--> src/range_map.rs:86:5
|
86 | pub fn iter_mut_all<'a>(&'a mut self) -> impl Iterator<Item = &'a mut T> + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
--> src/range_map.rs:122:5
|
122 | / pub fn iter_mut<'a>(
123 | | &'a mut self,
124 | | offset: Size,
125 | | len: Size,
126 | | ) -> impl Iterator<Item = (Size, &'a mut T)> + 'a
| |_____________________________________________________^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
--> src/shims/intrinsics.rs:1391:1
|
1391 | fn simd_element_to_bool<'tcx>(elem: ImmTy<'tcx, Tag>) -> InterpResult<'tcx, bool> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/data_race.rs:565:34
|
565 | this.validate_atomic_rmw(&place, atomic)?;
| ^^^^^^ help: change this to: `place`
|
= note: `-D clippy::needless-borrow` implied by `-D clippy::all`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/data_race.rs:1413:27
|
1413 | clocks.clock.join(&lock);
| ^^^^^ help: change this to: `lock`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/helpers.rs:326:51
|
326 | .size_and_align_of_mplace(&place)?
| ^^^^^^ help: change this to: `place`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/helpers.rs:365:17
|
365 | &self.ecx
| ^^^^^^^^^ help: change this to: `self.ecx`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/helpers.rs:634:47
|
634 | let seconds_place = this.mplace_field(&tp, 0)?;
| ^^^ help: change this to: `tp`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/helpers.rs:637:51
|
637 | let nanoseconds_place = this.mplace_field(&tp, 1)?;
| ^^^ help: change this to: `tp`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/machine.rs:547:73
|
547 | let link_name = match ecx.tcx.sess.first_attr_value_str_by_name(&attrs, sym::link_name) {
| ^^^^^^ help: change this to: `attrs`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/machine.rs:576:56
|
576 | Some(data_race::AllocExtra::new_allocation(&data_race, alloc.size(), kind))
| ^^^^^^^^^^ help: change this to: `data_race`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/shims/foreign_items.rs:241:43
|
241 | .first_attr_value_str_by_name(&attrs, sym::link_name)
| ^^^^^^ help: change this to: `attrs`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/shims/intrinsics.rs:778:61
|
778 | .read_immediate(&this.operand_index(&index, i)?.into())?
| ^^^^^^ help: change this to: `index`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/shims/intrinsics.rs:1195:44
|
1195 | this.write_immediate(*old, &dest)?; // old value is returned
| ^^^^^ help: change this to: `dest`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/shims/intrinsics.rs:1200:44
|
1200 | this.write_immediate(*old, &dest)?; // old value is returned
| ^^^^^ help: change this to: `dest`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/shims/posix/fs.rs:54:12
|
54 | Ok(&self)
| ^^^^^ help: change this to: `self`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/shims/posix/fs.rs:654:49
|
654 | let io_result = maybe_sync_file(&file, *writable, File::sync_all);
| ^^^^^ help: change this to: `file`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/shims/posix/fs.rs:746:52
|
746 | file_descriptor.write(communicate, &bytes)?.map(|c| i64::try_from(c).unwrap());
| ^^^^^^ help: change this to: `bytes`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/shims/posix/fs.rs:1494:45
|
1494 | let io_result = maybe_sync_file(&file, *writable, File::sync_all);
| ^^^^^ help: change this to: `file`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/shims/posix/fs.rs:1516:45
|
1516 | let io_result = maybe_sync_file(&file, *writable, File::sync_data);
| ^^^^^ help: change this to: `file`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/shims/posix/fs.rs:1561:45
|
1561 | let io_result = maybe_sync_file(&file, *writable, File::sync_data);
| ^^^^^ help: change this to: `file`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/shims/env.rs:232:65
|
232 | let var_ptr = alloc_env_var_as_c_str(&name, &value, &mut this)?;
| ^^^^^^^^^ help: change this to: `this`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/shims/env.rs:277:68
|
277 | let var_ptr = alloc_env_var_as_wide_str(&name, &value, &mut this)?;
| ^^^^^^^^^ help: change this to: `this`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/shims/env.rs:328:37
|
328 | let buf = this.read_pointer(&buf_op)?;
| ^^^^^^^ help: change this to: `buf_op`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: this expression creates a reference which is immediately dereferenced by the compiler
--> src/shims/env.rs:329:37
|
329 | let size = this.read_scalar(&size_op)?.to_machine_usize(&*this.tcx)?;
| ^^^^^^^^ help: change this to: `size_op`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> src/helpers.rs:54:29
|
54 | for item in mem::replace(&mut items, Default::default()).iter() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut items)`
|
= note: `-D clippy::mem-replace-with-default` implied by `-D clippy::all`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default
error: length comparison to one
--> src/shims/posix/thread.rs:102:12
|
102 | if args.len() < 1 {
| ^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `args.is_empty()`
|
= note: `-D clippy::len-zero` implied by `-D clippy::all`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
error: using `clone` on type `std::option::Option<u128>` which implements the `Copy` trait
--> src/shims/tls.rs:307:24
|
307 | let last_key = this.machine.tls.dtors_running[&active_thread].last_dtor_key.clone();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the `clone` call: `this.machine.tls.dtors_running[&active_thread].last_dtor_key`
|
= note: `-D clippy::clone-on-copy` implied by `-D clippy::all`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy
error: using `clone` on type `stacked_borrows::Item` which implements the `Copy` trait
--> src/stacked_borrows.rs:317:21
|
317 | item.clone(),
| ^^^^^^^^^^^^ help: try dereferencing it: `*item`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy
error: manual implementation of an assign operation
--> src/helpers.rs:673:17
|
673 | len = len + size1;
| ^^^^^^^^^^^^^^^^^ help: replace it with: `len += size1`
|
= note: `-D clippy::assign-op-pattern` implied by `-D clippy::all`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#assign_op_pattern
- Changed arg parsing to handle comma seperated list of `u64`'s.
- Changed type and field names of config, executor and global state
to hold a set of tracked ids.
- Adjusted Readme:
- explained list format
- arguments do not overwrite, instead append
- no effect on duplication
- Created a parsing function for comma separated lists
- Added error printing to alloc_id parsing
make strict-provenance imply check-number-validity
I feel like Miri not catching [this example](https://github.com/rust-lang/unsafe-code-guidelines/issues/286#issuecomment-1085144431) with strict provenance checking enabled is surprising.
OTOH, Miri suddenly complaining about uninit data in integers with `-Zmiri-strict-provenance` also might be surprising. Which one is more surprising? I don't know. We *could* go out of our way and have a mode where uninit integers are okay but provenance is not, but I am not sure if that is truly worth it. It'd be quite annoying to implement.
add -Zmiri-strict-provenance
This implements [strict provenance](https://github.com/rust-lang/rust/issues/95228) in Miri. The only change is that casting an integer to a pointer does not even attempt to produce a good provenance for the given address; instead, it always uses the invalid provenance. This stricter than even `-Zmiri-tag-raw-pointers` in that it also rejects the following example (which does not even involve Stacked Borrows):
```rust
fn main() {
let x = 22;
let ptr = &x as *const _ as *const u8;
let roundtrip = ptr as usize as *const u8;
let _ = unsafe { roundtrip.offset(1) };
}
```
The new flag also implies `-Zmiri-tag-raw-pointers` since the only reason one would *not* want to tag raw pointers is to support ptr-int-ptr roundtrips.
Note that the flag does *not* check against ptr-to-int *transmutes*; that still requires `-Zmiri-check-number-validity`. You can also check for strict provenance *without* Stacked Borrows by adding `-Zmiri-disable-stacked-borrows`.
The new "Miri hard mode" flags for maximal checking are `-Zmiri-strict-provenance -Zmiri-check-number-validity`. (Add `-Zmiri-symbolic-alignment-check` if you feel extra spicy today.)
Make backtraces work with #[global_allocator]
Currently, backtraces break when the global allocator is overridden because the allocator will attempt to deallocate memory allocated directly by Miri.
~~This PR fixes that by using a new memory kind and providing a function to deallocate it. We can't call the custom allocator to allocate because it's not possible to call a function in the middle of a shim.~~
This PR fixes that by adding a new version of the backtrace API accessible by setting `flags` to 1. Existing code still functions.
backtrace-rs PR: rust-lang/backtrace-rs#462
Fixes https://github.com/rust-lang/miri/issues/1996
Add a lot more information to SB fatal errors
In fatal errors, this clarifies the difference between a tag not being present in the borrow stack at all, and the tag being present but granting SRO. It also introduces a little notation for memory ranges so we can mention to the user that the span may point to code that operates on multiple memory locations, but we are reporting an error at a particular offset.
This also gets rid of the unqualified phrase "the borrow stack" in errors, and clarifies that it is the borrow stack _for some location_.
The crate `pdqselect` v0.1.1:
Before:
```
2103 | unsafe { copy_nonoverlapping(src, dst, count) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item granting read access to tag <2357> at alloc1029 found in borrow stack.
```
After:
```
2103 | unsafe { copy_nonoverlapping(src, dst, count) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| attempting a read access using <2357> at alloc1029[0x0], but that tag does not exist in the borrow stack for this location
| this error occurs as part of an access at alloc1029[0x0..0x4]
```
And the crate `half` v1.8.2
Before:
```
131 | unsafe { &mut *ptr::slice_from_raw_parts_mut(data, len) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trying to reborrow for Unique at alloc1051, but parent tag <2091> does not have an appropriate item in the borrow stack
```
After:
```
131 | unsafe { &mut *ptr::slice_from_raw_parts_mut(data, len) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| trying to reborrow <2091> for Unique permission at alloc1051[0x0], but that tag only grants SharedReadOnly permission for this location
| this error occurs as part of a reborrow at alloc1051[0x0..0x6]
```
This tries to clarify exactly why an access is not valid by printing
what memory range the access was over, which in combination with
tag-tracking may help a user figure out the source of the problem.
add write_int_fields to replace write_packed_immediates
This avoids having to explicitly list the types of all fields -- we derive them from the type of the struct instead.
Also add write_int_fields_named, to give the fields by name instead of ordered by index.
Allow varargs for libc::open when it is allowed by the second argument
This PR allows `libc::open` to be called using two or three arguments as defined in https://man7.org/linux/man-pages/man2/open.2.html
The presence of the third argument depends on the value of the second argument. If the second argument dictates that the third argument is *required* miri will emit an error if the argument is missing. If the second argument does *not* require a third argument, then the argument is ignored and passed as 0 internally (it would be ignored by libc anyway)
add flag to forward specific env vars (while isolation remains enabled)
The flag is called `-Zmiri-env-forward=<var>`, but I am open to bikeshedding. ;)
Prune backtraces similar to RUST_BACKTRACE=1 logic
This removes the majority of output from `cargo miri run` and `cargo miri test` in common usage.
~~I've copied the logic almost directly from `std`:
3b186511f6/library/std/src/sys_common/backtrace.rs (L76-L77~~)
~~It might be nice to have the "some details were omitted" note and a fallback to a setting where we print everything just in case this logic goes sideways, but~~
~~1. I'm not sure where to put the note~~
~~2. `MIRI_BACKTRACE`, `RUST_BACKTRACE`, and `RUSTC_CTFE_BACKTRACE` already do something else. Should we repurpose or add on to the semantics of `MIRI_BACKTRACE`?~~
---
Based on this tiny silly crate:
```rust
fn main() {
some_function();
}
fn some_function() {
unsafe {
let _x: &u8 = core::mem::transmute(1usize);
}
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
unsafe {
let _x: &'static u8 = core::mem::transmute(1usize);
}
}
}
```
`cargo miri run`:
Before:
```
Finished dev [unoptimized + debuginfo] target(s) in 0.10s
Running `/home/ben/.cargo/bin/cargo-miri target/miri/x86_64-unknown-linux-gnu/debug/scratch`
error: Undefined Behavior: type validation failed: encountered a dangling reference (address 0x1 is unallocated)
--> src/main.rs:7:23
|
7 | let _x: &u8 = core::mem::transmute(1usize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (address 0x1 is unallocated)
|
= 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: inside `some_function` at src/main.rs:7:23
note: inside `main` at src/main.rs:2:5
--> src/main.rs:2:5
|
2 | some_function();
| ^^^^^^^^^^^^^^^
= note: inside `<fn() as std::ops::FnOnce<()>>::call_once - shim(fn())` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
= note: inside `std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/sys_common/backtrace.rs:122:18
= note: inside closure at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/rt.rs:145:18
= 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/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/core/src/ops/function.rs:259:13
= note: inside `std::panicking::r#try::do_call::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/panicking.rs:492:40
= note: inside `std::panicking::r#try::<i32, &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/panicking.rs:456:19
= note: inside `std::panic::catch_unwind::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/panic.rs:137:14
= note: inside closure at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/rt.rs:128:48
= note: inside `std::panicking::r#try::do_call::<[closure@std::rt::lang_start_internal::{closure#2}], isize>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/panicking.rs:492:40
= note: inside `std::panicking::r#try::<isize, [closure@std::rt::lang_start_internal::{closure#2}]>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/panicking.rs:456:19
= note: inside `std::panic::catch_unwind::<[closure@std::rt::lang_start_internal::{closure#2}], isize>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/panic.rs:137:14
= note: inside `std::rt::lang_start_internal` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/rt.rs:128:20
= note: inside `std::rt::lang_start::<()>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/rt.rs:144:17
error: aborting due to previous error
```
After:
``` Finished dev [unoptimized + debuginfo] target(s) in 0.10s
Running `/home/ben/.cargo/bin/cargo-miri target/miri/x86_64-unknown-linux-gnu/debug/scratch`
error: Undefined Behavior: type validation failed: encountered a dangling reference (address 0x1 is unallocated)
--> src/main.rs:7:23
|
7 | let _x: &u8 = core::mem::transmute(1usize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (address 0x1 is unallocated)
|
= 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: inside `some_function` at src/main.rs:7:23
note: inside `main` at src/main.rs:2:5
--> src/main.rs:2:5
|
2 | some_function();
| ^^^^^^^^^^^^^^^
note: Some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace.
error: aborting due to previous error
```
`cargo miri test`
Before:
```
Finished test [unoptimized + debuginfo] target(s) in 0.00s
Running unittests (target/miri/x86_64-unknown-linux-gnu/debug/deps/scratch-9d7717efc37bb64c)
running 1 test
test tests::it_works ... error: Undefined Behavior: type validation failed: encountered a dangling reference (address 0x1 is unallocated)
--> src/main.rs:16:35
|
16 | let _x: &'static u8 = core::mem::transmute(1usize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (address 0x1 is unallocated)
|
= 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: inside `tests::it_works` at src/main.rs:16:35
note: inside closure at src/main.rs:14:5
--> src/main.rs:14:5
|
13 | #[test]
| ------- in this procedural macro expansion
14 | / fn it_works() {
15 | | unsafe {
16 | | let _x: &'static u8 = core::mem::transmute(1usize);
17 | | }
18 | | }
| |_____^
= note: inside `<[closure@src/main.rs:14:5: 18:6] as std::ops::FnOnce<()>>::call_once - shim` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
= note: inside `<fn() as std::ops::FnOnce<()>>::call_once - shim(fn())` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
= note: inside `tests::test::__rust_begin_short_backtrace::<fn()>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/test/src/lib.rs:575:5
= note: inside closure at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/test/src/lib.rs:566:30
= note: inside `<[closure@tests::test::run_test::{closure#1}] as std::ops::FnOnce<()>>::call_once - shim(vtable)` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
= note: inside `<std::boxed::Box<dyn std::ops::FnOnce() + std::marker::Send> as std::ops::FnOnce<()>>::call_once` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/alloc/src/boxed.rs:1854:9
= note: inside `<std::panic::AssertUnwindSafe<std::boxed::Box<dyn std::ops::FnOnce() + std::marker::Send>> as std::ops::FnOnce<()>>::call_once` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/core/src/panic/unwind_safe.rs:271:9
= note: inside `std::panicking::r#try::do_call::<std::panic::AssertUnwindSafe<std::boxed::Box<dyn std::ops::FnOnce() + std::marker::Send>>, ()>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/panicking.rs:492:40
= note: inside `std::panicking::r#try::<(), std::panic::AssertUnwindSafe<std::boxed::Box<dyn std::ops::FnOnce() + std::marker::Send>>>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/panicking.rs:456:19
= note: inside `std::panic::catch_unwind::<std::panic::AssertUnwindSafe<std::boxed::Box<dyn std::ops::FnOnce() + std::marker::Send>>, ()>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/panic.rs:137:14
= note: inside `tests::test::run_test_in_process` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/test/src/lib.rs:598:18
= note: inside closure at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/test/src/lib.rs:492:39
= note: inside `tests::test::run_test::run_test_inner` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/test/src/lib.rs:530:13
= note: inside `tests::test::run_test` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/test/src/lib.rs:562:28
= note: inside `tests::test::run_tests::<[closure@tests::test::run_tests_console::{closure#2}]>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/test/src/lib.rs:305:17
= note: inside `tests::test::run_tests_console` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/test/src/console.rs:290:5
= note: inside `tests::test::test_main` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/test/src/lib.rs:116:15
= note: inside `tests::test::test_main_static` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/test/src/lib.rs:135:5
= note: inside `main`
= note: inside `<fn() as std::ops::FnOnce<()>>::call_once - shim(fn())` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
= note: inside `std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/sys_common/backtrace.rs:122:18
= note: inside closure at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/rt.rs:145:18
= 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/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/core/src/ops/function.rs:259:13
= note: inside `std::panicking::r#try::do_call::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/panicking.rs:492:40
= note: inside `std::panicking::r#try::<i32, &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/panicking.rs:456:19
= note: inside `std::panic::catch_unwind::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/panic.rs:137:14
= note: inside closure at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/rt.rs:128:48
= note: inside `std::panicking::r#try::do_call::<[closure@std::rt::lang_start_internal::{closure#2}], isize>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/panicking.rs:492:40
= note: inside `std::panicking::r#try::<isize, [closure@std::rt::lang_start_internal::{closure#2}]>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/panicking.rs:456:19
= note: inside `std::panic::catch_unwind::<[closure@std::rt::lang_start_internal::{closure#2}], isize>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/panic.rs:137:14
= note: inside `std::rt::lang_start_internal` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/rt.rs:128:20
= note: inside `std::rt::lang_start::<()>` at /home/ben/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/rt.rs:144:17
= note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
error: test failed, to rerun pass '--bin scratch'
```
After:
```
Finished test [unoptimized + debuginfo] target(s) in 0.00s
Running unittests (target/miri/x86_64-unknown-linux-gnu/debug/deps/scratch-9d7717efc37bb64c)
running 1 test
test tests::it_works ... error: Undefined Behavior: type validation failed: encountered a dangling reference (address 0x1 is unallocated)
--> src/main.rs:16:35
|
16 | let _x: &'static u8 = core::mem::transmute(1usize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (address 0x1 is unallocated)
|
= 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: inside `tests::it_works` at src/main.rs:16:35
note: inside closure at src/main.rs:14:5
--> src/main.rs:14:5
|
13 | #[test]
| ------- in this procedural macro expansion
14 | / fn it_works() {
15 | | unsafe {
16 | | let _x: &'static u8 = core::mem::transmute(1usize);
17 | | }
18 | | }
| |_____^
= note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
note: Some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace.
error: aborting due to previous error
error: test failed, to rerun pass '--bin scratch'
```
Previously, Miri would always print a backtrace including all frames
when encountering an error. This adds -Zmiri-backtrace which defaults
to 1, internally called BacktraceStyle::Short. By default, backtraces
are pruned to start at __rust_begin_short_backtrace, similar to std.
Then we also remove non-local frames from the bottom of the trace.
This cleans up the last one or two shims outside main or a test.
Users can opt out of pruning by setting -Zmiri-backtrace=full, and will
be automatically opted out if there are no local frames because that
means the reported error is likely in the Rust runtime, which this
pruning is crafted to remove.
exclude mutable references to !Unpin types from uniqueness guarantees
This basically works around https://github.com/rust-lang/unsafe-code-guidelines/issues/148 by not requiring uniqueness any more for mutable references to self-referential generators. That corresponds to [the same work-around that was applied in rustc itself](b815532674/compiler/rustc_middle/src/ty/layout.rs (L2482)).
I am not entirely sure if this is a good idea since it might hide too many errors in case types are "accidentally" `!Unpin`. OTOH, our test suite still passes, and to my knowledge the vast majority of types is `Unpin`. (`place.layout.ty` is monomorphic, we should always exactly know which type this is.)
When two objects directly follow each other in memory, what is the
provenance of an integer cast to a pointer that points directly between
them? For a zero-size region, it could point into the end of the first
object, or the start of the second.
We can avoid answering this difficult question by simply never
allocating two objects directly beside each other. This fixes some of
the false positives from #1866.
This commit adds a `-Zmiri-check-number-initialization` flag to check
that integers and floats are initialized.
This commit also changes some shims to write at type `MaybeUninit<...>`
in order to prevent spurious errors from the uninit check.
add support for `#[global_allocator]`
This PR adds support for custom global allocators. Unfortunately, the code given in #1207 still causes errors when used with box. I believe this is because Box is special-cased in miri and stacked borrows.