Skip to content

Commit 8e1162f

Browse files
committed
Auto merge of rust-lang#110168 - saethlin:miri, r=RalfJung
update Miri Most importantly, this should ensure that the Miri test suite passes in this repo, when the issue is fixed. r? `@oli-obk`
2 parents 5072826 + d50fee9 commit 8e1162f

23 files changed

+105
-63
lines changed

src/tools/miri/.github/workflows/ci.yml

+6-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,12 @@ jobs:
174174
~/.local/bin/zulip-send --stream miri --subject "Cron Job Failure (miri, $(date -u +%Y-%m))" \
175175
--message 'Dear @*T-miri*,
176176
177-
It would appear that the Miri cron job build failed. Would you mind investigating this issue?
177+
It would appear that the [Miri cron job build]('"https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"') failed.
178+
179+
This likely means that rustc changed the miri directory and
180+
we now need to do a [`./miri rustc-pull`](https://github.com/rust-lang/miri/blob/master/CONTRIBUTING.md#importing-changes-from-the-rustc-repo).
181+
182+
Would you mind investigating this issue?
178183
179184
Thanks in advance!
180185
Sincerely,

src/tools/miri/Cargo.lock

+4-4
Original file line numberDiff line numberDiff line change
@@ -282,19 +282,19 @@ checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
282282

283283
[[package]]
284284
name = "libffi"
285-
version = "3.0.1"
285+
version = "3.2.0"
286286
source = "registry+https://github.com/rust-lang/crates.io-index"
287-
checksum = "1e454b3efb16fba3b17810ae5e41df02b649e564ab3c5a34b3b93ed07ad287e6"
287+
checksum = "ce826c243048e3d5cec441799724de52e2d42f820468431fc3fceee2341871e2"
288288
dependencies = [
289289
"libc",
290290
"libffi-sys",
291291
]
292292

293293
[[package]]
294294
name = "libffi-sys"
295-
version = "2.0.1"
295+
version = "2.2.1"
296296
source = "registry+https://github.com/rust-lang/crates.io-index"
297-
checksum = "84e78d02e5a8eae9c24c38ce6e6026f80e16dff76adcdae4bc5c6c52c2de4a60"
297+
checksum = "dc65067b78c0fc069771e8b9a9e02df71e08858bec92c1f101377c67b9dca7c7"
298298
dependencies = [
299299
"cc",
300300
]

src/tools/miri/README.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ for example:
1515
or an invalid enum discriminant)
1616
* **Experimental**: Violations of the [Stacked Borrows] rules governing aliasing
1717
for reference types
18-
* **Experimental**: Violations of the Tree Borrows aliasing rules, as an optional
18+
* **Experimental**: Violations of the [Tree Borrows] aliasing rules, as an optional
1919
alternative to [Stacked Borrows]
2020
* **Experimental**: Data races
2121

@@ -79,6 +79,7 @@ behavior** in your program, and cannot run all programs:
7979
[`unreachable_unchecked`]: https://doc.rust-lang.org/stable/std/hint/fn.unreachable_unchecked.html
8080
[`copy_nonoverlapping`]: https://doc.rust-lang.org/stable/std/ptr/fn.copy_nonoverlapping.html
8181
[Stacked Borrows]: https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md
82+
[Tree Borrows]: https://perso.crans.org/vanille/treebor/
8283

8384

8485
## Using Miri
@@ -359,7 +360,7 @@ to Miri failing to detect cases of undefined behavior in a program.
359360
* `-Zmiri-disable-data-race-detector` disables checking for data races. Using
360361
this flag is **unsound**. This implies `-Zmiri-disable-weak-memory-emulation`.
361362
* `-Zmiri-disable-stacked-borrows` disables checking the experimental
362-
aliasing rules to track borrows ([Stacked Borrows] and Tree Borrows).
363+
aliasing rules to track borrows ([Stacked Borrows] and [Tree Borrows]).
363364
This can make Miri run faster, but it also means no aliasing violations will
364365
be detected. Using this flag is **unsound** (but the affected soundness rules
365366
are experimental). Later flags take precedence: borrow tracking can be reactivated
@@ -425,7 +426,7 @@ to Miri failing to detect cases of undefined behavior in a program.
425426
* `-Zmiri-track-weak-memory-loads` shows a backtrace when weak memory emulation returns an outdated
426427
value from a load. This can help diagnose problems that disappear under
427428
`-Zmiri-disable-weak-memory-emulation`.
428-
* `-Zmiri-tree-borrows` replaces [Stacked Borrows] with the Tree Borrows rules.
429+
* `-Zmiri-tree-borrows` replaces [Stacked Borrows] with the [Tree Borrows] rules.
429430
The soundness rules are already experimental without this flag, but even more
430431
so with this flag.
431432
* `-Zmiri-force-page-size=<num>` overrides the default page size for an architecture, in multiples of 1k.
@@ -442,7 +443,7 @@ Some native rustc `-Z` flags are also very relevant for Miri:
442443
functions. This is needed so that Miri can execute such functions, so Miri
443444
sets this flag per default.
444445
* `-Zmir-emit-retag` controls whether `Retag` statements are emitted. Miri
445-
enables this per default because it is needed for [Stacked Borrows] and Tree Borrows.
446+
enables this per default because it is needed for [Stacked Borrows] and [Tree Borrows].
446447

447448
Moreover, Miri recognizes some environment variables:
448449

src/tools/miri/ci.sh

+3-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ function run_tests {
4343
# optimizations up all the way, too).
4444
# Optimizations change diagnostics (mostly backtraces), so we don't check
4545
# them. Also error locations change so we don't run the failing tests.
46-
MIRIFLAGS="${MIRIFLAGS:-} -O -Zmir-opt-level=4" MIRI_SKIP_UI_CHECKS=1 ./miri test -- tests/{pass,panic}
46+
# We explicitly enable debug-assertions here, they are disabled by -O but we have tests
47+
# which exist to check that we panic on debug assertion failures.
48+
MIRIFLAGS="${MIRIFLAGS:-} -O -Zmir-opt-level=4 -Cdebug-assertions=yes" MIRI_SKIP_UI_CHECKS=1 ./miri test -- tests/{pass,panic}
4749

4850
# Also run some many-seeds tests. 64 seeds means this takes around a minute per test.
4951
for FILE in tests/many-seeds/*.rs; do

src/tools/miri/rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
511364e7874dba9649a264100407e4bffe7b5425
1+
d4be8efc6296bace5b1e165f1b34d3c6da76aa8e

src/tools/miri/src/bin/miri.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ use rustc_middle::{
2828
middle::exported_symbols::{
2929
ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
3030
},
31-
ty::{query::ExternProviders, TyCtxt},
3231
query::LocalCrate,
32+
ty::{query::ExternProviders, TyCtxt},
3333
};
34+
use rustc_session::config::OptLevel;
35+
3436
use rustc_session::{config::CrateType, search_paths::PathKind, CtfeBacktrace};
3537

3638
use miri::{BacktraceStyle, BorrowTrackerMethod, ProvenanceMode, RetagFields};
@@ -83,6 +85,21 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
8385
env::set_current_dir(cwd).unwrap();
8486
}
8587

88+
if tcx.sess.opts.optimize != OptLevel::No {
89+
tcx.sess.warn("Miri does not support optimizations. If you have enabled optimizations \
90+
by selecting a Cargo profile (such as --release) which changes other profile settings \
91+
such as whether debug assertions and overflow checks are enabled, those settings are \
92+
still applied.");
93+
}
94+
if tcx.sess.mir_opt_level() > 0 {
95+
tcx.sess.warn("You have explicitly enabled MIR optimizations, overriding Miri's default \
96+
which is to completely disable them. Any optimizations may hide UB that Miri would \
97+
otherwise detect, and it is not necessarily possible to predict what kind of UB will \
98+
be missed. If you are enabling optimizations to make Miri run faster, we advise using \
99+
cfg(miri) to shrink your workload instead. The performance benefit of enabling MIR \
100+
optimizations is usually marginal at best.");
101+
}
102+
86103
if let Some(return_code) = miri::eval_entry(tcx, entry_def_id, entry_type, config) {
87104
std::process::exit(
88105
i32::try_from(return_code).expect("Return value was too large!"),

src/tools/miri/src/clock.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ use std::time::{Duration, Instant as StdInstant};
33

44
/// When using a virtual clock, this defines how many nanoseconds we pretend are passing for each
55
/// basic block.
6-
const NANOSECONDS_PER_BASIC_BLOCK: u64 = 10;
6+
/// This number is pretty random, but it has been shown to approximately cause
7+
/// some sample programs to run within an order of magnitude of real time on desktop CPUs.
8+
/// (See `tests/pass/shims/time-with-isolation*.rs`.)
9+
const NANOSECONDS_PER_BASIC_BLOCK: u64 = 5000;
710

811
#[derive(Debug)]
912
pub struct Instant {

src/tools/miri/src/lib.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,13 @@ pub use crate::tag_gc::{EvalContextExt as _, VisitTags};
124124

125125
/// Insert rustc arguments at the beginning of the argument list that Miri wants to be
126126
/// set per default, for maximal validation power.
127+
/// Also disable the MIR pass that inserts an alignment check on every pointer dereference. Miri
128+
/// does that too, and with a better error message.
127129
pub const MIRI_DEFAULT_ARGS: &[&str] = &[
130+
"--cfg=miri",
128131
"-Zalways-encode-mir",
132+
"-Zextra-const-ub-checks",
129133
"-Zmir-emit-retag",
130134
"-Zmir-opt-level=0",
131-
"--cfg=miri",
132-
"-Cdebug-assertions=on",
133-
"-Zextra-const-ub-checks",
135+
"-Zmir-enable-passes=-CheckAlignment",
134136
];

src/tools/miri/src/shims/panic.rs

+7-13
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
157157
&[catch_unwind.data.into(), payload.into()],
158158
None,
159159
// Directly return to caller of `try`.
160-
StackPopCleanup::Goto { ret: Some(catch_unwind.ret), unwind: mir::UnwindAction::Continue },
160+
StackPopCleanup::Goto {
161+
ret: Some(catch_unwind.ret),
162+
unwind: mir::UnwindAction::Continue,
163+
},
161164
)?;
162165

163166
// We pushed a new stack frame, the engine should not do any jumping now!
@@ -211,10 +214,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
211214
Abi::Rust,
212215
&[index.into(), len.into()],
213216
None,
214-
StackPopCleanup::Goto {
215-
ret: None,
216-
unwind,
217-
},
217+
StackPopCleanup::Goto { ret: None, unwind },
218218
)?;
219219
}
220220
MisalignedPointerDereference { required, found } => {
@@ -235,19 +235,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
235235
Abi::Rust,
236236
&[required.into(), found.into()],
237237
None,
238-
StackPopCleanup::Goto {
239-
ret: None,
240-
unwind,
241-
},
238+
StackPopCleanup::Goto { ret: None, unwind },
242239
)?;
243240
}
244241

245242
_ => {
246243
// Forward everything else to `panic` lang item.
247-
this.start_panic(
248-
msg.description(),
249-
unwind,
250-
)?;
244+
this.start_panic(msg.description(), unwind)?;
251245
}
252246
}
253247
Ok(())

src/tools/miri/src/shims/unix/fs.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -628,13 +628,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
628628
let fd = this.read_scalar(&args[0])?.to_i32()?;
629629
let cmd = this.read_scalar(&args[1])?.to_i32()?;
630630

631-
// Reject if isolation is enabled.
632-
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
633-
this.reject_in_isolation("`fcntl`", reject_with)?;
634-
this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
635-
return Ok(-1);
636-
}
637-
638631
// We only support getting the flags for a descriptor.
639632
if cmd == this.eval_libc_i32("F_GETFD") {
640633
// Currently this is the only flag that `F_GETFD` returns. It is OK to just return the
@@ -677,6 +670,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
677670
None => this.handle_not_found(),
678671
}
679672
} else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC") {
673+
// Reject if isolation is enabled.
674+
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
675+
this.reject_in_isolation("`fcntl`", reject_with)?;
676+
this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
677+
return Ok(-1);
678+
}
679+
680680
if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
681681
// FIXME: Support fullfsync for all FDs
682682
let FileHandle { file, writable } =

src/tools/miri/tests/fail/terminate-terminator.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
warning: You have explicitly enabled MIR optimizations, overriding Miri's default which is to completely disable them. Any optimizations may hide UB that Miri would otherwise detect, and it is not necessarily possible to predict what kind of UB will be missed. If you are enabling optimizations to make Miri run faster, we advise using cfg(miri) to shrink your workload instead. The performance benefit of enabling MIR optimizations is usually marginal at best.
2+
13
thread 'main' panicked at 'explicit panic', $DIR/terminate-terminator.rs:LL:CC
24
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
35
error: abnormal termination: panic in a function that cannot unwind
@@ -23,5 +25,5 @@ LL | panic_abort();
2325

2426
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
2527

26-
error: aborting due to previous error
28+
error: aborting due to previous error; 1 warning emitted
2729

src/tools/miri/tests/panic/alignment-assertion.rs

-9
This file was deleted.

src/tools/miri/tests/panic/alignment-assertion.stderr

-2
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//@only-target-apple: F_FULLFSYNC only on apple systems
2+
//@compile-flags: -Zmiri-isolation-error=warn-nobacktrace
3+
4+
use std::io::Error;
5+
6+
fn main() {
7+
// test `fcntl(F_FULLFSYNC)`
8+
unsafe {
9+
assert_eq!(libc::fcntl(1, libc::F_FULLFSYNC, 0), -1);
10+
assert_eq!(Error::last_os_error().raw_os_error(), Some(libc::EPERM));
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
warning: `fcntl` was made to return an error due to isolation
2+

src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ use std::fs;
77
use std::io::{Error, ErrorKind};
88

99
fn main() {
10-
// test `fcntl`
10+
// test `fcntl(F_DUPFD): should work even with isolation.`
1111
unsafe {
12-
assert_eq!(libc::fcntl(1, libc::F_DUPFD, 0), -1);
13-
assert_eq!(Error::last_os_error().raw_os_error(), Some(libc::EPERM));
12+
assert!(libc::fcntl(1, libc::F_DUPFD, 0) >= 0);
1413
}
1514

1615
// test `readlink`

src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.stderr

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
warning: `fcntl` was made to return an error due to isolation
2-
31
warning: `readlink` was made to return an error due to isolation
42

53
warning: `$STAT` was made to return an error due to isolation
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//@compile-flags: -Zmiri-disable-isolation -Zmiri-permissive-provenance -Zmiri-backtrace=full
1+
//@compile-flags: -Zmiri-permissive-provenance -Zmiri-backtrace=full
22
//@only-target-x86_64-unknown-linux: support for tokio only on linux and x86
33

44
use tokio::time::{sleep, Duration, Instant};
@@ -7,8 +7,6 @@ use tokio::time::{sleep, Duration, Instant};
77
async fn main() {
88
let start = Instant::now();
99
sleep(Duration::from_secs(1)).await;
10-
// It takes 96 millisecond to sleep for 1 millisecond
11-
// It takes 1025 millisecond to sleep for 1 second
1210
let time_elapsed = &start.elapsed().as_millis();
13-
assert!(time_elapsed > &1000, "{}", time_elapsed);
11+
assert!((1000..1100).contains(time_elapsed), "{}", time_elapsed);
1412
}

src/tools/miri/tests/pass-dep/tokio/tokio_mvp.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Need to disable preemption to stay on the supported MVP codepath in mio.
2-
//@compile-flags: -Zmiri-disable-isolation -Zmiri-permissive-provenance
2+
//@compile-flags: -Zmiri-permissive-provenance
33
//@only-target-x86_64-unknown-linux: support for tokio exists only on linux and x86
44

55
#[tokio::main]

src/tools/miri/tests/pass/concurrency/thread_park_isolated.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ fn main() {
77

88
thread::park_timeout(Duration::from_millis(200));
99

10-
// Thanks to deterministic execution, this will wiat *exactly* 200ms (rounded to 1ms).
11-
assert!((200..201).contains(&start.elapsed().as_millis()));
10+
// Thanks to deterministic execution, this will wait *exactly* 200ms, plus the time for the surrounding code.
11+
assert!((200..210).contains(&start.elapsed().as_millis()), "{}", start.elapsed().as_millis());
1212
}

src/tools/miri/tests/pass/shims/time-with-isolation.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,23 @@ fn test_time_passes() {
2222
let diff = now2.duration_since(now1);
2323
assert_eq!(now1 + diff, now2);
2424
assert_eq!(now2 - diff, now1);
25-
// The virtual clock is deterministic and I got 29us on a 64-bit Linux machine. However, this
25+
// The virtual clock is deterministic and I got 15ms on a 64-bit Linux machine. However, this
2626
// changes according to the platform so we use an interval to be safe. This should be updated
2727
// if `NANOSECONDS_PER_BASIC_BLOCK` changes.
28-
assert!(diff.as_micros() > 10);
29-
assert!(diff.as_micros() < 40);
28+
assert!(diff.as_millis() > 5);
29+
assert!(diff.as_millis() < 20);
30+
}
31+
32+
fn test_block_for_one_second() {
33+
let end = Instant::now() + Duration::from_secs(1);
34+
// This takes a long time, as we only increment when statements are executed.
35+
// When we sleep on all threads, we fast forward to the sleep duration, which we can't
36+
// do with busy waiting.
37+
while Instant::now() < end {}
3038
}
3139

3240
fn main() {
3341
test_time_passes();
42+
test_block_for_one_second();
3443
test_sleep();
3544
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use std::time::Instant;
2+
3+
fn main() {
4+
let begin = Instant::now();
5+
for _ in 0..100_000 {}
6+
let time = begin.elapsed();
7+
println!("The loop took around {}s", time.as_secs());
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The loop took around 13s

0 commit comments

Comments
 (0)