Skip to content

Commit 0ea334a

Browse files
committed
Auto merge of #120451 - RalfJung:miri, r=RalfJung
Miri subtree update r? `@ghost`
2 parents 7e43442 + 71f8f49 commit 0ea334a

File tree

17 files changed

+235
-172
lines changed

17 files changed

+235
-172
lines changed

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
name: Tier 2 sysroots
22

3-
on: push
4-
# schedule:
5-
# - cron: '44 4 * * *' # At 4:44 UTC every day.
3+
on:
4+
schedule:
5+
- cron: '44 4 * * *' # At 4:44 UTC every day.
66

77
defaults:
88
run:

src/tools/miri/Cargo.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -486,9 +486,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
486486

487487
[[package]]
488488
name = "measureme"
489-
version = "10.1.2"
489+
version = "11.0.1"
490490
source = "registry+https://github.com/rust-lang/crates.io-index"
491-
checksum = "45e381dcdad44c3c435f8052b08c5c4a1449c48ab56f312345eae12d7a693dbe"
491+
checksum = "dfa4a40f09af7aa6faef38285402a78847d0d72bf8827006cd2a332e1e6e4a8d"
492492
dependencies = [
493493
"log",
494494
"memmap2",

src/tools/miri/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,7 @@ Definite bugs found:
590590
* [Incorrect use of `compare_exchange_weak` in `once_cell`](https://github.com/matklad/once_cell/issues/186)
591591
* [Dropping with unaligned pointers in `vec::IntoIter`](https://github.com/rust-lang/rust/pull/106084)
592592
* [Deallocating with the wrong layout in new specializations for in-place `Iterator::collect`](https://github.com/rust-lang/rust/pull/118460)
593+
* [Incorrect offset computation for highly-aligned types in `portable-atomic-util`](https://github.com/taiki-e/portable-atomic/pull/138)
593594

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

src/tools/miri/cargo-miri/src/phases.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -501,11 +501,10 @@ pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: Runner
501501
// Set missing env vars. We prefer build-time env vars over run-time ones; see
502502
// <https://github.com/rust-lang/miri/issues/1661> for the kind of issue that fixes.
503503
for (name, val) in info.env {
504-
// `CARGO_MAKEFLAGS` contains information about how to reach the
505-
// jobserver, but by the time the program is being run, that jobserver
506-
// no longer exists. Hence we shouldn't forward this.
507-
// FIXME: Miri builds the final crate without a jobserver.
508-
// This may be fixed with github.com/rust-lang/cargo/issues/12597.
504+
// `CARGO_MAKEFLAGS` contains information about how to reach the jobserver, but by the time
505+
// the program is being run, that jobserver no longer exists (cargo only runs the jobserver
506+
// for the build portion of `cargo run`/`cargo test`). Hence we shouldn't forward this.
507+
// Also see <https://github.com/rust-lang/rust/pull/113730>.
509508
if name == "CARGO_MAKEFLAGS" {
510509
continue;
511510
}

src/tools/miri/rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
5bcd86d89b2b7b6a490f7e075dd4eb346deb5f98
1+
dd2559e08e1530806740931037d6bb83ef956161

src/tools/miri/src/helpers.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
217217

218218
/// Helper function to get a `windows` constant as a `Scalar`.
219219
fn eval_windows(&self, module: &str, name: &str) -> Scalar<Provenance> {
220-
self.eval_context_ref().eval_path_scalar(&["std", "sys", "pal","windows", module, name])
220+
self.eval_context_ref().eval_path_scalar(&["std", "sys", "pal", "windows", module, name])
221221
}
222222

223223
/// Helper function to get a `windows` constant as a `u32`.
@@ -249,7 +249,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
249249
fn windows_ty_layout(&self, name: &str) -> TyAndLayout<'tcx> {
250250
let this = self.eval_context_ref();
251251
let ty = this
252-
.resolve_path(&["std", "sys", "pal","windows", "c", name], Namespace::TypeNS)
252+
.resolve_path(&["std", "sys", "pal", "windows", "c", name], Namespace::TypeNS)
253253
.ty(*this.tcx, ty::ParamEnv::reveal_all());
254254
this.layout_of(ty).unwrap()
255255
}
@@ -270,6 +270,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
270270
bug!("No field named {} in type {}", name, base.layout().ty);
271271
}
272272

273+
/// Search if `base` (which must be a struct or union type) contains the `name` field.
274+
fn projectable_has_field<P: Projectable<'tcx, Provenance>>(
275+
&self,
276+
base: &P,
277+
name: &str,
278+
) -> bool {
279+
let adt = base.layout().ty.ty_adt_def().unwrap();
280+
for field in adt.non_enum_variant().fields.iter() {
281+
if field.name.as_str() == name {
282+
return true;
283+
}
284+
}
285+
false
286+
}
287+
273288
/// Write an int of the appropriate size to `dest`. The target type may be signed or unsigned,
274289
/// we try to do the right thing anyway. `i128` can fit all integer types except for `u128` so
275290
/// this method is fine for almost all integer types.

src/tools/miri/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ pub use crate::shims::os_str::EvalContextExt as _;
9494
pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _};
9595
pub use crate::shims::time::EvalContextExt as _;
9696
pub use crate::shims::tls::TlsData;
97-
pub use crate::shims::EvalContextExt as _;
9897

9998
pub use crate::borrow_tracker::stacked_borrows::{
10099
EvalContextExt as _, Item, Permission, Stack, Stacks,

src/tools/miri/src/machine.rs

+21-74
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use std::process;
1010

1111
use either::Either;
1212
use rand::rngs::StdRng;
13-
use rand::SeedableRng;
1413
use rand::Rng;
14+
use rand::SeedableRng;
1515

1616
use rustc_ast::ast::Mutability;
1717
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -83,7 +83,8 @@ pub struct FrameExtra<'tcx> {
8383
impl<'tcx> std::fmt::Debug for FrameExtra<'tcx> {
8484
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8585
// Omitting `timing`, it does not support `Debug`.
86-
let FrameExtra { borrow_tracker, catch_unwind, timing: _, is_user_relevant: _, salt: _ } = self;
86+
let FrameExtra { borrow_tracker, catch_unwind, timing: _, is_user_relevant: _, salt: _ } =
87+
self;
8788
f.debug_struct("FrameData")
8889
.field("borrow_tracker", borrow_tracker)
8990
.field("catch_unwind", catch_unwind)
@@ -93,7 +94,8 @@ impl<'tcx> std::fmt::Debug for FrameExtra<'tcx> {
9394

9495
impl VisitProvenance for FrameExtra<'_> {
9596
fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
96-
let FrameExtra { catch_unwind, borrow_tracker, timing: _, is_user_relevant: _, salt: _ } = self;
97+
let FrameExtra { catch_unwind, borrow_tracker, timing: _, is_user_relevant: _, salt: _ } =
98+
self;
9799

98100
catch_unwind.visit_provenance(visit);
99101
borrow_tracker.visit_provenance(visit);
@@ -710,7 +712,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
710712
Ok(())
711713
}
712714

713-
fn add_extern_static(
715+
pub(crate) fn add_extern_static(
714716
this: &mut MiriInterpCx<'mir, 'tcx>,
715717
name: &str,
716718
ptr: Pointer<Option<Provenance>>,
@@ -720,75 +722,6 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
720722
this.machine.extern_statics.try_insert(Symbol::intern(name), ptr).unwrap();
721723
}
722724

723-
fn alloc_extern_static(
724-
this: &mut MiriInterpCx<'mir, 'tcx>,
725-
name: &str,
726-
val: ImmTy<'tcx, Provenance>,
727-
) -> InterpResult<'tcx> {
728-
let place = this.allocate(val.layout, MiriMemoryKind::ExternStatic.into())?;
729-
this.write_immediate(*val, &place)?;
730-
Self::add_extern_static(this, name, place.ptr());
731-
Ok(())
732-
}
733-
734-
/// Sets up the "extern statics" for this machine.
735-
fn init_extern_statics(this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
736-
// "__rust_no_alloc_shim_is_unstable"
737-
let val = ImmTy::from_int(0, this.machine.layouts.u8);
738-
Self::alloc_extern_static(this, "__rust_no_alloc_shim_is_unstable", val)?;
739-
740-
match this.tcx.sess.target.os.as_ref() {
741-
"linux" => {
742-
// "environ"
743-
Self::add_extern_static(
744-
this,
745-
"environ",
746-
this.machine.env_vars.environ.as_ref().unwrap().ptr(),
747-
);
748-
// A couple zero-initialized pointer-sized extern statics.
749-
// Most of them are for weak symbols, which we all set to null (indicating that the
750-
// symbol is not supported, and triggering fallback code which ends up calling a
751-
// syscall that we do support).
752-
for name in &["__cxa_thread_atexit_impl", "getrandom", "statx", "__clock_gettime64"]
753-
{
754-
let val = ImmTy::from_int(0, this.machine.layouts.usize);
755-
Self::alloc_extern_static(this, name, val)?;
756-
}
757-
}
758-
"freebsd" => {
759-
// "environ"
760-
Self::add_extern_static(
761-
this,
762-
"environ",
763-
this.machine.env_vars.environ.as_ref().unwrap().ptr(),
764-
);
765-
}
766-
"android" => {
767-
// "signal" -- just needs a non-zero pointer value (function does not even get called),
768-
// but we arrange for this to be callable anyway (it will then do nothing).
769-
let layout = this.machine.layouts.const_raw_ptr;
770-
let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str("signal")));
771-
let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout);
772-
Self::alloc_extern_static(this, "signal", val)?;
773-
// A couple zero-initialized pointer-sized extern statics.
774-
// Most of them are for weak symbols, which we all set to null (indicating that the
775-
// symbol is not supported, and triggering fallback code.)
776-
for name in &["bsd_signal"] {
777-
let val = ImmTy::from_int(0, this.machine.layouts.usize);
778-
Self::alloc_extern_static(this, name, val)?;
779-
}
780-
}
781-
"windows" => {
782-
// "_tls_used"
783-
// This is some obscure hack that is part of the Windows TLS story. It's a `u8`.
784-
let val = ImmTy::from_int(0, this.machine.layouts.u8);
785-
Self::alloc_extern_static(this, "_tls_used", val)?;
786-
}
787-
_ => {} // No "extern statics" supported on this target
788-
}
789-
Ok(())
790-
}
791-
792725
pub(crate) fn communicate(&self) -> bool {
793726
self.isolated_op == IsolatedOp::Allow
794727
}
@@ -1009,7 +942,21 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
1009942
ret: Option<mir::BasicBlock>,
1010943
unwind: mir::UnwindAction,
1011944
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
1012-
ecx.find_mir_or_eval_fn(instance, abi, args, dest, ret, unwind)
945+
// For foreign items, try to see if we can emulate them.
946+
if ecx.tcx.is_foreign_item(instance.def_id()) {
947+
// An external function call that does not have a MIR body. We either find MIR elsewhere
948+
// or emulate its effect.
949+
// This will be Ok(None) if we're emulating the intrinsic entirely within Miri (no need
950+
// to run extra MIR), and Ok(Some(body)) if we found MIR to run for the
951+
// foreign function
952+
// Any needed call to `goto_block` will be performed by `emulate_foreign_item`.
953+
let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit?
954+
let link_name = ecx.item_link_name(instance.def_id());
955+
return ecx.emulate_foreign_item(link_name, abi, &args, dest, ret, unwind);
956+
}
957+
958+
// Otherwise, load the MIR.
959+
Ok(Some((ecx.load_mir(instance.def, None)?, instance)))
1013960
}
1014961

1015962
#[inline(always)]

src/tools/miri/src/operator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
2424

2525
Ok(match bin_op {
2626
Eq | Ne | Lt | Le | Gt | Ge => {
27-
assert_eq!(left.layout.abi, right.layout.abi); // types an differ, e.g. fn ptrs with different `for`
27+
assert_eq!(left.layout.abi, right.layout.abi); // types can differ, e.g. fn ptrs with different `for`
2828
let size = this.pointer_size();
2929
// Just compare the bits. ScalarPairs are compared lexicographically.
3030
// We thus always compare pairs and simply fill scalars up with 0.
+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//! Provides the `extern static` that this platform expects.
2+
3+
use crate::*;
4+
5+
impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
6+
fn alloc_extern_static(
7+
this: &mut MiriInterpCx<'mir, 'tcx>,
8+
name: &str,
9+
val: ImmTy<'tcx, Provenance>,
10+
) -> InterpResult<'tcx> {
11+
let place = this.allocate(val.layout, MiriMemoryKind::ExternStatic.into())?;
12+
this.write_immediate(*val, &place)?;
13+
Self::add_extern_static(this, name, place.ptr());
14+
Ok(())
15+
}
16+
17+
/// Zero-initialized pointer-sized extern statics are pretty common.
18+
/// Most of them are for weak symbols, which we all set to null (indicating that the
19+
/// symbol is not supported, and triggering fallback code which ends up calling a
20+
/// syscall that we do support).
21+
fn null_ptr_extern_statics(
22+
this: &mut MiriInterpCx<'mir, 'tcx>,
23+
names: &[&str],
24+
) -> InterpResult<'tcx> {
25+
for name in names {
26+
let val = ImmTy::from_int(0, this.machine.layouts.usize);
27+
Self::alloc_extern_static(this, name, val)?;
28+
}
29+
Ok(())
30+
}
31+
32+
/// Sets up the "extern statics" for this machine.
33+
pub fn init_extern_statics(this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
34+
// "__rust_no_alloc_shim_is_unstable"
35+
let val = ImmTy::from_int(0, this.machine.layouts.u8);
36+
Self::alloc_extern_static(this, "__rust_no_alloc_shim_is_unstable", val)?;
37+
38+
match this.tcx.sess.target.os.as_ref() {
39+
"linux" => {
40+
Self::null_ptr_extern_statics(
41+
this,
42+
&["__cxa_thread_atexit_impl", "getrandom", "statx", "__clock_gettime64"],
43+
)?;
44+
// "environ"
45+
Self::add_extern_static(
46+
this,
47+
"environ",
48+
this.machine.env_vars.environ.as_ref().unwrap().ptr(),
49+
);
50+
}
51+
"freebsd" => {
52+
Self::null_ptr_extern_statics(this, &["__cxa_thread_atexit_impl"])?;
53+
// "environ"
54+
Self::add_extern_static(
55+
this,
56+
"environ",
57+
this.machine.env_vars.environ.as_ref().unwrap().ptr(),
58+
);
59+
}
60+
"android" => {
61+
Self::null_ptr_extern_statics(this, &["bsd_signal"])?;
62+
// "signal" -- just needs a non-zero pointer value (function does not even get called),
63+
// but we arrange for this to call the `signal` function anyway.
64+
let layout = this.machine.layouts.const_raw_ptr;
65+
let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str("signal")));
66+
let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout);
67+
Self::alloc_extern_static(this, "signal", val)?;
68+
}
69+
"windows" => {
70+
// "_tls_used"
71+
// This is some obscure hack that is part of the Windows TLS story. It's a `u8`.
72+
let val = ImmTy::from_int(0, this.machine.layouts.u8);
73+
Self::alloc_extern_static(this, "_tls_used", val)?;
74+
}
75+
_ => {} // No "extern statics" supported on this target
76+
}
77+
Ok(())
78+
}
79+
}

src/tools/miri/src/shims/intrinsics/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
148148
// ```
149149
// Would not be considered UB, or the other way around (`is_val_statically_known(0)`).
150150
"is_val_statically_known" => {
151-
let [_] = check_arg_count(args)?;
151+
let [arg] = check_arg_count(args)?;
152+
this.validate_operand(arg)?;
152153
let branch: bool = this.machine.rng.get_mut().gen();
153154
this.write_scalar(Scalar::from_bool(branch), dest)?;
154155
}

src/tools/miri/src/shims/mod.rs

+1-41
Original file line numberDiff line numberDiff line change
@@ -10,48 +10,8 @@ pub mod windows;
1010
mod x86;
1111

1212
pub mod env;
13+
pub mod extern_static;
1314
pub mod os_str;
1415
pub mod panic;
1516
pub mod time;
1617
pub mod tls;
17-
18-
// End module management, begin local code
19-
20-
use log::trace;
21-
22-
use rustc_middle::{mir, ty};
23-
use rustc_target::spec::abi::Abi;
24-
25-
use crate::*;
26-
27-
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
28-
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
29-
fn find_mir_or_eval_fn(
30-
&mut self,
31-
instance: ty::Instance<'tcx>,
32-
abi: Abi,
33-
args: &[FnArg<'tcx, Provenance>],
34-
dest: &PlaceTy<'tcx, Provenance>,
35-
ret: Option<mir::BasicBlock>,
36-
unwind: mir::UnwindAction,
37-
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
38-
let this = self.eval_context_mut();
39-
trace!("eval_fn_call: {:#?}, {:?}", instance, dest);
40-
41-
// For foreign items, try to see if we can emulate them.
42-
if this.tcx.is_foreign_item(instance.def_id()) {
43-
// An external function call that does not have a MIR body. We either find MIR elsewhere
44-
// or emulate its effect.
45-
// This will be Ok(None) if we're emulating the intrinsic entirely within Miri (no need
46-
// to run extra MIR), and Ok(Some(body)) if we found MIR to run for the
47-
// foreign function
48-
// Any needed call to `goto_block` will be performed by `emulate_foreign_item`.
49-
let args = this.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit?
50-
let link_name = this.item_link_name(instance.def_id());
51-
return this.emulate_foreign_item(link_name, abi, &args, dest, ret, unwind);
52-
}
53-
54-
// Otherwise, load the MIR.
55-
Ok(Some((this.load_mir(instance.def, None)?, instance)))
56-
}
57-
}

0 commit comments

Comments
 (0)