Skip to content

Commit f9bac9e

Browse files
authored
Rollup merge of #139065 - RalfJung:miri-sync, r=RalfJung
Miri subtree update r? `@ghost`
2 parents 41b7379 + a7ca21c commit f9bac9e

24 files changed

+231
-66
lines changed

Diff for: .github/workflows/sysroots.yml

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ jobs:
1616
- uses: actions/checkout@v4
1717
- name: Build the sysroots
1818
run: |
19+
rustup toolchain install nightly
1920
cargo install -f rustup-toolchain-install-master
2021
./miri toolchain -c rust-docs # Docs are the only place targets are separated by tier
2122
./miri install

Diff for: Cargo.lock

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ windows-sys = { version = "0.52", features = [
4747
] }
4848

4949
[dev-dependencies]
50-
ui_test = "0.28.0"
50+
ui_test = "0.29.1"
5151
colored = "2"
5252
rustc_version = "0.4"
5353
regex = "1.5.5"

Diff for: README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,7 @@ inherent interpreter slowdown and a loss of parallelism.
237237
You can get your test suite's parallelism back by running `cargo miri nextest run -jN`
238238
(note that you will need [`cargo-nextest`](https://nexte.st) installed).
239239
This works because `cargo-nextest` collects a list of all tests then launches a
240-
separate `cargo miri run` for each test. You will need to specify a `-j` or `--test-threads`;
241-
by default `cargo miri nextest run` runs one test at a time. For more details, see the
240+
separate `cargo miri run` for each test. For more information about nextest, see the
242241
[`cargo-nextest` Miri documentation](https://nexte.st/book/miri.html).
243242

244243
Note: This one-test-per-process model means that `cargo miri test` is able to detect data
@@ -432,7 +431,8 @@ to Miri failing to detect cases of undefined behavior in a program.
432431
* `-Zmiri-track-weak-memory-loads` shows a backtrace when weak memory emulation returns an outdated
433432
value from a load. This can help diagnose problems that disappear under
434433
`-Zmiri-disable-weak-memory-emulation`.
435-
* `-Zmiri-tree-borrows` replaces [Stacked Borrows] with the [Tree Borrows] rules.
434+
* <a name="-Zmiri-tree-borrows"><!-- The playground links here --></a>
435+
`-Zmiri-tree-borrows` replaces [Stacked Borrows] with the [Tree Borrows] rules.
436436
Tree Borrows is even more experimental than Stacked Borrows. While Tree Borrows
437437
is still sound in the sense of catching all aliasing violations that current versions
438438
of the compiler might exploit, it is likely that the eventual final aliasing model

Diff for: bench-cargo-miri/mse/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ fn main() {
1010
}
1111

1212
fn read_i16(buffer: &[u8], index: usize) -> i16 {
13-
const SIZE: usize = std::mem::size_of::<i16>();
13+
const SIZE: usize = size_of::<i16>();
1414
let mut bytes: [u8; SIZE] = [0u8; SIZE];
1515
bytes.copy_from_slice(&buffer[(index * SIZE)..(index * SIZE + SIZE)]);
1616
unsafe { std::mem::transmute(bytes) }

Diff for: cargo-miri/src/phases.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
467467
if let Some(i) = val.iter().position(|&s| s == "link") {
468468
emit_link_hack = true;
469469
val.remove(i);
470-
if !val.iter().any(|&s| s == "metadata") {
470+
if !val.contains(&"metadata") {
471471
val.push("metadata");
472472
}
473473
}

Diff for: ci/ci.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ case $HOST_TARGET in
166166
UNIX="hello panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there
167167
TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe
168168
TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe
169-
TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread epoll eventfd
169+
TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync concurrency thread epoll eventfd
170170
TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm
171171
TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std
172172
TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std

Diff for: rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
f5729cfed3c45e061e8a443677fc1d5ef9277df7
1+
4ac032f857b46037b55c1fc0fa702450aad37f43

Diff for: src/alloc_addresses/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -170,20 +170,22 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
170170
// This ensures the interpreted program and native code have the same view of memory.
171171
let base_ptr = match info.kind {
172172
AllocKind::LiveData => {
173-
if this.tcx.try_get_global_alloc(alloc_id).is_some() {
173+
if memory_kind == MiriMemoryKind::Global.into() {
174174
// For new global allocations, we always pre-allocate the memory to be able use the machine address directly.
175175
let prepared_bytes = MiriAllocBytes::zeroed(info.size, info.align)
176176
.unwrap_or_else(|| {
177177
panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes", size = info.size)
178178
});
179179
let ptr = prepared_bytes.as_ptr();
180-
// Store prepared allocation space to be picked up for use later.
180+
// Store prepared allocation to be picked up for use later.
181181
global_state
182182
.prepared_alloc_bytes
183183
.try_insert(alloc_id, prepared_bytes)
184184
.unwrap();
185185
ptr
186186
} else {
187+
// Non-global allocations are already in memory at this point so
188+
// we can just get a pointer to where their data is stored.
187189
this.get_alloc_bytes_unchecked_raw(alloc_id)?
188190
}
189191
}
@@ -381,6 +383,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
381383
align: Align,
382384
) -> InterpResult<'tcx, MiriAllocBytes> {
383385
let this = self.eval_context_ref();
386+
assert!(this.tcx.try_get_global_alloc(id).is_some());
384387
if this.machine.native_lib.is_some() {
385388
// In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`.
386389
// This additional call ensures that some `MiriAllocBytes` are always prepared, just in case

Diff for: src/concurrency/thread.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1150,7 +1150,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
11501150
loop {
11511151
if CTRL_C_RECEIVED.load(Relaxed) {
11521152
this.machine.handle_abnormal_termination();
1153-
std::process::exit(1);
1153+
throw_machine_stop!(TerminationInfo::Interrupted);
11541154
}
11551155
match this.machine.threads.schedule(&this.machine.clock)? {
11561156
SchedulingAction::ExecuteStep => {

Diff for: src/diagnostics.rs

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ pub enum TerminationInfo {
1616
leak_check: bool,
1717
},
1818
Abort(String),
19+
/// Miri was interrupted by a Ctrl+C from the user
20+
Interrupted,
1921
UnsupportedInIsolation(String),
2022
StackedBorrowsUb {
2123
msg: String,
@@ -63,6 +65,7 @@ impl fmt::Display for TerminationInfo {
6365
match self {
6466
Exit { code, .. } => write!(f, "the evaluated program completed with exit code {code}"),
6567
Abort(msg) => write!(f, "{msg}"),
68+
Interrupted => write!(f, "interpretation was interrupted"),
6669
UnsupportedInIsolation(msg) => write!(f, "{msg}"),
6770
Int2PtrWithStrictProvenance =>
6871
write!(
@@ -226,6 +229,7 @@ pub fn report_error<'tcx>(
226229
let title = match info {
227230
&Exit { code, leak_check } => return Some((code, leak_check)),
228231
Abort(_) => Some("abnormal termination"),
232+
Interrupted => None,
229233
UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance | UnsupportedForeignItem(_) =>
230234
Some("unsupported operation"),
231235
StackedBorrowsUb { .. } | TreeBorrowsUb { .. } | DataRace { .. } =>

Diff for: src/eval.rs

-1
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,6 @@ pub fn create_ecx<'tcx>(
434434
/// Evaluates the entry function specified by `entry_id`.
435435
/// Returns `Some(return_code)` if program execution completed.
436436
/// Returns `None` if an evaluation error occurred.
437-
#[expect(clippy::needless_lifetimes)]
438437
pub fn eval_entry<'tcx>(
439438
tcx: TyCtxt<'tcx>,
440439
entry_id: DefId,

Diff for: src/helpers.rs

+89-5
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
1414
use rustc_middle::middle::dependency_format::Linkage;
1515
use rustc_middle::middle::exported_symbols::ExportedSymbol;
1616
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, MaybeResult, TyAndLayout};
17-
use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, UintTy};
17+
use rustc_middle::ty::{self, Binder, FloatTy, FnSig, IntTy, Ty, TyCtxt, UintTy};
1818
use rustc_session::config::CrateType;
1919
use rustc_span::{Span, Symbol};
20+
use rustc_symbol_mangling::mangle_internal_symbol;
2021
use rustc_target::callconv::{Conv, FnAbi};
2122

2223
use crate::*;
@@ -994,10 +995,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
994995
exp_abi: Conv,
995996
link_name: Symbol,
996997
args: &'a [OpTy<'tcx>],
997-
) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]>
998-
where
999-
&'a [OpTy<'tcx>; N]: TryFrom<&'a [OpTy<'tcx>]>,
1000-
{
998+
) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> {
1001999
self.check_abi_and_shim_symbol_clash(abi, exp_abi, link_name)?;
10021000

10031001
if abi.c_variadic {
@@ -1015,6 +1013,80 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
10151013
)
10161014
}
10171015

1016+
/// Check that the given `caller_fn_abi` matches the expected ABI described by
1017+
/// `callee_abi`, `callee_input_tys`, `callee_output_ty`, and the return the list of
1018+
/// arguments.
1019+
fn check_shim_abi<'a, const N: usize>(
1020+
&mut self,
1021+
link_name: Symbol,
1022+
caller_fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
1023+
callee_abi: ExternAbi,
1024+
callee_input_tys: [Ty<'tcx>; N],
1025+
callee_output_ty: Ty<'tcx>,
1026+
caller_args: &'a [OpTy<'tcx>],
1027+
) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> {
1028+
let this = self.eval_context_mut();
1029+
let mut inputs_and_output = callee_input_tys.to_vec();
1030+
inputs_and_output.push(callee_output_ty);
1031+
let fn_sig_binder = Binder::dummy(FnSig {
1032+
inputs_and_output: this.machine.tcx.mk_type_list(&inputs_and_output),
1033+
c_variadic: false,
1034+
// This does not matter for the ABI.
1035+
safety: Safety::Safe,
1036+
abi: callee_abi,
1037+
});
1038+
let callee_fn_abi = this.fn_abi_of_fn_ptr(fn_sig_binder, Default::default())?;
1039+
1040+
this.check_abi_and_shim_symbol_clash(caller_fn_abi, callee_fn_abi.conv, link_name)?;
1041+
1042+
if caller_fn_abi.c_variadic {
1043+
throw_ub_format!(
1044+
"ABI mismatch: calling a non-variadic function with a variadic caller-side signature"
1045+
);
1046+
}
1047+
1048+
if callee_fn_abi.fixed_count != caller_fn_abi.fixed_count {
1049+
throw_ub_format!(
1050+
"ABI mismatch: expected {} arguments, found {} arguments ",
1051+
callee_fn_abi.fixed_count,
1052+
caller_fn_abi.fixed_count
1053+
);
1054+
}
1055+
1056+
if callee_fn_abi.can_unwind && !caller_fn_abi.can_unwind {
1057+
throw_ub_format!(
1058+
"ABI mismatch: callee may unwind, but caller-side signature prohibits unwinding",
1059+
);
1060+
}
1061+
1062+
if !this.check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret)? {
1063+
throw_ub!(AbiMismatchReturn {
1064+
caller_ty: caller_fn_abi.ret.layout.ty,
1065+
callee_ty: callee_fn_abi.ret.layout.ty
1066+
});
1067+
}
1068+
1069+
if let Some(index) = caller_fn_abi
1070+
.args
1071+
.iter()
1072+
.zip(callee_fn_abi.args.iter())
1073+
.map(|(caller_arg, callee_arg)| this.check_argument_compat(caller_arg, callee_arg))
1074+
.collect::<InterpResult<'tcx, Vec<bool>>>()?
1075+
.into_iter()
1076+
.position(|b| !b)
1077+
{
1078+
throw_ub!(AbiMismatchArgument {
1079+
caller_ty: caller_fn_abi.args[index].layout.ty,
1080+
callee_ty: callee_fn_abi.args[index].layout.ty
1081+
});
1082+
}
1083+
1084+
if let Ok(ops) = caller_args.try_into() {
1085+
return interp_ok(ops);
1086+
}
1087+
unreachable!()
1088+
}
1089+
10181090
/// Check shim for variadic function.
10191091
/// Returns a tuple that consisting of an array of fixed args, and a slice of varargs.
10201092
fn check_shim_variadic<'a, const N: usize>(
@@ -1187,6 +1259,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
11871259

11881260
interp_ok(array)
11891261
}
1262+
1263+
fn mangle_internal_symbol<'a>(&'a mut self, name: &'static str) -> &'a str
1264+
where
1265+
'tcx: 'a,
1266+
{
1267+
let this = self.eval_context_mut();
1268+
let tcx = *this.tcx;
1269+
this.machine
1270+
.mangle_internal_symbol_cache
1271+
.entry(name)
1272+
.or_insert_with(|| mangle_internal_symbol(tcx, name))
1273+
}
11901274
}
11911275

11921276
impl<'tcx> MiriMachine<'tcx> {

Diff for: src/machine.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,9 @@ pub struct MiriMachine<'tcx> {
611611
pub(crate) reject_in_isolation_warned: RefCell<FxHashSet<String>>,
612612
/// Remembers which int2ptr casts we have already warned about.
613613
pub(crate) int2ptr_warned: RefCell<FxHashSet<Span>>,
614+
615+
/// Cache for `mangle_internal_symbol`.
616+
pub(crate) mangle_internal_symbol_cache: FxHashMap<&'static str, String>,
614617
}
615618

616619
impl<'tcx> MiriMachine<'tcx> {
@@ -757,6 +760,7 @@ impl<'tcx> MiriMachine<'tcx> {
757760
native_call_mem_warned: Cell::new(false),
758761
reject_in_isolation_warned: Default::default(),
759762
int2ptr_warned: Default::default(),
763+
mangle_internal_symbol_cache: Default::default(),
760764
}
761765
}
762766

@@ -930,6 +934,7 @@ impl VisitProvenance for MiriMachine<'_> {
930934
native_call_mem_warned: _,
931935
reject_in_isolation_warned: _,
932936
int2ptr_warned: _,
937+
mangle_internal_symbol_cache: _,
933938
} = self;
934939

935940
threads.visit_provenance(visit);
@@ -1540,7 +1545,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
15401545
fn before_terminator(ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> {
15411546
ecx.machine.basic_block_count += 1u64; // a u64 that is only incremented by 1 will "never" overflow
15421547
ecx.machine.since_gc += 1;
1543-
// Possibly report our progress.
1548+
// Possibly report our progress. This will point at the terminator we are about to execute.
15441549
if let Some(report_progress) = ecx.machine.report_progress {
15451550
if ecx.machine.basic_block_count % u64::from(report_progress) == 0 {
15461551
ecx.emit_diagnostic(NonHaltingDiagnostic::ProgressReport {
@@ -1559,6 +1564,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
15591564
}
15601565

15611566
// These are our preemption points.
1567+
// (This will only take effect after the terminator has been executed.)
15621568
ecx.maybe_preempt_active_thread();
15631569

15641570
// Make sure some time passes.

0 commit comments

Comments
 (0)