From cfbcc0e6f565a6848e519570cdb4dcd4c3c34fc5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Oct 2023 18:29:49 +0200 Subject: [PATCH 01/21] add test for a function ABI mismatch due to target features --- .../simd_feature_flag_difference.rs | 30 +++++++++++++++++++ .../simd_feature_flag_difference.stderr | 20 +++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.rs create mode 100644 src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.stderr diff --git a/src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.rs b/src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.rs new file mode 100644 index 0000000000000..e98a3abadf59b --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.rs @@ -0,0 +1,30 @@ +//@only-target-x86_64 +#![allow(improper_ctypes_definitions)] +use std::arch::x86_64::*; +use std::mem::transmute; + +#[no_mangle] +#[target_feature(enable = "avx")] +pub unsafe extern "C" fn foo(_y: f32, x: __m256) -> __m256 { + x +} + +pub fn bar(x: __m256) -> __m256 { + // The first and second argument get mixed up here since caller + // and callee do not have the same feature flags. + // In Miri, we don't have a concept of "dynamically available feature flags", + // so this will always lead to an error due to calling a function that requires + // an unavailable feature. If we ever support dynamically available features, + // this will need some dedicated checks. + unsafe { foo(0.0, x) } //~ERROR: unavailable target features +} + +fn assert_eq_m256(a: __m256, b: __m256) { + unsafe { assert_eq!(transmute::<_, [f32; 8]>(a), transmute::<_, [f32; 8]>(b)) } +} + +fn main() { + let input = unsafe { transmute::<_, __m256>([1.0f32; 8]) }; + let copy = bar(input); + assert_eq_m256(input, copy); +} diff --git a/src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.stderr b/src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.stderr new file mode 100644 index 0000000000000..ab3ff5fcdc12c --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: calling a function that requires unavailable target features: avx + --> $DIR/simd_feature_flag_difference.rs:LL:CC + | +LL | unsafe { foo(0.0, x) } + | ^^^^^^^^^^^ calling a function that requires unavailable target features: avx + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `bar` at $DIR/simd_feature_flag_difference.rs:LL:CC +note: inside `main` + --> $DIR/simd_feature_flag_difference.rs:LL:CC + | +LL | let copy = bar(input); + | ^^^^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + From 91ef03bf2f545f10db008d0ad54c3d197f539895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Tue, 3 Oct 2023 18:14:01 +0200 Subject: [PATCH 02/21] =?UTF-8?q?Fix=20typos=20`*ucom`=20=E2=86=92=20`ucom?= =?UTF-8?q?*`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tools/miri/src/shims/x86/sse.rs | 2 +- src/tools/miri/src/shims/x86/sse2.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs index de1e695b6d149..0e51a73d09113 100644 --- a/src/tools/miri/src/shims/x86/sse.rs +++ b/src/tools/miri/src/shims/x86/sse.rs @@ -141,7 +141,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let left = this.read_scalar(&this.project_index(&left, 0)?)?.to_f32()?; let right = this.read_scalar(&this.project_index(&right, 0)?)?.to_f32()?; - // The difference between the com* and *ucom variants is signaling + // The difference between the com* and ucom* variants is signaling // of exceptions when either argument is a quiet NaN. We do not // support accessing the SSE status register from miri (or from Rust, // for that matter), so we treat equally both variants. diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index 2ef6a9b59ede7..a27d37d0fff89 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -637,7 +637,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let left = this.read_scalar(&this.project_index(&left, 0)?)?.to_f64()?; let right = this.read_scalar(&this.project_index(&right, 0)?)?.to_f64()?; - // The difference between the com* and *ucom variants is signaling + // The difference between the com* and ucom* variants is signaling // of exceptions when either argument is a quiet NaN. We do not // support accessing the SSE status register from miri (or from Rust, // for that matter), so we treat equally both variants. From 3e21c1fc5681b118fb27bf0c8131d73bcfa8185c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 3 Oct 2023 20:00:48 +0200 Subject: [PATCH 03/21] wording tweaks --- src/tools/miri/src/shims/x86/sse.rs | 2 +- src/tools/miri/src/shims/x86/sse2.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs index 0e51a73d09113..fa722f4b75ecd 100644 --- a/src/tools/miri/src/shims/x86/sse.rs +++ b/src/tools/miri/src/shims/x86/sse.rs @@ -144,7 +144,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: // The difference between the com* and ucom* variants is signaling // of exceptions when either argument is a quiet NaN. We do not // support accessing the SSE status register from miri (or from Rust, - // for that matter), so we treat equally both variants. + // for that matter), so we treat both variants equally. let res = match unprefixed_name { "comieq.ss" | "ucomieq.ss" => left == right, "comilt.ss" | "ucomilt.ss" => left < right, diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index a27d37d0fff89..261c947c8efd2 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -640,7 +640,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: // The difference between the com* and ucom* variants is signaling // of exceptions when either argument is a quiet NaN. We do not // support accessing the SSE status register from miri (or from Rust, - // for that matter), so we treat equally both variants. + // for that matter), so we treat both variants equally. let res = match unprefixed_name { "comieq.sd" | "ucomieq.sd" => left == right, "comilt.sd" | "ucomilt.sd" => left < right, From 31a57557f6fc9319ef8cb8f18ad1f22690d92d39 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 4 Oct 2023 22:11:15 +0200 Subject: [PATCH 04/21] auto-detect no_std where possible --- src/tools/miri/CONTRIBUTING.md | 17 +++++------------ src/tools/miri/README.md | 6 ++++-- src/tools/miri/cargo-miri/src/setup.rs | 12 +++++++++++- src/tools/miri/ci.sh | 2 +- src/tools/miri/tests/compiletest.rs | 4 +--- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md index 4e50b8fae81ce..40a4332cdb9c0 100644 --- a/src/tools/miri/CONTRIBUTING.md +++ b/src/tools/miri/CONTRIBUTING.md @@ -71,19 +71,12 @@ and you can (cross-)run the entire test suite using: MIRI_TEST_TARGET=i686-unknown-linux-gnu ./miri test ``` -If your target doesn't support libstd, you can run miri with +If your target doesn't support libstd that should usually just work. However, if you are using a +custom target file, you might have to set `MIRI_NO_STD=1`. -``` -MIRI_NO_STD=1 MIRI_TEST_TARGET=thumbv7em-none-eabihf ./miri test tests/fail/alloc/no_global_allocator.rs -MIRI_NO_STD=1 ./miri run tests/pass/no_std.rs --target thumbv7em-none-eabihf -``` - -to avoid attempting (and failing) to build libstd. Note that almost no tests will pass -this way, but you can run individual tests. - -`./miri test FILTER` only runs those tests that contain `FILTER` in their -filename (including the base directory, e.g. `./miri test fail` will run all -compile-fail tests). +`./miri test FILTER` only runs those tests that contain `FILTER` in their filename (including the +base directory, e.g. `./miri test fail` will run all compile-fail tests). These filters are passed +to `cargo test`, so for multiple filers you need to use `./miri test -- FILTER1 FILTER2`. You can get a trace of which MIR statements are being executed by setting the `MIRI_LOG` environment variable. For example: diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 6127eada2221e..ca2bb80bd26d3 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -480,8 +480,10 @@ Moreover, Miri recognizes some environment variables: purpose. * `MIRI_TEST_THREADS` (recognized by the test suite): set the number of threads to use for running tests. By default the number of cores is used. -* `MIRI_NO_STD` (recognized by `cargo miri` and the test suite) makes sure that the target's - sysroot is built without libstd. This allows testing and running no_std programs. +* `MIRI_NO_STD` (recognized by `cargo miri`) makes sure that the target's sysroot is built without + libstd. This allows testing and running no_std programs. + (Miri has a heuristic to detect no-std targets based on the target name; this environment variable + is only needed when that heuristic fails.) * `RUSTC_BLESS` (recognized by the test suite and `cargo-miri-test/run-test.py`): overwrite all `stderr` and `stdout` files instead of checking whether the output matches. * `MIRI_SKIP_UI_CHECKS` (recognized by the test suite): don't check whether the diff --git a/src/tools/miri/cargo-miri/src/setup.rs b/src/tools/miri/cargo-miri/src/setup.rs index 77cecddcb8b14..d921741d5dec2 100644 --- a/src/tools/miri/cargo-miri/src/setup.rs +++ b/src/tools/miri/cargo-miri/src/setup.rs @@ -74,7 +74,17 @@ pub fn setup( } }; // Sysroot configuration and build details. - let sysroot_config = if std::env::var_os("MIRI_NO_STD").is_some() { + let no_std = match std::env::var_os("MIRI_NO_STD") { + None => + // No-std heuristic taken from rust/src/bootstrap/config.rs + // (https://github.com/rust-lang/rust/blob/25b5af1b3a0b9e2c0c57b223b2d0e3e203869b2c/src/bootstrap/config.rs#L549-L555). + target.contains("-none") + || target.contains("nvptx") + || target.contains("switch") + || target.contains("-uefi"), + Some(val) => val != "0", + }; + let sysroot_config = if no_std { SysrootConfig::NoStd } else { SysrootConfig::WithStd { diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh index 9e7779e3513d9..1b3ed796c665b 100755 --- a/src/tools/miri/ci.sh +++ b/src/tools/miri/ci.sh @@ -112,7 +112,7 @@ case $HOST_TARGET in MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std integer strings - MIRI_TEST_TARGET=thumbv7em-none-eabihf MIRI_NO_STD=1 run_tests_minimal no_std # no_std embedded architecture + MIRI_TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std # no_std embedded architecture MIRI_TEST_TARGET=tests/avr.json MIRI_NO_STD=1 run_tests_minimal no_std # JSON target file ;; x86_64-apple-darwin) diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs index 035846f0ef952..c2dccf81377e4 100644 --- a/src/tools/miri/tests/compiletest.rs +++ b/src/tools/miri/tests/compiletest.rs @@ -93,9 +93,7 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> ..Config::rustc(path) }; - let use_std = env::var_os("MIRI_NO_STD").is_none(); - - if with_dependencies && use_std { + if with_dependencies { config.dependencies_crate_manifest_path = Some(Path::new("test_dependencies").join("Cargo.toml")); let mut builder_args = vec!["run".into()]; From 7d065db5c118af4d77960ec047c4b2b39eaa0065 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 4 Oct 2023 22:17:15 +0200 Subject: [PATCH 05/21] miri-script: print which sysroot target we are building --- src/tools/miri/miri-script/src/commands.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index de80777a689ff..c24035ae0862d 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -37,7 +37,10 @@ impl MiriEnv { Err(_) => vec![], }; if !quiet { - eprintln!("$ (building Miri sysroot)"); + match self.sh.var("MIRI_TEST_TARGET") { + Ok(target) => eprintln!("$ (building Miri sysroot for {target})"), + Err(_) => eprintln!("$ (building Miri sysroot)"), + } } let output = cmd!(self.sh, "cargo +{toolchain} --quiet run {cargo_extra_flags...} --manifest-path {manifest_path} -- From 5178ae60a1c7156d994a66bdc488f386c2234f5d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 5 Oct 2023 08:18:50 +0200 Subject: [PATCH 06/21] Tree Borrows: do not create new tags as 'Active' --- src/tools/miri/src/borrow_tracker/mod.rs | 5 +- .../src/borrow_tracker/stacked_borrows/mod.rs | 52 ++++++++-------- .../src/borrow_tracker/tree_borrows/mod.rs | 59 +++++++++++-------- .../src/borrow_tracker/tree_borrows/perms.rs | 1 + src/tools/miri/src/machine.rs | 18 ++++-- .../arg_inplace_mutate.tree.stderr | 8 ++- .../arg_inplace_observe_during.tree.stderr | 8 ++- .../return_pointer_aliasing.tree.stderr | 8 ++- .../return_pointer_aliasing2.stderr | 8 ++- 9 files changed, 106 insertions(+), 61 deletions(-) diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index b6dfd9944eef3..1951cf87f2f32 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -305,7 +305,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - fn protect_place(&mut self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { + fn protect_place( + &mut self, + place: &MPlaceTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> { let this = self.eval_context_mut(); let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; match method { diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index e670dcef330c9..a440ee720c78b 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -810,36 +810,43 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' Ok(Some(Provenance::Concrete { alloc_id, tag: new_tag })) } - /// Retags an individual pointer, returning the retagged version. - /// `kind` indicates what kind of reference is being created. - fn sb_retag_reference( + fn sb_retag_place( &mut self, - val: &ImmTy<'tcx, Provenance>, + place: &MPlaceTy<'tcx, Provenance>, new_perm: NewPermission, info: RetagInfo, // diagnostics info about this retag - ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { + ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> { let this = self.eval_context_mut(); - // We want a place for where the ptr *points to*, so we get one. - let place = this.ref_to_mplace(val)?; - let size = this.size_and_align_of_mplace(&place)?.map(|(size, _)| size); + let size = this.size_and_align_of_mplace(place)?.map(|(size, _)| size); // FIXME: If we cannot determine the size (because the unsized tail is an `extern type`), // bail out -- we cannot reasonably figure out which memory range to reborrow. // See https://github.com/rust-lang/unsafe-code-guidelines/issues/276. let size = match size { Some(size) => size, - None => return Ok(val.clone()), + None => return Ok(place.clone()), }; // Compute new borrow. let new_tag = this.machine.borrow_tracker.as_mut().unwrap().get_mut().new_ptr(); // Reborrow. - let new_prov = this.sb_reborrow(&place, size, new_perm, new_tag, info)?; + let new_prov = this.sb_reborrow(place, size, new_perm, new_tag, info)?; - // Adjust pointer. - let new_place = place.map_provenance(|_| new_prov); + // Adjust place. + Ok(place.clone().map_provenance(|_| new_prov)) + } - // Return new pointer. + /// Retags an individual pointer, returning the retagged version. + /// `kind` indicates what kind of reference is being created. + fn sb_retag_reference( + &mut self, + val: &ImmTy<'tcx, Provenance>, + new_perm: NewPermission, + info: RetagInfo, // diagnostics info about this retag + ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { + let this = self.eval_context_mut(); + let place = this.ref_to_mplace(val)?; + let new_place = this.sb_retag_place(&place, new_perm, info)?; Ok(ImmTy::from_immediate(new_place.to_ref(this), val.layout)) } } @@ -972,26 +979,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// call. /// /// This is used to ensure soundness of in-place function argument/return passing. - fn sb_protect_place(&mut self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { + fn sb_protect_place( + &mut self, + place: &MPlaceTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> { let this = self.eval_context_mut(); - // We have to turn the place into a pointer to use the usual retagging logic. - // (The pointer type does not matter, so we use a raw pointer.) - let ptr = this.mplace_to_ref(place)?; - // Reborrow it. With protection! That is the entire point. + // Retag it. With protection! That is the entire point. let new_perm = NewPermission::Uniform { perm: Permission::Unique, access: Some(AccessKind::Write), protector: Some(ProtectorKind::StrongProtector), }; - let _new_ptr = this.sb_retag_reference( - &ptr, + this.sb_retag_place( + place, new_perm, RetagInfo { cause: RetagCause::InPlaceFnPassing, in_field: false }, - )?; - // We just throw away `new_ptr`, so nobody can access this memory while it is protected. - - Ok(()) + ) } /// Mark the given tag as exposed. It was found on a pointer with the given AllocId. diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 924e0de38c9da..68bc4a415c601 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -5,7 +5,11 @@ use rustc_target::abi::{Abi, Align, Size}; use crate::borrow_tracker::{AccessKind, GlobalStateInner, ProtectorKind, RetagFields}; use rustc_middle::{ mir::{Mutability, RetagKind}, - ty::{self, layout::HasParamEnv, Ty}, + ty::{ + self, + layout::{HasParamEnv, HasTyCtxt}, + Ty, + }, }; use rustc_span::def_id::DefId; @@ -174,6 +178,8 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' new_tag: BorTag, ) -> InterpResult<'tcx, Option> { let this = self.eval_context_mut(); + // Make sure the new permission makes sense as the initial permission of a fresh tag. + assert!(new_perm.initial_state.is_initial()); // Ensure we bail out if the pointer goes out-of-bounds (see miri#1050). this.check_ptr_access_align( place.ptr(), @@ -275,10 +281,6 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' diagnostics::AccessCause::Reborrow, )?; // Record the parent-child pair in the tree. - // FIXME: We should eventually ensure that the following `assert` holds, because - // some "exhaustive" tests consider only the initial configurations that satisfy it. - // The culprit is `Permission::new_active` in `tb_protect_place`. - //assert!(new_perm.initial_state.is_initial()); tree_borrows.new_child(orig_tag, new_tag, new_perm.initial_state, range, span)?; drop(tree_borrows); @@ -306,15 +308,12 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' Ok(Some(Provenance::Concrete { alloc_id, tag: new_tag })) } - /// Retags an individual pointer, returning the retagged version. - fn tb_retag_reference( + fn tb_retag_place( &mut self, - val: &ImmTy<'tcx, Provenance>, + place: &MPlaceTy<'tcx, Provenance>, new_perm: NewPermission, - ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { + ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> { let this = self.eval_context_mut(); - // We want a place for where the ptr *points to*, so we get one. - let place = this.ref_to_mplace(val)?; // Determine the size of the reborrow. // For most types this is the entire size of the place, however @@ -323,7 +322,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' // then we override the size to do a zero-length reborrow. let reborrow_size = match new_perm { NewPermission { zero_size: false, .. } => - this.size_and_align_of_mplace(&place)? + this.size_and_align_of_mplace(place)? .map(|(size, _)| size) .unwrap_or(place.layout.size), _ => Size::from_bytes(0), @@ -339,12 +338,21 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' let new_tag = this.machine.borrow_tracker.as_mut().unwrap().get_mut().new_ptr(); // Compute the actual reborrow. - let new_prov = this.tb_reborrow(&place, reborrow_size, new_perm, new_tag)?; + let new_prov = this.tb_reborrow(place, reborrow_size, new_perm, new_tag)?; - // Adjust pointer. - let new_place = place.map_provenance(|_| new_prov); + // Adjust place. + Ok(place.clone().map_provenance(|_| new_prov)) + } - // Return new pointer. + /// Retags an individual pointer, returning the retagged version. + fn tb_retag_reference( + &mut self, + val: &ImmTy<'tcx, Provenance>, + new_perm: NewPermission, + ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { + let this = self.eval_context_mut(); + let place = this.ref_to_mplace(val)?; + let new_place = this.tb_retag_place(&place, new_perm)?; Ok(ImmTy::from_immediate(new_place.to_ref(this), val.layout)) } } @@ -493,22 +501,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// call. /// /// This is used to ensure soundness of in-place function argument/return passing. - fn tb_protect_place(&mut self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { + fn tb_protect_place( + &mut self, + place: &MPlaceTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> { let this = self.eval_context_mut(); - // We have to turn the place into a pointer to use the usual retagging logic. - // (The pointer type does not matter, so we use a raw pointer.) - let ptr = this.mplace_to_ref(place)?; - // Reborrow it. With protection! That is the entire point. + // Retag it. With protection! That is the entire point. let new_perm = NewPermission { - initial_state: Permission::new_active(), + initial_state: Permission::new_reserved( + place.layout.ty.is_freeze(this.tcx(), this.param_env()), + ), zero_size: false, protector: Some(ProtectorKind::StrongProtector), }; - let _new_ptr = this.tb_retag_reference(&ptr, new_perm)?; - // We just throw away `new_ptr`, so nobody can access this memory while it is protected. - - Ok(()) + this.tb_retag_place(place, new_perm) } /// Mark the given tag as exposed. It was found on a pointer with the given AllocId. diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs index 16bad13e28f34..3e019356ca746 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs @@ -159,6 +159,7 @@ impl Permission { } /// Default initial permission of the root of a new tree. + /// Must *only* be used for the root, this is not in general an "initial" permission! pub fn new_active() -> Self { Self { inner: Active } } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index f1c50794ca8da..fb56e0135b4ca 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1275,19 +1275,25 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ecx: &mut InterpCx<'mir, 'tcx, Self>, place: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { - // We do need to write `uninit` so that even after the call ends, the former contents of - // this place cannot be observed any more. - ecx.write_uninit(place)?; // If we have a borrow tracker, we also have it set up protection so that all reads *and // writes* during this call are insta-UB. - if ecx.machine.borrow_tracker.is_some() { + let protected_place = if ecx.machine.borrow_tracker.is_some() { // Have to do `to_op` first because a `Place::Local` doesn't imply the local doesn't have an address. if let Either::Left(place) = ecx.place_to_op(place)?.as_mplace_or_imm() { - ecx.protect_place(&place)?; + ecx.protect_place(&place)?.into() } else { // Locals that don't have their address taken are as protected as they can ever be. + place.clone() } - } + } else { + // No borrow tracker. + place.clone() + }; + // We do need to write `uninit` so that even after the call ends, the former contents of + // this place cannot be observed any more. We do the write after retagging so that for + // Tree Borrows, this is considered to activate the new tag. + ecx.write_uninit(&protected_place)?; + // Now we throw away the protected place, ensuring its tag is never used again. Ok(()) } diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr index 544cd575ada33..3d8ba68547bd1 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr @@ -19,11 +19,17 @@ LL | | let non_copy = S(42); LL | | LL | | } | |_____^ -help: the protected tag was created here, in the initial state Active +help: the protected tag was created here, in the initial state Reserved --> $DIR/arg_inplace_mutate.rs:LL:CC | LL | unsafe { ptr.write(S(0)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: the protected tag later transitioned to Active due to a child write access at offsets [0x0..0x4] + --> $DIR/arg_inplace_mutate.rs:LL:CC + | +LL | unsafe { ptr.write(S(0)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference = note: BACKTRACE (of the first span): = note: inside `callee` at $DIR/arg_inplace_mutate.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr index c33645bdd280a..7b1846a32dbc3 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr @@ -19,11 +19,17 @@ LL | | let non_copy = S(42); LL | | LL | | } | |_____^ -help: the protected tag was created here, in the initial state Active +help: the protected tag was created here, in the initial state Reserved --> $DIR/arg_inplace_observe_during.rs:LL:CC | LL | x.0 = 0; | ^^^^^^^ +help: the protected tag later transitioned to Active due to a child write access at offsets [0x0..0x4] + --> $DIR/arg_inplace_observe_during.rs:LL:CC + | +LL | x.0 = 0; + | ^^^^^^^ + = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference = note: BACKTRACE (of the first span): = note: inside `change_arg` at $DIR/arg_inplace_observe_during.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr index 66c2fb8db19f0..deafbf0207725 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr @@ -19,11 +19,17 @@ LL | | let ptr = &raw mut x; LL | | } LL | | } | |_____^ -help: the protected tag was created here, in the initial state Active +help: the protected tag was created here, in the initial state Reserved --> $DIR/return_pointer_aliasing.rs:LL:CC | LL | unsafe { ptr.read() }; | ^^^^^^^^^^^^^^^^^^^^^ +help: the protected tag later transitioned to Active due to a child write access at offsets [0x0..0x4] + --> $DIR/return_pointer_aliasing.rs:LL:CC + | +LL | unsafe { ptr.read() }; + | ^^^^^^^^^^^^^^^^^^^^^ + = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference = note: BACKTRACE (of the first span): = note: inside `myfun` at $DIR/return_pointer_aliasing.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr index 443ee8643fc28..e1b40a6bc1839 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr @@ -19,11 +19,17 @@ LL | | let ptr = &raw mut _x; LL | | } LL | | } | |_____^ -help: the protected tag was created here, in the initial state Active +help: the protected tag was created here, in the initial state Reserved --> $DIR/return_pointer_aliasing2.rs:LL:CC | LL | unsafe { ptr.write(0) }; | ^^^^^^^^^^^^^^^^^^^^^^^ +help: the protected tag later transitioned to Active due to a child write access at offsets [0x0..0x4] + --> $DIR/return_pointer_aliasing2.rs:LL:CC + | +LL | unsafe { ptr.write(0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ + = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference = note: BACKTRACE (of the first span): = note: inside `myfun` at $DIR/return_pointer_aliasing2.rs:LL:CC note: inside `main` From 95c459098868ca9c31f857dac8f085665d593039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Thu, 5 Oct 2023 19:28:26 +0200 Subject: [PATCH 07/21] Update miri dependencies --- src/tools/miri/Cargo.lock | 302 +++++++++++++++++--------------------- 1 file changed, 133 insertions(+), 169 deletions(-) diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 3f11e4db327e6..e654932255ae6 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.19.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.0.1" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" dependencies = [ "memchr", ] @@ -47,9 +47,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "autocfg" @@ -59,9 +59,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", @@ -86,30 +86,29 @@ checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "bstr" -version = "1.4.0" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" +checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" dependencies = [ "memchr", - "once_cell", "regex-automata", "serde", ] [[package]] name = "camino" -version = "1.1.4" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" dependencies = [ "serde", ] @@ -130,9 +129,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -209,21 +211,21 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] [[package]] name = "ctrlc" -version = "3.2.5" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbcf33c2a618cbe41ee43ae6e9f2e48368cd9f9db2896f10167d8d762679f639" +checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf" dependencies = [ "nix", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -247,9 +249,9 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" dependencies = [ "errno-dragonfly", "libc", @@ -278,18 +280,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", @@ -298,15 +297,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "hermit-abi" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "humantime" @@ -342,17 +341,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "io-lifetimes" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "is-terminal" version = "0.4.9" @@ -360,15 +348,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi", - "rustix 0.38.14", + "rustix", "windows-sys 0.48.0", ] [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "lazy_static" @@ -409,9 +397,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", "windows-sys 0.48.0", @@ -419,21 +407,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.3.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" - -[[package]] -name = "linux-raw-sys" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" +checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -441,12 +423,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "measureme" @@ -464,9 +443,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memmap2" @@ -479,9 +458,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] @@ -510,14 +489,13 @@ dependencies = [ [[package]] name = "nix" -version = "0.26.2" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", "cfg-if", "libc", - "static_assertions", ] [[package]] @@ -528,18 +506,18 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.30.3" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "owo-colors" @@ -592,9 +570,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "portable-atomic" @@ -620,9 +598,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] @@ -686,26 +664,32 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.1" +version = "1.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" dependencies = [ "aho-corasick", "memchr", + "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.1.10" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] [[package]] name = "regex-syntax" -version = "0.7.1" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "rustc-demangle" @@ -742,66 +726,52 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.7", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustix" -version = "0.38.14" +version = "0.38.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f" +checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7" dependencies = [ "bitflags 2.4.0", "errno", "libc", - "linux-raw-sys 0.4.7", + "linux-raw-sys", "windows-sys 0.48.0", ] [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.185" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.185" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", @@ -810,9 +780,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", @@ -821,30 +791,24 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "syn" -version = "2.0.29" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -853,40 +817,40 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.5.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix 0.37.19", - "windows-sys 0.45.0", + "rustix", + "windows-sys 0.48.0", ] [[package]] name = "termcolor" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", @@ -916,9 +880,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ "once_cell", "valuable", @@ -974,9 +938,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-width" @@ -1014,9 +978,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -1042,7 +1006,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.48.5", ] [[package]] @@ -1062,17 +1026,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -1083,9 +1047,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" @@ -1095,9 +1059,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" @@ -1107,9 +1071,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" @@ -1119,9 +1083,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" @@ -1131,9 +1095,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" @@ -1143,9 +1107,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" @@ -1155,9 +1119,9 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "yansi-term" From f49d325f9dee9d6ad6051d71d160d38cb9f79498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Thu, 5 Oct 2023 19:29:02 +0200 Subject: [PATCH 08/21] Update cargo-miri dependencies --- src/tools/miri/cargo-miri/Cargo.lock | 296 +++++++++------------------ src/tools/miri/cargo-miri/Cargo.toml | 4 +- 2 files changed, 99 insertions(+), 201 deletions(-) diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock index 1f3a33270e12f..c37a5ca88756f 100644 --- a/src/tools/miri/cargo-miri/Cargo.lock +++ b/src/tools/miri/cargo-miri/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "bitflags" @@ -14,11 +14,17 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + [[package]] name = "camino" -version = "1.1.4" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ "serde", ] @@ -38,18 +44,18 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" dependencies = [ "serde", ] [[package]] name = "cargo_metadata" -version = "0.15.4" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +checksum = "fb9ac64500cc83ce4b9f8dafa78186aa008c8dea77a09b94cd307fd0cd5022a8" dependencies = [ "camino", "cargo-platform", @@ -61,9 +67,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -73,33 +82,34 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "directories" -version = "4.0.1" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.3.7" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", + "option-ext", "redox_users", - "winapi", + "windows-sys", ] [[package]] name = "errno" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" dependencies = [ "errno-dragonfly", "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -114,73 +124,50 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", "wasi", ] -[[package]] -name = "hermit-abi" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "libc" -version = "0.2.142" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "linux-raw-sys" -version = "0.3.7" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" + +[[package]] +name = "option-ext" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] @@ -200,7 +187,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -209,7 +196,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -251,47 +238,46 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.19" +version = "0.38.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7" dependencies = [ - "bitflags", + "bitflags 2.4.0", "errno", - "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "semver" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.185" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.185" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", @@ -300,9 +286,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", @@ -311,9 +297,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.29" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -322,31 +308,31 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.5.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ "cfg-if", "fastrand", "redox_syscall 0.3.5", "rustix", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", @@ -355,9 +341,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "wasi" @@ -365,156 +351,68 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows-targets" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/src/tools/miri/cargo-miri/Cargo.toml b/src/tools/miri/cargo-miri/Cargo.toml index e118d12897a6a..55f6b5ac7efae 100644 --- a/src/tools/miri/cargo-miri/Cargo.toml +++ b/src/tools/miri/cargo-miri/Cargo.toml @@ -14,10 +14,10 @@ test = false # we have no unit tests doctest = false # and no doc tests [dependencies] -directories = "4" +directories = "5" rustc_version = "0.4" serde_json = "1.0.40" -cargo_metadata = "0.15.0" +cargo_metadata = "0.18.0" rustc-build-sysroot = "0.4.1" # Enable some feature flags that dev-dependencies need but dependencies From bbebfa718690ab79c11814bbdbac666f12165daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Thu, 5 Oct 2023 19:29:27 +0200 Subject: [PATCH 09/21] Update miri-script dependencies --- src/tools/miri/miri-script/Cargo.lock | 216 +++++++++++++++++++++----- src/tools/miri/miri-script/Cargo.toml | 4 +- 2 files changed, 179 insertions(+), 41 deletions(-) diff --git a/src/tools/miri/miri-script/Cargo.lock b/src/tools/miri/miri-script/Cargo.lock index 1a22596b7742a..6f8dd973fdd91 100644 --- a/src/tools/miri/miri-script/Cargo.lock +++ b/src/tools/miri/miri-script/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "bitflags" @@ -14,6 +14,21 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -22,22 +37,23 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "directories" -version = "4.0.1" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.3.7" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", + "option-ext", "redox_users", - "winapi", + "windows-sys", ] [[package]] @@ -48,9 +64,30 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "errno" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] [[package]] name = "getrandom" @@ -63,20 +100,35 @@ dependencies = [ "wasi", ] +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys", +] + [[package]] name = "itertools" -version = "0.10.5" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" dependencies = [ "either", ] [[package]] name = "libc" -version = "0.2.144" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" + +[[package]] +name = "linux-raw-sys" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" [[package]] name = "miri-script" @@ -96,9 +148,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "path_macro" @@ -108,9 +166,9 @@ checksum = "a6e819bbd49d5939f682638fa54826bf1650abddcd65d000923de8ad63cc7d15" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] @@ -130,7 +188,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -153,6 +211,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7" +dependencies = [ + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "same-file" version = "1.0.6" @@ -164,9 +235,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" [[package]] name = "shell-words" @@ -176,9 +247,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "syn" -version = "2.0.29" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -187,18 +258,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.47" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.47" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", @@ -207,15 +278,15 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "walkdir" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", @@ -229,13 +300,14 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "which" -version = "4.4.0" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ "either", - "libc", + "home", "once_cell", + "rustix", ] [[package]] @@ -256,9 +328,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -269,17 +341,83 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "xshell" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "962c039b3a7b16cf4e9a4248397c6585c07547412e7d6a6e035389a802dcfe90" +checksum = "ce2107fe03e558353b4c71ad7626d58ed82efaf56c54134228608893c77023ad" dependencies = [ "xshell-macros", ] [[package]] name = "xshell-macros" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dbabb1cbd15a1d6d12d9ed6b35cc6777d4af87ab3ba155ea37215f20beab80c" +checksum = "7e2c411759b501fb9501aac2b1b2d287a6e93e5bdcf13c25306b23e1b716dd0e" diff --git a/src/tools/miri/miri-script/Cargo.toml b/src/tools/miri/miri-script/Cargo.toml index d805a94c8f588..aaa788d58462d 100644 --- a/src/tools/miri/miri-script/Cargo.toml +++ b/src/tools/miri/miri-script/Cargo.toml @@ -13,11 +13,11 @@ edition = "2021" [dependencies] which = "4.4" walkdir = "2.3" -itertools = "0.10" +itertools = "0.11" path_macro = "1.0" shell-words = "1.1" anyhow = "1.0" xshell = "0.2" rustc_version = "0.4" dunce = "1.0.4" -directories = "4" +directories = "5" From 11afb99b4ff378a97abf4f03b0fa2a0ed9a4351e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Thu, 5 Oct 2023 19:30:31 +0200 Subject: [PATCH 10/21] Update test dependencies --- src/tools/miri/test_dependencies/Cargo.lock | 252 +++++++++++++------- src/tools/miri/test_dependencies/Cargo.toml | 2 +- 2 files changed, 162 insertions(+), 92 deletions(-) diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index 3ed564b4cbbb7..8d18d8535d8f5 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -2,12 +2,42 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -16,15 +46,24 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytes" -version = "1.3.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -45,9 +84,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "js-sys", @@ -56,35 +95,38 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] [[package]] name = "libc" -version = "0.2.139" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -92,27 +134,32 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] [[package]] name = "mio" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys", ] @@ -122,7 +169,7 @@ name = "miri-test-deps" version = "0.1.0" dependencies = [ "getrandom 0.1.16", - "getrandom 0.2.8", + "getrandom 0.2.10", "libc", "num_cpus", "page_size", @@ -132,25 +179,34 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", ] +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "page_size" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b7663cbd190cfd818d08efa8497f6cd383076688c49a391ef7c0d03cd12b561" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" dependencies = [ "libc", "winapi", @@ -168,22 +224,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.5" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-targets", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "ppv-lite86" @@ -193,18 +249,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.60" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.23" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -236,54 +292,60 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.8", + "getrandom 0.2.10", ] [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "socket2" -version = "0.4.7" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" dependencies = [ "libc", - "winapi", + "windows-sys", ] [[package]] name = "syn" -version = "1.0.107" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -292,14 +354,13 @@ dependencies = [ [[package]] name = "tokio" -version = "1.24.2" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a12a59981d9e3c38d216785b0c37399f6e415e8d0712047620f189371b0bb" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" dependencies = [ - "autocfg", + "backtrace", "bytes", "libc", - "memchr", "mio", "num_cpus", "parking_lot", @@ -312,9 +373,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.8.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", @@ -323,9 +384,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.6" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "wasi" @@ -341,9 +402,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -351,9 +412,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", @@ -366,9 +427,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -376,9 +437,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", @@ -389,9 +450,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "winapi" @@ -417,9 +478,18 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -432,42 +502,42 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/src/tools/miri/test_dependencies/Cargo.toml b/src/tools/miri/test_dependencies/Cargo.toml index d1ff33379e40a..670f5c895cbd6 100644 --- a/src/tools/miri/test_dependencies/Cargo.toml +++ b/src/tools/miri/test_dependencies/Cargo.toml @@ -17,7 +17,7 @@ getrandom = { version = "0.2", features = ["js"] } rand = { version = "0.8", features = ["small_rng"] } [target.'cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))'.dependencies] -page_size = "0.5" +page_size = "0.6" tokio = { version = "1.24", features = ["full"] } [workspace] From dff7d5aa2f041f833901318ab8d301aeeb8ef06c Mon Sep 17 00:00:00 2001 From: BlackHoleFox Date: Sun, 1 Oct 2023 12:19:41 -0500 Subject: [PATCH 11/21] Move getentropy handling to a shared location for foreign item implementation --- src/tools/miri/src/shims/unix/macos/dlsym.rs | 7 +++--- .../src/shims/unix/macos/foreign_items.rs | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/src/shims/unix/macos/dlsym.rs b/src/tools/miri/src/shims/unix/macos/dlsym.rs index 63ad680de60fa..fa8094528757e 100644 --- a/src/tools/miri/src/shims/unix/macos/dlsym.rs +++ b/src/tools/miri/src/shims/unix/macos/dlsym.rs @@ -2,6 +2,7 @@ use rustc_middle::mir; use log::trace; +use super::foreign_items::EvalContextExt as _; use crate::*; use helpers::check_arg_count; @@ -38,10 +39,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { match dlsym { Dlsym::getentropy => { let [ptr, len] = check_arg_count(args)?; - let ptr = this.read_pointer(ptr)?; - let len = this.read_target_usize(len)?; - this.gen_random(ptr, len)?; - this.write_null(dest)?; + let result = this.getentropy(ptr, len)?; + this.write_scalar(result, dest)?; } } diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 0ee3cea05d508..b514097c5df08 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -109,6 +109,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(result, dest)?; } + // Random generation related shims + "getentropy" => { + let [buf, bufsize] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let result = this.getentropy(buf, bufsize)?; + this.write_scalar(result, dest)?; + } + // Access to command-line arguments "_NSGetArgc" => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -198,4 +206,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(EmulateByNameResult::NeedsJumping) } + + fn getentropy( + &mut self, + buffer_op: &OpTy<'tcx, Provenance>, + length_op: &OpTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + this.assert_target_os("macos", "getentropy"); + + let ptr = this.read_pointer(buffer_op)?; + let len = this.read_target_usize(length_op)?; + this.gen_random(ptr, len)?; + + Ok(Scalar::from_i32(0)) // KERN_SUCCESS + } } From bc8d4dfa95ae10c3f7229c01710a9e8f838baaec Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 6 Oct 2023 09:15:48 +0200 Subject: [PATCH 12/21] refactor dlsym: dispatch symbols via the normal shim mechanism --- src/tools/miri/src/helpers.rs | 2 +- src/tools/miri/src/lib.rs | 4 +- src/tools/miri/src/machine.rs | 12 +-- src/tools/miri/src/shims/dlsym.rs | 48 ---------- src/tools/miri/src/shims/foreign_items.rs | 42 ++++++-- src/tools/miri/src/shims/mod.rs | 4 +- .../miri/src/shims/unix/android/dlsym.rs | 54 ----------- .../src/shims/unix/android/foreign_items.rs | 21 ++-- src/tools/miri/src/shims/unix/android/mod.rs | 1 - src/tools/miri/src/shims/unix/dlsym.rs | 55 ----------- .../miri/src/shims/unix/foreign_items.rs | 31 ++++-- .../miri/src/shims/unix/freebsd/dlsym.rs | 36 ------- .../src/shims/unix/freebsd/foreign_items.rs | 7 +- src/tools/miri/src/shims/unix/freebsd/mod.rs | 1 - src/tools/miri/src/shims/unix/linux/dlsym.rs | 40 -------- .../src/shims/unix/linux/foreign_items.rs | 8 +- src/tools/miri/src/shims/unix/linux/mod.rs | 1 - src/tools/miri/src/shims/unix/macos/dlsym.rs | 51 ---------- .../src/shims/unix/macos/foreign_items.rs | 31 +++--- src/tools/miri/src/shims/unix/macos/mod.rs | 1 - src/tools/miri/src/shims/unix/mod.rs | 1 - src/tools/miri/src/shims/windows/dlsym.rs | 82 ---------------- .../miri/src/shims/windows/foreign_items.rs | 95 +++++++++++++------ src/tools/miri/src/shims/windows/mod.rs | 1 - 24 files changed, 168 insertions(+), 461 deletions(-) delete mode 100644 src/tools/miri/src/shims/dlsym.rs delete mode 100644 src/tools/miri/src/shims/unix/android/dlsym.rs delete mode 100644 src/tools/miri/src/shims/unix/dlsym.rs delete mode 100644 src/tools/miri/src/shims/unix/freebsd/dlsym.rs delete mode 100644 src/tools/miri/src/shims/unix/linux/dlsym.rs delete mode 100644 src/tools/miri/src/shims/unix/macos/dlsym.rs delete mode 100644 src/tools/miri/src/shims/windows/dlsym.rs diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index fd9d57c487c0e..4146a9b41ae1c 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -960,7 +960,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { self.check_abi(abi, exp_abi)?; if let Some((body, instance)) = self.eval_context_mut().lookup_exported_symbol(link_name)? { // If compiler-builtins is providing the symbol, then don't treat it as a clash. - // We'll use our built-in implementation in `emulate_foreign_item_by_name` for increased + // We'll use our built-in implementation in `emulate_foreign_item_inner` for increased // performance. Note that this means we won't catch any undefined behavior in // compiler-builtins when running other crates, but Miri can still be run on // compiler-builtins itself (or any crate that uses it as a normal dependency) diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 816055cc4fe91..f1d8ce01bc24c 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -8,6 +8,7 @@ #![feature(yeet_expr)] #![feature(nonzero_ops)] #![feature(round_ties_even)] +#![feature(let_chains)] #![feature(lint_reasons)] #![feature(trait_upcasting)] // Configure clippy and other lints @@ -86,9 +87,8 @@ pub use rustc_const_eval::interpret::*; // Resolve ambiguity. pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy, Provenance as _}; -pub use crate::shims::dlsym::{Dlsym, EvalContextExt as _}; pub use crate::shims::env::{EnvVars, EvalContextExt as _}; -pub use crate::shims::foreign_items::EvalContextExt as _; +pub use crate::shims::foreign_items::{DynSym, EvalContextExt as _}; pub use crate::shims::intrinsics::EvalContextExt as _; pub use crate::shims::os_str::EvalContextExt as _; pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _}; diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index fb56e0135b4ca..54f90b2c03990 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -709,9 +709,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { "android" => { // "signal" let layout = this.machine.layouts.const_raw_ptr; - let dlsym = Dlsym::from_str("signal".as_bytes(), &this.tcx.sess.target.os)? - .expect("`signal` must be an actual dlsym on android"); - let ptr = this.fn_ptr(FnVal::Other(dlsym)); + let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str("signal"))); let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout); Self::alloc_extern_static(this, "signal", val)?; // A couple zero-initialized pointer-sized extern statics. @@ -867,7 +865,7 @@ impl<'mir, 'tcx> MiriInterpCxExt<'mir, 'tcx> for MiriInterpCx<'mir, 'tcx> { /// Machine hook implementations. impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { type MemoryKind = MiriMemoryKind; - type ExtraFnVal = Dlsym; + type ExtraFnVal = DynSym; type FrameExtra = FrameExtra<'tcx>; type AllocExtra = AllocExtra<'tcx>; @@ -939,15 +937,15 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { #[inline(always)] fn call_extra_fn( ecx: &mut MiriInterpCx<'mir, 'tcx>, - fn_val: Dlsym, + fn_val: DynSym, abi: Abi, args: &[FnArg<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, ret: Option, - _unwind: mir::UnwindAction, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit? - ecx.call_dlsym(fn_val, abi, &args, dest, ret) + ecx.emulate_dyn_sym(fn_val, abi, &args, dest, ret, unwind) } #[inline(always)] diff --git a/src/tools/miri/src/shims/dlsym.rs b/src/tools/miri/src/shims/dlsym.rs deleted file mode 100644 index 8bf6d24f85f31..0000000000000 --- a/src/tools/miri/src/shims/dlsym.rs +++ /dev/null @@ -1,48 +0,0 @@ -use rustc_middle::mir; -use rustc_target::spec::abi::Abi; - -use crate::helpers::target_os_is_unix; -use crate::*; -use shims::unix::dlsym as unix; -use shims::windows::dlsym as windows; - -#[derive(Debug, Copy, Clone)] -#[allow(non_camel_case_types)] -pub enum Dlsym { - Posix(unix::Dlsym), - Windows(windows::Dlsym), -} - -impl Dlsym { - // Returns an error for unsupported symbols, and None if this symbol - // should become a NULL pointer (pretend it does not exist). - pub fn from_str<'tcx>(name: &[u8], target_os: &str) -> InterpResult<'tcx, Option> { - let name = &*String::from_utf8_lossy(name); - Ok(match target_os { - target if target_os_is_unix(target) => - unix::Dlsym::from_str(name, target)?.map(Dlsym::Posix), - "windows" => windows::Dlsym::from_str(name)?.map(Dlsym::Windows), - os => bug!("dlsym not implemented for target_os {}", os), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - abi: Abi, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - match dlsym { - Dlsym::Posix(dlsym) => - unix::EvalContextExt::call_dlsym(this, dlsym, abi, args, dest, ret), - Dlsym::Windows(dlsym) => - windows::EvalContextExt::call_dlsym(this, dlsym, abi, args, dest, ret), - } - } -} diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 0c92ede40fd8c..e93521ac774c9 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -6,7 +6,7 @@ use rustc_apfloat::Float; use rustc_ast::expand::allocator::AllocatorKind; use rustc_hir::{ def::DefKind, - def_id::{CrateNum, DefId, LOCAL_CRATE}, + def_id::{CrateNum, LOCAL_CRATE}, }; use rustc_middle::middle::{ codegen_fn_attrs::CodegenFnAttrFlags, dependency_format::Linkage, @@ -25,7 +25,18 @@ use super::backtrace::EvalContextExt as _; use crate::helpers::target_os_is_unix; use crate::*; -/// Returned by `emulate_foreign_item_by_name`. +/// Type of dynamic symbols (for `dlsym` et al) +#[derive(Debug, Copy, Clone)] +pub struct DynSym(Symbol); + +#[allow(clippy::should_implement_trait)] +impl DynSym { + pub fn from_str(name: &str) -> Self { + DynSym(Symbol::intern(name)) + } +} + +/// Returned by `emulate_foreign_item_inner`. pub enum EmulateByNameResult<'mir, 'tcx> { /// The caller is expected to jump to the return block. NeedsJumping, @@ -254,7 +265,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// is delegated to another function. fn emulate_foreign_item( &mut self, - def_id: DefId, + link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, @@ -262,7 +273,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { let this = self.eval_context_mut(); - let link_name = this.item_link_name(def_id); let tcx = this.tcx.tcx; // First: functions that diverge. @@ -322,7 +332,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { }; // Second: functions that return immediately. - match this.emulate_foreign_item_by_name(link_name, abi, args, dest)? { + match this.emulate_foreign_item_inner(link_name, abi, args, dest)? { EmulateByNameResult::NeedsJumping => { trace!("{:?}", this.dump_place(dest)); this.go_to_block(ret); @@ -345,6 +355,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(None) } + /// Emulates a call to a `DynSym`. + fn emulate_dyn_sym( + &mut self, + sym: DynSym, + abi: Abi, + args: &[OpTy<'tcx, Provenance>], + dest: &PlaceTy<'tcx, Provenance>, + ret: Option, + unwind: mir::UnwindAction, + ) -> InterpResult<'tcx> { + let res = self.emulate_foreign_item(sym.0, abi, args, dest, ret, unwind)?; + assert!(res.is_none(), "DynSyms that delegate are not supported"); + Ok(()) + } + /// Emulates calling the internal __rust_* allocator functions fn emulate_allocator( &mut self, @@ -373,8 +398,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - /// Emulates calling a foreign item using its name. - fn emulate_foreign_item_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, @@ -1045,11 +1069,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => return match this.tcx.sess.target.os.as_ref() { target_os if target_os_is_unix(target_os) => - shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_by_name( + shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, ), "windows" => - shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_by_name( + shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, ), _ => Ok(EmulateByNameResult::NotSupported), diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index 5a9574766f3d9..a031a2a25c968 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -9,7 +9,6 @@ pub mod unix; pub mod windows; mod x86; -pub mod dlsym; pub mod env; pub mod os_str; pub mod panic; @@ -58,7 +57,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // foreign function // Any needed call to `goto_block` will be performed by `emulate_foreign_item`. let args = this.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit? - return this.emulate_foreign_item(instance.def_id(), abi, &args, dest, ret, unwind); + let link_name = this.item_link_name(instance.def_id()); + return this.emulate_foreign_item(link_name, abi, &args, dest, ret, unwind); } // Otherwise, load the MIR. diff --git a/src/tools/miri/src/shims/unix/android/dlsym.rs b/src/tools/miri/src/shims/unix/android/dlsym.rs deleted file mode 100644 index 451bc0bd5e153..0000000000000 --- a/src/tools/miri/src/shims/unix/android/dlsym.rs +++ /dev/null @@ -1,54 +0,0 @@ -use rustc_middle::mir; - -use crate::helpers::check_arg_count; -use crate::*; - -#[derive(Debug, Copy, Clone)] -#[allow(non_camel_case_types)] -pub enum Dlsym { - signal, -} - -impl Dlsym { - // Returns an error for unsupported symbols, and None if this symbol - // should become a NULL pointer (pretend it does not exist). - pub fn from_str<'tcx>(name: &str) -> InterpResult<'tcx, Option> { - Ok(match name { - "signal" => Some(Dlsym::signal), - "android_set_abort_message" => None, - _ => throw_unsup_format!("unsupported Android dlsym: {}", name), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - let ret = ret.expect("we don't support any diverging dlsym"); - assert!(this.tcx.sess.target.os == "android"); - - match dlsym { - Dlsym::signal => { - if !this.frame_in_std() { - throw_unsup_format!( - "`signal` support is crude and just enough for libstd to work" - ); - } - - let [_sig, _func] = check_arg_count(args)?; - this.write_null(dest)?; - } - } - - log::trace!("{:?}", this.dump_place(dest)); - this.go_to_block(ret); - Ok(()) - } -} diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs index 756aed369f15b..b610cf97750f3 100644 --- a/src/tools/miri/src/shims/unix/android/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs @@ -6,17 +6,26 @@ use shims::foreign_items::EmulateByNameResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +pub fn is_dyn_sym(name: &str) -> bool { + matches!(name, "signal") +} + pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn emulate_foreign_item_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, - _abi: Abi, - _args: &[OpTy<'tcx, Provenance>], - _dest: &PlaceTy<'tcx, Provenance>, + abi: Abi, + args: &[OpTy<'tcx, Provenance>], + dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { - let _this = self.eval_context_mut(); - #[allow(clippy::match_single_binding)] + let this = self.eval_context_mut(); + match link_name.as_str() { + "signal" if this.frame_in_std() => { + let [_sig, _func] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + this.write_null(dest)?; + } _ => return Ok(EmulateByNameResult::NotSupported), } diff --git a/src/tools/miri/src/shims/unix/android/mod.rs b/src/tools/miri/src/shims/unix/android/mod.rs index 434f5f30b5a56..09c6507b24f84 100644 --- a/src/tools/miri/src/shims/unix/android/mod.rs +++ b/src/tools/miri/src/shims/unix/android/mod.rs @@ -1,2 +1 @@ -pub mod dlsym; pub mod foreign_items; diff --git a/src/tools/miri/src/shims/unix/dlsym.rs b/src/tools/miri/src/shims/unix/dlsym.rs deleted file mode 100644 index 8bc19d18f2b29..0000000000000 --- a/src/tools/miri/src/shims/unix/dlsym.rs +++ /dev/null @@ -1,55 +0,0 @@ -use rustc_middle::mir; -use rustc_target::spec::abi::Abi; - -use crate::*; -use shims::unix::android::dlsym as android; -use shims::unix::freebsd::dlsym as freebsd; -use shims::unix::linux::dlsym as linux; -use shims::unix::macos::dlsym as macos; - -#[derive(Debug, Copy, Clone)] -pub enum Dlsym { - Android(android::Dlsym), - FreeBsd(freebsd::Dlsym), - Linux(linux::Dlsym), - MacOs(macos::Dlsym), -} - -impl Dlsym { - // Returns an error for unsupported symbols, and None if this symbol - // should become a NULL pointer (pretend it does not exist). - pub fn from_str<'tcx>(name: &str, target_os: &str) -> InterpResult<'tcx, Option> { - Ok(match target_os { - "android" => android::Dlsym::from_str(name)?.map(Dlsym::Android), - "freebsd" => freebsd::Dlsym::from_str(name)?.map(Dlsym::FreeBsd), - "linux" => linux::Dlsym::from_str(name)?.map(Dlsym::Linux), - "macos" => macos::Dlsym::from_str(name)?.map(Dlsym::MacOs), - _ => panic!("unsupported Unix OS {target_os}"), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - abi: Abi, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - - this.check_abi(abi, Abi::C { unwind: false })?; - - match dlsym { - Dlsym::Android(dlsym) => - android::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), - Dlsym::FreeBsd(dlsym) => - freebsd::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), - Dlsym::Linux(dlsym) => linux::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), - Dlsym::MacOs(dlsym) => macos::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), - } - } -} diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 4bcca5076cac2..06ffdbff4e6d0 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -1,4 +1,5 @@ use std::ffi::OsStr; +use std::str; use log::trace; @@ -14,9 +15,14 @@ use shims::unix::mem::EvalContextExt as _; use shims::unix::sync::EvalContextExt as _; use shims::unix::thread::EvalContextExt as _; +use shims::unix::android::foreign_items as android; +use shims::unix::freebsd::foreign_items as freebsd; +use shims::unix::linux::foreign_items as linux; +use shims::unix::macos::foreign_items as macos; + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn emulate_foreign_item_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, @@ -25,7 +31,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { let this = self.eval_context_mut(); - // See `fn emulate_foreign_item_by_name` in `shims/foreign_items.rs` for the general pattern. + // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. #[rustfmt::skip] match link_name.as_str() { // Environment related shims @@ -230,9 +236,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [handle, symbol] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.read_target_usize(handle)?; let symbol = this.read_pointer(symbol)?; - let symbol_name = this.read_c_str(symbol)?; - if let Some(dlsym) = Dlsym::from_str(symbol_name, &this.tcx.sess.target.os)? { - let ptr = this.fn_ptr(FnVal::Other(dlsym)); + let name = this.read_c_str(symbol)?; + let is_dyn_sym = |name| match &*this.tcx.sess.target.os { + "android" => android::is_dyn_sym(name), + "freebsd" => freebsd::is_dyn_sym(name), + "linux" => linux::is_dyn_sym(name), + "macos" => macos::is_dyn_sym(name), + target_os => panic!("unsupported Unix OS {target_os}"), + }; + if let Ok(name) = str::from_utf8(name) && is_dyn_sym(name) { + let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str(name))); this.write_pointer(ptr, dest)?; } else { this.write_null(dest)?; @@ -609,10 +622,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => { let target_os = &*this.tcx.sess.target.os; return match target_os { - "android" => shims::unix::android::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), - "freebsd" => shims::unix::freebsd::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), - "linux" => shims::unix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), - "macos" => shims::unix::macos::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), + "android" => android::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), + "freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), + "linux" => linux::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), + "macos" => macos::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), _ => Ok(EmulateByNameResult::NotSupported), }; } diff --git a/src/tools/miri/src/shims/unix/freebsd/dlsym.rs b/src/tools/miri/src/shims/unix/freebsd/dlsym.rs deleted file mode 100644 index d759ffb8994b7..0000000000000 --- a/src/tools/miri/src/shims/unix/freebsd/dlsym.rs +++ /dev/null @@ -1,36 +0,0 @@ -use rustc_middle::mir; - -use crate::*; - -#[derive(Debug, Copy, Clone)] -#[allow(non_camel_case_types)] -pub enum Dlsym {} - -impl Dlsym { - // Returns an error for unsupported symbols, and None if this symbol - // should become a NULL pointer (pretend it does not exist). - pub fn from_str<'tcx>(name: &str) -> InterpResult<'tcx, Option> { - throw_unsup_format!("unsupported FreeBSD dlsym: {}", name) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - _args: &[OpTy<'tcx, Provenance>], - _dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - let _ret = ret.expect("we don't support any diverging dlsym"); - assert!(this.tcx.sess.target.os == "freebsd"); - - match dlsym {} - - //trace!("{:?}", this.dump_place(**dest)); - //this.go_to_block(ret); - //Ok(()) - } -} diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index d755e5f10bae8..388b205267953 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -5,10 +5,13 @@ use crate::*; use shims::foreign_items::EmulateByNameResult; use shims::unix::thread::EvalContextExt as _; -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +pub fn is_dyn_sym(_name: &str) -> bool { + false +} +impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn emulate_foreign_item_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, diff --git a/src/tools/miri/src/shims/unix/freebsd/mod.rs b/src/tools/miri/src/shims/unix/freebsd/mod.rs index 434f5f30b5a56..09c6507b24f84 100644 --- a/src/tools/miri/src/shims/unix/freebsd/mod.rs +++ b/src/tools/miri/src/shims/unix/freebsd/mod.rs @@ -1,2 +1 @@ -pub mod dlsym; pub mod foreign_items; diff --git a/src/tools/miri/src/shims/unix/linux/dlsym.rs b/src/tools/miri/src/shims/unix/linux/dlsym.rs deleted file mode 100644 index a96c14c142b25..0000000000000 --- a/src/tools/miri/src/shims/unix/linux/dlsym.rs +++ /dev/null @@ -1,40 +0,0 @@ -use rustc_middle::mir; - -use crate::*; - -#[derive(Debug, Copy, Clone)] -pub enum Dlsym {} - -impl Dlsym { - // Returns an error for unsupported symbols, and None if this symbol - // should become a NULL pointer (pretend it does not exist). - pub fn from_str<'tcx>(name: &str) -> InterpResult<'tcx, Option> { - Ok(match name { - "__pthread_get_minstack" => None, - "getrandom" => None, // std falls back to syscall(SYS_getrandom, ...) when this is NULL. - "statx" => None, // std falls back to syscall(SYS_statx, ...) when this is NULL. - _ => throw_unsup_format!("unsupported Linux dlsym: {}", name), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - _args: &[OpTy<'tcx, Provenance>], - _dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - let _ret = ret.expect("we don't support any diverging dlsym"); - assert!(this.tcx.sess.target.os == "linux"); - - match dlsym {} - - //trace!("{:?}", this.dump_place(**dest)); - //this.go_to_block(ret); - //Ok(()) - } -} diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 1bd751c59811f..9f5f6ea9bd091 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -12,9 +12,13 @@ use shims::unix::linux::sync::futex; use shims::unix::sync::EvalContextExt as _; use shims::unix::thread::EvalContextExt as _; +pub fn is_dyn_sym(_name: &str) -> bool { + false +} + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn emulate_foreign_item_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, @@ -23,7 +27,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { let this = self.eval_context_mut(); - // See `fn emulate_foreign_item_by_name` in `shims/foreign_items.rs` for the general pattern. + // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. match link_name.as_str() { // errno diff --git a/src/tools/miri/src/shims/unix/linux/mod.rs b/src/tools/miri/src/shims/unix/linux/mod.rs index 856ec226de8fc..fe18f1a32fd42 100644 --- a/src/tools/miri/src/shims/unix/linux/mod.rs +++ b/src/tools/miri/src/shims/unix/linux/mod.rs @@ -1,4 +1,3 @@ -pub mod dlsym; pub mod fd; pub mod foreign_items; pub mod mem; diff --git a/src/tools/miri/src/shims/unix/macos/dlsym.rs b/src/tools/miri/src/shims/unix/macos/dlsym.rs deleted file mode 100644 index fa8094528757e..0000000000000 --- a/src/tools/miri/src/shims/unix/macos/dlsym.rs +++ /dev/null @@ -1,51 +0,0 @@ -use rustc_middle::mir; - -use log::trace; - -use super::foreign_items::EvalContextExt as _; -use crate::*; -use helpers::check_arg_count; - -#[derive(Debug, Copy, Clone)] -#[allow(non_camel_case_types)] -pub enum Dlsym { - getentropy, -} - -impl Dlsym { - // Returns an error for unsupported symbols, and None if this symbol - // should become a NULL pointer (pretend it does not exist). - pub fn from_str<'tcx>(name: &str) -> InterpResult<'tcx, Option> { - Ok(match name { - "getentropy" => Some(Dlsym::getentropy), - _ => throw_unsup_format!("unsupported macOS dlsym: {}", name), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - let ret = ret.expect("we don't support any diverging dlsym"); - assert!(this.tcx.sess.target.os == "macos"); - - match dlsym { - Dlsym::getentropy => { - let [ptr, len] = check_arg_count(args)?; - let result = this.getentropy(ptr, len)?; - this.write_scalar(result, dest)?; - } - } - - trace!("{:?}", this.dump_place(dest)); - this.go_to_block(ret); - Ok(()) - } -} diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index b514097c5df08..cb0af4c827914 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -6,9 +6,13 @@ use shims::foreign_items::EmulateByNameResult; use shims::unix::fs::EvalContextExt as _; use shims::unix::thread::EvalContextExt as _; +pub fn is_dyn_sym(name: &str) -> bool { + matches!(name, "getentropy") +} + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn emulate_foreign_item_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, @@ -17,7 +21,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { let this = self.eval_context_mut(); - // See `fn emulate_foreign_item_by_name` in `shims/foreign_items.rs` for the general pattern. + // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. match link_name.as_str() { // errno @@ -113,8 +117,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "getentropy" => { let [buf, bufsize] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.getentropy(buf, bufsize)?; - this.write_scalar(result, dest)?; + let buf = this.read_pointer(buf)?; + let bufsize = this.read_target_usize(bufsize)?; + + this.gen_random(buf, bufsize)?; + + this.write_scalar(Scalar::from_i32(0), dest)?; // KERN_SUCCESS } // Access to command-line arguments @@ -206,19 +214,4 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(EmulateByNameResult::NeedsJumping) } - - fn getentropy( - &mut self, - buffer_op: &OpTy<'tcx, Provenance>, - length_op: &OpTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, Scalar> { - let this = self.eval_context_mut(); - this.assert_target_os("macos", "getentropy"); - - let ptr = this.read_pointer(buffer_op)?; - let len = this.read_target_usize(length_op)?; - this.gen_random(ptr, len)?; - - Ok(Scalar::from_i32(0)) // KERN_SUCCESS - } } diff --git a/src/tools/miri/src/shims/unix/macos/mod.rs b/src/tools/miri/src/shims/unix/macos/mod.rs index 434f5f30b5a56..09c6507b24f84 100644 --- a/src/tools/miri/src/shims/unix/macos/mod.rs +++ b/src/tools/miri/src/shims/unix/macos/mod.rs @@ -1,2 +1 @@ -pub mod dlsym; pub mod foreign_items; diff --git a/src/tools/miri/src/shims/unix/mod.rs b/src/tools/miri/src/shims/unix/mod.rs index a8ebd369abaaa..2f8014933521f 100644 --- a/src/tools/miri/src/shims/unix/mod.rs +++ b/src/tools/miri/src/shims/unix/mod.rs @@ -1,4 +1,3 @@ -pub mod dlsym; pub mod foreign_items; mod fs; diff --git a/src/tools/miri/src/shims/windows/dlsym.rs b/src/tools/miri/src/shims/windows/dlsym.rs deleted file mode 100644 index e5afee35905d0..0000000000000 --- a/src/tools/miri/src/shims/windows/dlsym.rs +++ /dev/null @@ -1,82 +0,0 @@ -use rustc_middle::mir; -use rustc_target::spec::abi::Abi; - -use log::trace; - -use crate::helpers::check_arg_count; -use crate::shims::windows::handle::{EvalContextExt as _, Handle, PseudoHandle}; -use crate::shims::windows::sync::EvalContextExt as _; -use crate::*; - -#[derive(Debug, Copy, Clone)] -pub enum Dlsym { - SetThreadDescription, - WaitOnAddress, - WakeByAddressSingle, -} - -impl Dlsym { - // Returns an error for unsupported symbols, and None if this symbol - // should become a NULL pointer (pretend it does not exist). - pub fn from_str<'tcx>(name: &str) -> InterpResult<'tcx, Option> { - Ok(match name { - "GetSystemTimePreciseAsFileTime" => None, - "SetThreadDescription" => Some(Dlsym::SetThreadDescription), - "WaitOnAddress" => Some(Dlsym::WaitOnAddress), - "WakeByAddressSingle" => Some(Dlsym::WakeByAddressSingle), - _ => throw_unsup_format!("unsupported Windows dlsym: {}", name), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - abi: Abi, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - let ret = ret.expect("we don't support any diverging dlsym"); - assert!(this.tcx.sess.target.os == "windows"); - - this.check_abi(abi, Abi::System { unwind: false })?; - - match dlsym { - Dlsym::SetThreadDescription => { - let [handle, name] = check_arg_count(args)?; - - let handle = this.read_scalar(handle)?; - - let name = this.read_wide_str(this.read_pointer(name)?)?; - - let thread = match Handle::from_scalar(handle, this)? { - Some(Handle::Thread(thread)) => thread, - Some(Handle::Pseudo(PseudoHandle::CurrentThread)) => this.get_active_thread(), - _ => this.invalid_handle("SetThreadDescription")?, - }; - - this.set_thread_name_wide(thread, &name); - - this.write_null(dest)?; - } - Dlsym::WaitOnAddress => { - let [ptr_op, compare_op, size_op, timeout_op] = check_arg_count(args)?; - - this.WaitOnAddress(ptr_op, compare_op, size_op, timeout_op, dest)?; - } - Dlsym::WakeByAddressSingle => { - let [ptr_op] = check_arg_count(args)?; - - this.WakeByAddressSingle(ptr_op)?; - } - } - - trace!("{:?}", this.dump_place(dest)); - this.go_to_block(ret); - Ok(()) - } -} diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index d76d01b07891a..fe2f48638b8f7 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -1,4 +1,5 @@ use std::iter; +use std::str; use rustc_span::Symbol; use rustc_target::abi::Size; @@ -10,9 +11,13 @@ use shims::windows::handle::{EvalContextExt as _, Handle, PseudoHandle}; use shims::windows::sync::EvalContextExt as _; use shims::windows::thread::EvalContextExt as _; +fn is_dyn_sym(name: &str) -> bool { + matches!(name, "SetThreadDescription" | "WaitOnAddress" | "WakeByAddressSingle") +} + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn emulate_foreign_item_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, @@ -21,7 +26,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { let this = self.eval_context_mut(); - // See `fn emulate_foreign_item_by_name` in `shims/foreign_items.rs` for the general pattern. + // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. // Windows API stubs. // HANDLE = isize @@ -326,6 +331,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.WakeAllConditionVariable(condvar)?; } + "WaitOnAddress" => { + let [ptr_op, compare_op, size_op, timeout_op] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + this.WaitOnAddress(ptr_op, compare_op, size_op, timeout_op, dest)?; + } + "WakeByAddressSingle" => { + let [ptr_op] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + this.WakeByAddressSingle(ptr_op)?; + } // Dynamic symbol loading "GetProcAddress" => { @@ -334,14 +351,58 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; this.read_target_isize(hModule)?; let name = this.read_c_str(this.read_pointer(lpProcName)?)?; - if let Some(dlsym) = Dlsym::from_str(name, &this.tcx.sess.target.os)? { - let ptr = this.fn_ptr(FnVal::Other(dlsym)); + if let Ok(name) = str::from_utf8(name) && is_dyn_sym(name) { + let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str(name))); this.write_pointer(ptr, dest)?; } else { this.write_null(dest)?; } } + // Threading + "CreateThread" => { + let [security, stacksize, start, arg, flags, thread] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + let thread_id = + this.CreateThread(security, stacksize, start, arg, flags, thread)?; + + this.write_scalar(Handle::Thread(thread_id).to_scalar(this), dest)?; + } + "WaitForSingleObject" => { + let [handle, timeout] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + let ret = this.WaitForSingleObject(handle, timeout)?; + this.write_scalar(Scalar::from_u32(ret), dest)?; + } + "GetCurrentThread" => { + let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + this.write_scalar( + Handle::Pseudo(PseudoHandle::CurrentThread).to_scalar(this), + dest, + )?; + } + "SetThreadDescription" => { + let [handle, name] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + let handle = this.read_scalar(handle)?; + + let name = this.read_wide_str(this.read_pointer(name)?)?; + + let thread = match Handle::from_scalar(handle, this)? { + Some(Handle::Thread(thread)) => thread, + Some(Handle::Pseudo(PseudoHandle::CurrentThread)) => this.get_active_thread(), + _ => this.invalid_handle("SetThreadDescription")?, + }; + + this.set_thread_name_wide(thread, &name); + + this.write_null(dest)?; + } + // Miscellaneous "SystemFunction036" => { // This is really 'RtlGenRandom'. @@ -456,32 +517,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - // Threading - "CreateThread" => { - let [security, stacksize, start, arg, flags, thread] = - this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - - let thread_id = - this.CreateThread(security, stacksize, start, arg, flags, thread)?; - - this.write_scalar(Handle::Thread(thread_id).to_scalar(this), dest)?; - } - "WaitForSingleObject" => { - let [handle, timeout] = - this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - - let ret = this.WaitForSingleObject(handle, timeout)?; - this.write_scalar(Scalar::from_u32(ret), dest)?; - } - "GetCurrentThread" => { - let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - - this.write_scalar( - Handle::Pseudo(PseudoHandle::CurrentThread).to_scalar(this), - dest, - )?; - } - // Incomplete shims that we "stub out" just to get pre-main initialization code to work. // These shims are enabled only when the caller is in the standard library. "GetProcessHeap" if this.frame_in_std() => { diff --git a/src/tools/miri/src/shims/windows/mod.rs b/src/tools/miri/src/shims/windows/mod.rs index 40fe71b2dbd02..7688abe412b99 100644 --- a/src/tools/miri/src/shims/windows/mod.rs +++ b/src/tools/miri/src/shims/windows/mod.rs @@ -1,4 +1,3 @@ -pub mod dlsym; pub mod foreign_items; mod handle; From 099311ba5a15162d73afe9ebe62bdc463ebd76c0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 6 Oct 2023 09:20:51 +0200 Subject: [PATCH 13/21] make some things on foreign_items private --- src/tools/miri/src/shims/foreign_items.rs | 418 +++++++++--------- .../src/shims/unix/android/foreign_items.rs | 8 +- .../miri/src/shims/unix/foreign_items.rs | 8 +- .../src/shims/unix/freebsd/foreign_items.rs | 8 +- .../src/shims/unix/linux/foreign_items.rs | 10 +- .../src/shims/unix/macos/foreign_items.rs | 8 +- .../miri/src/shims/windows/foreign_items.rs | 8 +- src/tools/miri/src/shims/x86/mod.rs | 12 +- src/tools/miri/src/shims/x86/sse.rs | 8 +- src/tools/miri/src/shims/x86/sse2.rs | 8 +- src/tools/miri/src/shims/x86/sse3.rs | 8 +- src/tools/miri/src/shims/x86/ssse3.rs | 8 +- 12 files changed, 256 insertions(+), 256 deletions(-) diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index e93521ac774c9..3462f03c30ffb 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -37,119 +37,129 @@ impl DynSym { } /// Returned by `emulate_foreign_item_inner`. -pub enum EmulateByNameResult<'mir, 'tcx> { +pub enum EmulateForeignItemResult { /// The caller is expected to jump to the return block. NeedsJumping, /// Jumping has already been taken care of. AlreadyJumped, - /// A MIR body has been found for the function. - MirBody(&'mir mir::Body<'tcx>, ty::Instance<'tcx>), /// The item is not supported. NotSupported, } impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - /// Returns the minimum alignment for the target architecture for allocations of the given size. - fn min_align(&self, size: u64, kind: MiriMemoryKind) -> Align { - let this = self.eval_context_ref(); - // List taken from `library/std/src/sys/common/alloc.rs`. - // This list should be kept in sync with the one from libstd. - let min_align = match this.tcx.sess.target.arch.as_ref() { - "x86" | "arm" | "mips" | "mips32r6" | "powerpc" | "powerpc64" | "asmjs" | "wasm32" => 8, - "x86_64" | "aarch64" | "mips64" | "mips64r6" | "s390x" | "sparc64" | "loongarch64" => - 16, - arch => bug!("unsupported target architecture for malloc: `{}`", arch), + /// Emulates calling a foreign item, failing if the item is not supported. + /// This function will handle `goto_block` if needed. + /// Returns Ok(None) if the foreign item was completely handled + /// by this function. + /// Returns Ok(Some(body)) if processing the foreign item + /// is delegated to another function. + fn emulate_foreign_item( + &mut self, + link_name: Symbol, + abi: Abi, + args: &[OpTy<'tcx, Provenance>], + dest: &PlaceTy<'tcx, Provenance>, + ret: Option, + unwind: mir::UnwindAction, + ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { + let this = self.eval_context_mut(); + let tcx = this.tcx.tcx; + + // First: functions that diverge. + let ret = match ret { + None => + match link_name.as_str() { + "miri_start_panic" => { + // `check_shim` happens inside `handle_miri_start_panic`. + this.handle_miri_start_panic(abi, link_name, args, unwind)?; + return Ok(None); + } + // This matches calls to the foreign item `panic_impl`. + // The implementation is provided by the function with the `#[panic_handler]` attribute. + "panic_impl" => { + // We don't use `check_shim` here because we are just forwarding to the lang + // item. Argument count checking will be performed when the returned `Body` is + // called. + this.check_abi_and_shim_symbol_clash(abi, Abi::Rust, link_name)?; + let panic_impl_id = tcx.lang_items().panic_impl().unwrap(); + let panic_impl_instance = ty::Instance::mono(tcx, panic_impl_id); + return Ok(Some(( + this.load_mir(panic_impl_instance.def, None)?, + panic_impl_instance, + ))); + } + #[rustfmt::skip] + | "exit" + | "ExitProcess" + => { + let exp_abi = if link_name.as_str() == "exit" { + Abi::C { unwind: false } + } else { + Abi::System { unwind: false } + }; + let [code] = this.check_shim(abi, exp_abi, link_name, args)?; + // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway + let code = this.read_scalar(code)?.to_i32()?; + throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false }); + } + "abort" => { + let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + throw_machine_stop!(TerminationInfo::Abort( + "the program aborted execution".to_owned() + )) + } + _ => { + if let Some(body) = this.lookup_exported_symbol(link_name)? { + return Ok(Some(body)); + } + this.handle_unsupported(format!( + "can't call (diverging) foreign function: {link_name}" + ))?; + return Ok(None); + } + }, + Some(p) => p, }; - // Windows always aligns, even small allocations. - // Source: - // But jemalloc does not, so for the C heap we only align if the allocation is sufficiently big. - if kind == MiriMemoryKind::WinHeap || size >= min_align { - return Align::from_bytes(min_align).unwrap(); - } - // We have `size < min_align`. Round `size` *down* to the next power of two and use that. - fn prev_power_of_two(x: u64) -> u64 { - let next_pow2 = x.next_power_of_two(); - if next_pow2 == x { - // x *is* a power of two, just use that. - x - } else { - // x is between two powers, so next = 2*prev. - next_pow2 / 2 + + // Second: functions that return immediately. + match this.emulate_foreign_item_inner(link_name, abi, args, dest)? { + EmulateForeignItemResult::NeedsJumping => { + trace!("{:?}", this.dump_place(dest)); + this.go_to_block(ret); } - } - Align::from_bytes(prev_power_of_two(size)).unwrap() - } + EmulateForeignItemResult::AlreadyJumped => (), + EmulateForeignItemResult::NotSupported => { + if let Some(body) = this.lookup_exported_symbol(link_name)? { + return Ok(Some(body)); + } - fn malloc( - &mut self, - size: u64, - zero_init: bool, - kind: MiriMemoryKind, - ) -> InterpResult<'tcx, Pointer>> { - let this = self.eval_context_mut(); - if size == 0 { - Ok(Pointer::null()) - } else { - let align = this.min_align(size, kind); - let ptr = this.allocate_ptr(Size::from_bytes(size), align, kind.into())?; - if zero_init { - // We just allocated this, the access is definitely in-bounds and fits into our address space. - this.write_bytes_ptr( - ptr.into(), - iter::repeat(0u8).take(usize::try_from(size).unwrap()), - ) - .unwrap(); + this.handle_unsupported(format!( + "can't call foreign function `{link_name}` on OS `{os}`", + os = this.tcx.sess.target.os, + ))?; + return Ok(None); } - Ok(ptr.into()) } + + Ok(None) } - fn free( + /// Emulates a call to a `DynSym`. + fn emulate_dyn_sym( &mut self, - ptr: Pointer>, - kind: MiriMemoryKind, + sym: DynSym, + abi: Abi, + args: &[OpTy<'tcx, Provenance>], + dest: &PlaceTy<'tcx, Provenance>, + ret: Option, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - if !this.ptr_is_null(ptr)? { - this.deallocate_ptr(ptr, None, kind.into())?; - } + let res = self.emulate_foreign_item(sym.0, abi, args, dest, ret, unwind)?; + assert!(res.is_none(), "DynSyms that delegate are not supported"); Ok(()) } - fn realloc( - &mut self, - old_ptr: Pointer>, - new_size: u64, - kind: MiriMemoryKind, - ) -> InterpResult<'tcx, Pointer>> { - let this = self.eval_context_mut(); - let new_align = this.min_align(new_size, kind); - if this.ptr_is_null(old_ptr)? { - if new_size == 0 { - Ok(Pointer::null()) - } else { - let new_ptr = - this.allocate_ptr(Size::from_bytes(new_size), new_align, kind.into())?; - Ok(new_ptr.into()) - } - } else { - if new_size == 0 { - this.deallocate_ptr(old_ptr, None, kind.into())?; - Ok(Pointer::null()) - } else { - let new_ptr = this.reallocate_ptr( - old_ptr, - None, - Size::from_bytes(new_size), - new_align, - kind.into(), - )?; - Ok(new_ptr.into()) - } - } - } - /// Lookup the body of a function that has `link_name` as the symbol name. fn lookup_exported_symbol( &mut self, @@ -244,6 +254,78 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } + fn malloc( + &mut self, + size: u64, + zero_init: bool, + kind: MiriMemoryKind, + ) -> InterpResult<'tcx, Pointer>> { + let this = self.eval_context_mut(); + if size == 0 { + Ok(Pointer::null()) + } else { + let align = this.min_align(size, kind); + let ptr = this.allocate_ptr(Size::from_bytes(size), align, kind.into())?; + if zero_init { + // We just allocated this, the access is definitely in-bounds and fits into our address space. + this.write_bytes_ptr( + ptr.into(), + iter::repeat(0u8).take(usize::try_from(size).unwrap()), + ) + .unwrap(); + } + Ok(ptr.into()) + } + } + + fn free( + &mut self, + ptr: Pointer>, + kind: MiriMemoryKind, + ) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + if !this.ptr_is_null(ptr)? { + this.deallocate_ptr(ptr, None, kind.into())?; + } + Ok(()) + } + + fn realloc( + &mut self, + old_ptr: Pointer>, + new_size: u64, + kind: MiriMemoryKind, + ) -> InterpResult<'tcx, Pointer>> { + let this = self.eval_context_mut(); + let new_align = this.min_align(new_size, kind); + if this.ptr_is_null(old_ptr)? { + if new_size == 0 { + Ok(Pointer::null()) + } else { + let new_ptr = + this.allocate_ptr(Size::from_bytes(new_size), new_align, kind.into())?; + Ok(new_ptr.into()) + } + } else { + if new_size == 0 { + this.deallocate_ptr(old_ptr, None, kind.into())?; + Ok(Pointer::null()) + } else { + let new_ptr = this.reallocate_ptr( + old_ptr, + None, + Size::from_bytes(new_size), + new_align, + kind.into(), + )?; + Ok(new_ptr.into()) + } + } + } +} + +impl<'mir, 'tcx: 'mir> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Read bytes from a `(ptr, len)` argument fn read_byte_slice<'i>(&'i self, bytes: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, &'i [u8]> where @@ -257,129 +339,47 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(bytes) } - /// Emulates calling a foreign item, failing if the item is not supported. - /// This function will handle `goto_block` if needed. - /// Returns Ok(None) if the foreign item was completely handled - /// by this function. - /// Returns Ok(Some(body)) if processing the foreign item - /// is delegated to another function. - fn emulate_foreign_item( - &mut self, - link_name: Symbol, - abi: Abi, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - unwind: mir::UnwindAction, - ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { - let this = self.eval_context_mut(); - let tcx = this.tcx.tcx; - - // First: functions that diverge. - let ret = match ret { - None => - match link_name.as_str() { - "miri_start_panic" => { - // `check_shim` happens inside `handle_miri_start_panic`. - this.handle_miri_start_panic(abi, link_name, args, unwind)?; - return Ok(None); - } - // This matches calls to the foreign item `panic_impl`. - // The implementation is provided by the function with the `#[panic_handler]` attribute. - "panic_impl" => { - // We don't use `check_shim` here because we are just forwarding to the lang - // item. Argument count checking will be performed when the returned `Body` is - // called. - this.check_abi_and_shim_symbol_clash(abi, Abi::Rust, link_name)?; - let panic_impl_id = tcx.lang_items().panic_impl().unwrap(); - let panic_impl_instance = ty::Instance::mono(tcx, panic_impl_id); - return Ok(Some(( - this.load_mir(panic_impl_instance.def, None)?, - panic_impl_instance, - ))); - } - #[rustfmt::skip] - | "exit" - | "ExitProcess" - => { - let exp_abi = if link_name.as_str() == "exit" { - Abi::C { unwind: false } - } else { - Abi::System { unwind: false } - }; - let [code] = this.check_shim(abi, exp_abi, link_name, args)?; - // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway - let code = this.read_scalar(code)?.to_i32()?; - throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false }); - } - "abort" => { - let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - throw_machine_stop!(TerminationInfo::Abort( - "the program aborted execution".to_owned() - )) - } - _ => { - if let Some(body) = this.lookup_exported_symbol(link_name)? { - return Ok(Some(body)); - } - this.handle_unsupported(format!( - "can't call (diverging) foreign function: {link_name}" - ))?; - return Ok(None); - } - }, - Some(p) => p, + /// Returns the minimum alignment for the target architecture for allocations of the given size. + fn min_align(&self, size: u64, kind: MiriMemoryKind) -> Align { + let this = self.eval_context_ref(); + // List taken from `library/std/src/sys/common/alloc.rs`. + // This list should be kept in sync with the one from libstd. + let min_align = match this.tcx.sess.target.arch.as_ref() { + "x86" | "arm" | "mips" | "mips32r6" | "powerpc" | "powerpc64" | "asmjs" | "wasm32" => 8, + "x86_64" | "aarch64" | "mips64" | "mips64r6" | "s390x" | "sparc64" | "loongarch64" => + 16, + arch => bug!("unsupported target architecture for malloc: `{}`", arch), }; - - // Second: functions that return immediately. - match this.emulate_foreign_item_inner(link_name, abi, args, dest)? { - EmulateByNameResult::NeedsJumping => { - trace!("{:?}", this.dump_place(dest)); - this.go_to_block(ret); - } - EmulateByNameResult::AlreadyJumped => (), - EmulateByNameResult::MirBody(mir, instance) => return Ok(Some((mir, instance))), - EmulateByNameResult::NotSupported => { - if let Some(body) = this.lookup_exported_symbol(link_name)? { - return Ok(Some(body)); - } - - this.handle_unsupported(format!( - "can't call foreign function `{link_name}` on OS `{os}`", - os = this.tcx.sess.target.os, - ))?; - return Ok(None); + // Windows always aligns, even small allocations. + // Source: + // But jemalloc does not, so for the C heap we only align if the allocation is sufficiently big. + if kind == MiriMemoryKind::WinHeap || size >= min_align { + return Align::from_bytes(min_align).unwrap(); + } + // We have `size < min_align`. Round `size` *down* to the next power of two and use that. + fn prev_power_of_two(x: u64) -> u64 { + let next_pow2 = x.next_power_of_two(); + if next_pow2 == x { + // x *is* a power of two, just use that. + x + } else { + // x is between two powers, so next = 2*prev. + next_pow2 / 2 } } - - Ok(None) - } - - /// Emulates a call to a `DynSym`. - fn emulate_dyn_sym( - &mut self, - sym: DynSym, - abi: Abi, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - unwind: mir::UnwindAction, - ) -> InterpResult<'tcx> { - let res = self.emulate_foreign_item(sym.0, abi, args, dest, ret, unwind)?; - assert!(res.is_none(), "DynSyms that delegate are not supported"); - Ok(()) + Align::from_bytes(prev_power_of_two(size)).unwrap() } /// Emulates calling the internal __rust_* allocator functions fn emulate_allocator( &mut self, default: impl FnOnce(&mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); let Some(allocator_kind) = this.tcx.allocator_kind(()) else { // in real code, this symbol does not exist without an allocator - return Ok(EmulateByNameResult::NotSupported); + return Ok(EmulateForeignItemResult::NotSupported); }; match allocator_kind { @@ -389,11 +389,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // and not execute any Miri shim. Somewhat unintuitively doing so is done // by returning `NotSupported`, which triggers the `lookup_exported_symbol` // fallback case in `emulate_foreign_item`. - return Ok(EmulateByNameResult::NotSupported); + return Ok(EmulateForeignItemResult::NotSupported); } AllocatorKind::Default => { default(this)?; - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } } @@ -404,7 +404,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); // First deal with any external C functions in linked .so file. @@ -415,7 +415,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // by the specified `.so` file; we should continue and check if it corresponds to // a provided shim. if this.call_external_c_fct(link_name, dest, args)? { - return Ok(EmulateByNameResult::NeedsJumping); + return Ok(EmulateForeignItemResult::NeedsJumping); } } @@ -615,7 +615,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "__rust_alloc" => return this.emulate_allocator(default), "miri_alloc" => { default(this)?; - return Ok(EmulateByNameResult::NeedsJumping); + return Ok(EmulateForeignItemResult::NeedsJumping); } _ => unreachable!(), } @@ -675,7 +675,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } "miri_dealloc" => { default(this)?; - return Ok(EmulateByNameResult::NeedsJumping); + return Ok(EmulateForeignItemResult::NeedsJumping); } _ => unreachable!(), } @@ -1076,12 +1076,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, ), - _ => Ok(EmulateByNameResult::NotSupported), + _ => Ok(EmulateForeignItemResult::NotSupported), }, }; // We only fall through to here if we did *not* hit the `_` arm above, // i.e., if we actually emulated the function with one of the shims. - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } /// Check some basic requirements for this allocation request: diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs index b610cf97750f3..66ce0d4ebdbc5 100644 --- a/src/tools/miri/src/shims/unix/android/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs @@ -2,7 +2,7 @@ use rustc_span::Symbol; use rustc_target::spec::abi::Abi; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} @@ -17,7 +17,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); match link_name.as_str() { @@ -26,10 +26,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.write_null(dest)?; } - _ => return Ok(EmulateByNameResult::NotSupported), + _ => return Ok(EmulateForeignItemResult::NotSupported), } #[allow(unreachable_code)] - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 06ffdbff4e6d0..76021e9de95c4 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -9,7 +9,7 @@ use rustc_target::abi::{Align, Size}; use rustc_target::spec::abi::Abi; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; use shims::unix::fs::EvalContextExt as _; use shims::unix::mem::EvalContextExt as _; use shims::unix::sync::EvalContextExt as _; @@ -28,7 +28,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. @@ -626,11 +626,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "linux" => linux::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "macos" => macos::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), - _ => Ok(EmulateByNameResult::NotSupported), + _ => Ok(EmulateForeignItemResult::NotSupported), }; } }; - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index 388b205267953..869434e8876ed 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -2,7 +2,7 @@ use rustc_span::Symbol; use rustc_target::spec::abi::Abi; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; use shims::unix::thread::EvalContextExt as _; pub fn is_dyn_sym(_name: &str) -> bool { @@ -17,7 +17,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); match link_name.as_str() { // Threading @@ -45,8 +45,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } - _ => return Ok(EmulateByNameResult::NotSupported), + _ => return Ok(EmulateForeignItemResult::NotSupported), } - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 9f5f6ea9bd091..17129c372ea61 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -4,7 +4,7 @@ use rustc_target::spec::abi::Abi; use crate::machine::SIGRTMAX; use crate::machine::SIGRTMIN; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; use shims::unix::fs::EvalContextExt as _; use shims::unix::linux::fd::EvalContextExt as _; use shims::unix::linux::mem::EvalContextExt as _; @@ -24,7 +24,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. @@ -186,7 +186,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } id => { this.handle_unsupported(format!("can't execute syscall with ID {id}"))?; - return Ok(EmulateByNameResult::AlreadyJumped); + return Ok(EmulateForeignItemResult::AlreadyJumped); } } } @@ -217,10 +217,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_null(dest)?; } - _ => return Ok(EmulateByNameResult::NotSupported), + _ => return Ok(EmulateForeignItemResult::NotSupported), }; - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index cb0af4c827914..5881a3f46f295 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -2,7 +2,7 @@ use rustc_span::Symbol; use rustc_target::spec::abi::Abi; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; use shims::unix::fs::EvalContextExt as _; use shims::unix::thread::EvalContextExt as _; @@ -18,7 +18,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. @@ -209,9 +209,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(res, dest)?; } - _ => return Ok(EmulateByNameResult::NotSupported), + _ => return Ok(EmulateForeignItemResult::NotSupported), }; - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index fe2f48638b8f7..759a412c16a25 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -6,7 +6,7 @@ use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; use shims::windows::handle::{EvalContextExt as _, Handle, PseudoHandle}; use shims::windows::sync::EvalContextExt as _; use shims::windows::thread::EvalContextExt as _; @@ -23,7 +23,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. @@ -583,9 +583,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_null(dest)?; } - _ => return Ok(EmulateByNameResult::NotSupported), + _ => return Ok(EmulateForeignItemResult::NotSupported), } - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index 7c280109cb011..53a4a1ef28a7f 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -5,7 +5,7 @@ use rustc_target::spec::abi::Abi; use crate::*; use helpers::bool_to_simd_element; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; mod sse; mod sse2; @@ -22,7 +22,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.").unwrap(); @@ -34,7 +34,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/addcarry-u32-addcarry-u64.html "addcarry.32" | "addcarry.64" => { if unprefixed_name == "addcarry.64" && this.tcx.sess.target.arch != "x86_64" { - return Ok(EmulateByNameResult::NotSupported); + return Ok(EmulateForeignItemResult::NotSupported); } let [c_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; @@ -60,7 +60,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/subborrow-u32-subborrow-u64.html "subborrow.32" | "subborrow.64" => { if unprefixed_name == "subborrow.64" && this.tcx.sess.target.arch != "x86_64" { - return Ok(EmulateByNameResult::NotSupported); + return Ok(EmulateForeignItemResult::NotSupported); } let [b_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; @@ -100,9 +100,9 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this, link_name, abi, args, dest, ); } - _ => return Ok(EmulateByNameResult::NotSupported), + _ => return Ok(EmulateForeignItemResult::NotSupported), } - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs index fa722f4b75ecd..6f0b76059f10d 100644 --- a/src/tools/miri/src/shims/x86/sse.rs +++ b/src/tools/miri/src/shims/x86/sse.rs @@ -7,7 +7,7 @@ use rand::Rng as _; use super::{bin_op_simd_float_all, bin_op_simd_float_first, FloatBinOp, FloatCmpOp}; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -19,7 +19,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse.").unwrap(); @@ -228,9 +228,9 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.write_scalar(Scalar::from_u32(res), dest)?; } - _ => return Ok(EmulateByNameResult::NotSupported), + _ => return Ok(EmulateForeignItemResult::NotSupported), } - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index 261c947c8efd2..c6a847b5cf824 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -10,7 +10,7 @@ use rustc_target::spec::abi::Abi; use super::{bin_op_simd_float_all, bin_op_simd_float_first, FloatBinOp, FloatCmpOp}; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -22,7 +22,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse2.").unwrap(); @@ -797,9 +797,9 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.yield_active_thread(); } - _ => return Ok(EmulateByNameResult::NotSupported), + _ => return Ok(EmulateForeignItemResult::NotSupported), } - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs index f5c30a521fa8b..a41de5dbf7ee5 100644 --- a/src/tools/miri/src/shims/x86/sse3.rs +++ b/src/tools/miri/src/shims/x86/sse3.rs @@ -5,7 +5,7 @@ use rustc_target::spec::abi::Abi; use super::horizontal_bin_op; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -17,7 +17,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse3.").unwrap(); @@ -83,8 +83,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: /*nonoverlapping*/ true, )?; } - _ => return Ok(EmulateByNameResult::NotSupported), + _ => return Ok(EmulateForeignItemResult::NotSupported), } - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/ssse3.rs b/src/tools/miri/src/shims/x86/ssse3.rs index b01546722346b..dbc2b947b3322 100644 --- a/src/tools/miri/src/shims/x86/ssse3.rs +++ b/src/tools/miri/src/shims/x86/ssse3.rs @@ -4,7 +4,7 @@ use rustc_target::spec::abi::Abi; use super::horizontal_bin_op; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -16,7 +16,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.ssse3.").unwrap(); @@ -192,8 +192,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.write_immediate(*res, &dest)?; } } - _ => return Ok(EmulateByNameResult::NotSupported), + _ => return Ok(EmulateForeignItemResult::NotSupported), } - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } From 16cde069fc7e727dca3c6d8ec5077f0d2f6f928b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 6 Oct 2023 09:38:50 +0200 Subject: [PATCH 14/21] allow dyn_sym in the files where they are defined; remove unreachable android code --- src/tools/miri/src/machine.rs | 3 ++- .../src/shims/unix/android/foreign_items.rs | 11 +++----- .../miri/src/shims/unix/foreign_items.rs | 26 +++++++++++++------ .../src/shims/unix/linux/foreign_items.rs | 4 +-- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 54f90b2c03990..bd7ec88fc1c3b 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -707,7 +707,8 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { ); } "android" => { - // "signal" + // "signal" -- just needs a non-zero pointer value (function does not even get called), + // but we arrange for this to be callable anyway (it will then do nothing). let layout = this.machine.layouts.const_raw_ptr; let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str("signal"))); let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout); diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs index 66ce0d4ebdbc5..f61ebd5a3a8dc 100644 --- a/src/tools/miri/src/shims/unix/android/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs @@ -6,11 +6,12 @@ use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub fn is_dyn_sym(name: &str) -> bool { - matches!(name, "signal") +pub fn is_dyn_sym(_name: &str) -> bool { + false } pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { + #[allow(unused, clippy::match_single_binding)] // there isn't anything here yet fn emulate_foreign_item_inner( &mut self, link_name: Symbol, @@ -21,15 +22,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); match link_name.as_str() { - "signal" if this.frame_in_std() => { - let [_sig, _func] = - this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - this.write_null(dest)?; - } _ => return Ok(EmulateForeignItemResult::NotSupported), } - #[allow(unreachable_code)] Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 76021e9de95c4..f18fa1cbbb7ab 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -20,6 +20,23 @@ use shims::unix::freebsd::foreign_items as freebsd; use shims::unix::linux::foreign_items as linux; use shims::unix::macos::foreign_items as macos; +fn is_dyn_sym(name: &str, target_os: &str) -> bool { + match name { + // `signal` is set up as a weak symbol in `init_extern_statics` so we might as well allow it + // in `dlsym` as well. + "signal" => true, + // Give specific OSes a chance to allow their symbols. + _ => + match target_os { + "android" => android::is_dyn_sym(name), + "freebsd" => freebsd::is_dyn_sym(name), + "linux" => linux::is_dyn_sym(name), + "macos" => macos::is_dyn_sym(name), + target_os => panic!("unsupported Unix OS {target_os}"), + }, + } +} + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn emulate_foreign_item_inner( @@ -237,14 +254,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.read_target_usize(handle)?; let symbol = this.read_pointer(symbol)?; let name = this.read_c_str(symbol)?; - let is_dyn_sym = |name| match &*this.tcx.sess.target.os { - "android" => android::is_dyn_sym(name), - "freebsd" => freebsd::is_dyn_sym(name), - "linux" => linux::is_dyn_sym(name), - "macos" => macos::is_dyn_sym(name), - target_os => panic!("unsupported Unix OS {target_os}"), - }; - if let Ok(name) = str::from_utf8(name) && is_dyn_sym(name) { + if let Ok(name) = str::from_utf8(name) && is_dyn_sym(name, &this.tcx.sess.target.os) { let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str(name))); this.write_pointer(ptr, dest)?; } else { diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 17129c372ea61..6937e0f089ec8 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -12,8 +12,8 @@ use shims::unix::linux::sync::futex; use shims::unix::sync::EvalContextExt as _; use shims::unix::thread::EvalContextExt as _; -pub fn is_dyn_sym(_name: &str) -> bool { - false +pub fn is_dyn_sym(name: &str) -> bool { + matches!(name, "getrandom") } impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} From 03a03e2ef66f80548681b8dbbf387b55e7b8a3cb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 6 Oct 2023 11:06:16 +0200 Subject: [PATCH 15/21] add a direct dlsym test --- .../miri/src/shims/unix/foreign_items.rs | 8 +++-- src/tools/miri/src/shims/unix/fs.rs | 35 ++++++++++--------- .../miri/tests/pass-dep/shims/libc-misc.rs | 14 ++++++++ 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index f18fa1cbbb7ab..c013d27502927 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -22,8 +22,10 @@ use shims::unix::macos::foreign_items as macos; fn is_dyn_sym(name: &str, target_os: &str) -> bool { match name { - // `signal` is set up as a weak symbol in `init_extern_statics` so we might as well allow it - // in `dlsym` as well. + // Used for tests. + "isatty" => true, + // `signal` is set up as a weak symbol in `init_extern_statics` (on Android) so we might as + // well allow it in `dlsym`. "signal" => true, // Give specific OSes a chance to allow their symbols. _ => @@ -588,7 +590,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "getuid" if this.frame_in_std() => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - // FOr now, just pretend we always have this fixed UID. + // For now, just pretend we always have this fixed UID. this.write_int(super::UID, dest)?; } diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 8963dfb97a6e5..1014a61b75ed2 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -63,7 +63,7 @@ pub trait FileDescriptor: std::fmt::Debug + Any { fn dup(&mut self) -> io::Result>; - fn is_tty(&self) -> bool { + fn is_tty(&self, _communicate_allowed: bool) -> bool { false } @@ -156,8 +156,8 @@ impl FileDescriptor for FileHandle { Some(self.file.as_raw_fd()) } - fn is_tty(&self) -> bool { - self.file.is_terminal() + fn is_tty(&self, communicate_allowed: bool) -> bool { + communicate_allowed && self.file.is_terminal() } } @@ -188,8 +188,8 @@ impl FileDescriptor for io::Stdin { Some(libc::STDIN_FILENO) } - fn is_tty(&self) -> bool { - self.is_terminal() + fn is_tty(&self, communicate_allowed: bool) -> bool { + communicate_allowed && self.is_terminal() } } @@ -225,8 +225,8 @@ impl FileDescriptor for io::Stdout { Some(libc::STDOUT_FILENO) } - fn is_tty(&self) -> bool { - self.is_terminal() + fn is_tty(&self, communicate_allowed: bool) -> bool { + communicate_allowed && self.is_terminal() } } @@ -255,8 +255,8 @@ impl FileDescriptor for io::Stderr { Some(libc::STDERR_FILENO) } - fn is_tty(&self) -> bool { - self.is_terminal() + fn is_tty(&self, communicate_allowed: bool) -> bool { + communicate_allowed && self.is_terminal() } } @@ -1721,15 +1721,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); // "returns 1 if fd is an open file descriptor referring to a terminal; // otherwise 0 is returned, and errno is set to indicate the error" - if matches!(this.machine.isolated_op, IsolatedOp::Allow) { - let fd = this.read_scalar(miri_fd)?.to_i32()?; - if this.machine.file_handler.handles.get(&fd).map(|fd| fd.is_tty()) == Some(true) { + let fd = this.read_scalar(miri_fd)?.to_i32()?; + let error = if let Some(fd) = this.machine.file_handler.handles.get(&fd) { + if fd.is_tty(this.machine.communicate()) { return Ok(Scalar::from_i32(1)); + } else { + this.eval_libc("ENOTTY") } - } - // Fallback when the FD was not found or isolation is enabled. - let enotty = this.eval_libc("ENOTTY"); - this.set_last_error(enotty)?; + } else { + // FD does not exist + this.eval_libc("EBADF") + }; + this.set_last_error(error)?; Ok(Scalar::from_i32(0)) } diff --git a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs index ebfeb863abfd9..82c49cfb17c5a 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs @@ -3,6 +3,7 @@ #![feature(io_error_more)] use std::fs::{remove_file, File}; +use std::mem::transmute; use std::os::unix::io::AsRawFd; use std::path::PathBuf; @@ -375,6 +376,18 @@ fn test_sigrt() { assert!(max - min >= 8) } +fn test_dlsym() { + let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, b"notasymbol\0".as_ptr().cast()) }; + assert!(addr as usize == 0); + + let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, b"isatty\0".as_ptr().cast()) }; + assert!(addr as usize != 0); + let isatty: extern "C" fn(i32) -> i32 = unsafe { transmute(addr) }; + assert_eq!(isatty(999), 0); + let errno = std::io::Error::last_os_error().raw_os_error().unwrap(); + assert_eq!(errno, libc::EBADF); +} + fn main() { test_posix_gettimeofday(); test_posix_mkstemp(); @@ -387,6 +400,7 @@ fn main() { test_isatty(); test_clocks(); + test_dlsym(); test_memcpy(); test_strcpy(); From bf1356efc3d3d2c6b5c3fb3157d234f7a0901bc8 Mon Sep 17 00:00:00 2001 From: Neven Villani Date: Wed, 20 Sep 2023 14:27:20 +0200 Subject: [PATCH 16/21] Fix problems of Reserved -> Frozen Reserved loses permissions too quickly. Adding more fine-grained behavior of Reserved lets it lose write permissions only temporarily. Protected tags receive a read access on initialized locations. --- src/tools/miri/src/borrow_tracker/mod.rs | 20 +- .../stacked_borrows/diagnostics.rs | 3 +- .../src/borrow_tracker/stacked_borrows/mod.rs | 8 +- .../tree_borrows/diagnostics.rs | 21 +- .../src/borrow_tracker/tree_borrows/mod.rs | 57 ++- .../src/borrow_tracker/tree_borrows/perms.rs | 186 +++++---- .../src/borrow_tracker/tree_borrows/tree.rs | 380 +++++++++++------- .../borrow_tracker/tree_borrows/tree/tests.rs | 25 +- .../src/borrow_tracker/tree_borrows/unimap.rs | 7 +- src/tools/miri/src/machine.rs | 30 +- .../both_borrows/aliasing_mut1.tree.stderr | 6 +- .../both_borrows/aliasing_mut2.tree.stderr | 6 +- .../both_borrows/aliasing_mut3.tree.stderr | 6 +- .../newtype_pair_retagging.tree.stderr | 6 +- .../newtype_retagging.tree.stderr | 6 +- .../retag_data_race_protected_read.rs | 29 -- ...retag_data_race_protected_read.tree.stderr | 25 -- .../retag_data_race_protected_read.rs | 30 ++ .../retag_data_race_protected_read.stderr} | 0 .../reserved/cell-protected-write.stderr | 14 +- .../reserved/int-protected-write.stderr | 14 +- .../tests/fail/tree_borrows/spurious_read.rs | 117 ++++++ .../fail/tree_borrows/spurious_read.stderr | 44 ++ .../tree_borrows/cell-alternate-writes.stderr | 12 +- .../pass/tree_borrows/end-of-protector.stderr | 48 +-- .../tests/pass/tree_borrows/formatting.stderr | 50 +-- .../pass/tree_borrows/read_retag_no_race.rs | 114 ++++++ .../tree_borrows/read_retag_no_race.stderr | 8 + .../pass/tree_borrows/reborrow-is-read.stderr | 18 +- .../tests/pass/tree_borrows/reserved.stderr | 68 ++-- .../tests/pass/tree_borrows/spurious_read.rs | 115 ++++++ .../pass/tree_borrows/spurious_read.stderr | 16 + .../tests/pass/tree_borrows/tree-borrows.rs | 19 + .../pass/tree_borrows/unique.default.stderr | 24 +- .../pass/tree_borrows/unique.uniq.stderr | 30 +- .../tree_borrows/vec_unique.default.stderr | 6 +- .../pass/tree_borrows/vec_unique.uniq.stderr | 10 +- 37 files changed, 1097 insertions(+), 481 deletions(-) delete mode 100644 src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.rs delete mode 100644 src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.tree.stderr create mode 100644 src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs rename src/tools/miri/tests/fail/{both_borrows/retag_data_race_protected_read.stack.stderr => stacked_borrows/retag_data_race_protected_read.stderr} (100%) create mode 100644 src/tools/miri/tests/fail/tree_borrows/spurious_read.rs create mode 100644 src/tools/miri/tests/fail/tree_borrows/spurious_read.stderr create mode 100644 src/tools/miri/tests/pass/tree_borrows/read_retag_no_race.rs create mode 100644 src/tools/miri/tests/pass/tree_borrows/read_retag_no_race.stderr create mode 100644 src/tools/miri/tests/pass/tree_borrows/spurious_read.rs create mode 100644 src/tools/miri/tests/pass/tree_borrows/spurious_read.stderr diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index 1951cf87f2f32..a95571572d684 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -66,10 +66,13 @@ pub struct FrameState { /// `stacked_borrows::GlobalState` upon function return, and if we attempt to pop a protected /// tag, to identify which call is responsible for protecting the tag. /// See `Stack::item_popped` for more explanation. + /// Tree Borrows also needs to know which allocation these tags + /// belong to so that it can perform a read through them immediately before + /// the frame gets popped. /// /// This will contain one tag per reference passed to the function, so /// a size of 2 is enough for the vast majority of functions. - pub protected_tags: SmallVec<[BorTag; 2]>, + pub protected_tags: SmallVec<[(AllocId, BorTag); 2]>, } impl VisitTags for FrameState { @@ -208,7 +211,7 @@ impl GlobalStateInner { } pub fn end_call(&mut self, frame: &machine::FrameExtra<'_>) { - for tag in &frame + for (_, tag) in &frame .borrow_tracker .as_ref() .expect("we should have borrow tracking data") @@ -453,6 +456,19 @@ impl AllocState { AllocState::TreeBorrows(tb) => tb.borrow_mut().remove_unreachable_tags(tags), } } + + /// Tree Borrows needs to be told when a tag stops being protected. + pub fn release_protector<'tcx>( + &self, + machine: &MiriMachine<'_, 'tcx>, + global: &GlobalState, + tag: BorTag, + ) -> InterpResult<'tcx> { + match self { + AllocState::StackedBorrows(_sb) => Ok(()), + AllocState::TreeBorrows(tb) => tb.borrow_mut().release_protector(machine, global, tag), + } + } } impl VisitTags for AllocState { diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs index 1ef30cb9fad20..1a11879fa9012 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -436,6 +436,7 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> { ProtectorKind::WeakProtector => "weakly protected", ProtectorKind::StrongProtector => "strongly protected", }; + let item_tag = item.tag(); let call_id = self .machine .threads @@ -444,7 +445,7 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> { .map(|frame| { frame.extra.borrow_tracker.as_ref().expect("we should have borrow tracking data") }) - .find(|frame| frame.protected_tags.contains(&item.tag())) + .find(|frame| frame.protected_tags.iter().any(|(_, tag)| tag == &item_tag)) .map(|frame| frame.call_id) .unwrap(); // FIXME: Surely we should find something, but a panic seems wrong here? match self.operation { diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index a440ee720c78b..66b729fb166b5 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -719,7 +719,13 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' if let Some(protect) = new_perm.protector() { // See comment in `Stack::item_invalidated` for why we store the tag twice. - this.frame_mut().extra.borrow_tracker.as_mut().unwrap().protected_tags.push(new_tag); + this.frame_mut() + .extra + .borrow_tracker + .as_mut() + .unwrap() + .protected_tags + .push((alloc_id, new_tag)); this.machine .borrow_tracker .as_mut() diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs index fd45671ba29d8..b3001b5b88cdc 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs @@ -19,6 +19,7 @@ pub enum AccessCause { Explicit(AccessKind), Reborrow, Dealloc, + FnExit, } impl fmt::Display for AccessCause { @@ -27,6 +28,7 @@ impl fmt::Display for AccessCause { Self::Explicit(kind) => write!(f, "{kind}"), Self::Reborrow => write!(f, "reborrow"), Self::Dealloc => write!(f, "deallocation"), + Self::FnExit => write!(f, "protector release"), } } } @@ -38,6 +40,7 @@ impl AccessCause { Self::Explicit(kind) => format!("{rel} {kind}"), Self::Reborrow => format!("reborrow (acting as a {rel} read access)"), Self::Dealloc => format!("deallocation (acting as a {rel} write access)"), + Self::FnExit => format!("protector release (acting as a {rel} read access)"), } } } @@ -52,7 +55,9 @@ pub struct Event { /// Relative position of the tag to the one used for the access. pub is_foreign: bool, /// User-visible range of the access. - pub access_range: AllocRange, + /// `None` means that this is an implicit access to the entire allocation + /// (used for the implicit read on protector release). + pub access_range: Option, /// The transition recorded by this event only occured on a subrange of /// `access_range`: a single access on `access_range` triggers several events, /// each with their own mutually disjoint `transition_range`. No-op transitions @@ -123,7 +128,17 @@ impl HistoryData { // NOTE: `transition_range` is explicitly absent from the error message, it has no significance // to the user. The meaningful one is `access_range`. let access = access_cause.print_as_access(is_foreign); - self.events.push((Some(span.data()), format!("{this} later transitioned to {endpoint} due to a {access} at offsets {access_range:?}", endpoint = transition.endpoint()))); + let access_range_text = match access_range { + Some(r) => format!("at offsets {r:?}"), + None => format!("on every location previously accessed by this tag"), + }; + self.events.push(( + Some(span.data()), + format!( + "{this} later transitioned to {endpoint} due to a {access} {access_range_text}", + endpoint = transition.endpoint() + ), + )); self.events .push((None, format!("this transition corresponds to {}", transition.summary()))); } @@ -745,7 +760,7 @@ const DEFAULT_FORMATTER: DisplayFmt = DisplayFmt { bot: '─', warning_text: "Warning: this tree is indicative only. Some tags may have been hidden.", }, - perm: DisplayFmtPermission { open: "|", sep: "|", close: "|", uninit: "---", range_sep: ".." }, + perm: DisplayFmtPermission { open: "|", sep: "|", close: "|", uninit: "----", range_sep: ".." }, padding: DisplayFmtPadding { join_middle: "├", join_last: "└", diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 68bc4a415c601..6d4c573a35c01 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -2,7 +2,9 @@ use log::trace; use rustc_target::abi::{Abi, Align, Size}; -use crate::borrow_tracker::{AccessKind, GlobalStateInner, ProtectorKind, RetagFields}; +use crate::borrow_tracker::{ + AccessKind, GlobalState, GlobalStateInner, ProtectorKind, RetagFields, +}; use rustc_middle::{ mir::{Mutability, RetagKind}, ty::{ @@ -70,7 +72,7 @@ impl<'tcx> Tree { self.perform_access( access_kind, tag, - range, + Some(range), global, span, diagnostics::AccessCause::Explicit(access_kind), @@ -99,6 +101,29 @@ impl<'tcx> Tree { pub fn expose_tag(&mut self, _tag: BorTag) { // TODO } + + /// A tag just lost its protector. + /// + /// This emits a special kind of access that is only applied + /// to initialized locations, as a protection against other + /// tags not having been made aware of the existence of this + /// protector. + pub fn release_protector( + &mut self, + machine: &MiriMachine<'_, 'tcx>, + global: &GlobalState, + tag: BorTag, + ) -> InterpResult<'tcx> { + let span = machine.current_span(); + self.perform_access( + AccessKind::Read, + tag, + None, // no specified range because it occurs on the entire allocation + global, + span, + diagnostics::AccessCause::FnExit, + ) + } } /// Policy for a new borrow. @@ -248,7 +273,13 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' // We register the protection in two different places. // This makes creating a protector slower, but checking whether a tag // is protected faster. - this.frame_mut().extra.borrow_tracker.as_mut().unwrap().protected_tags.push(new_tag); + this.frame_mut() + .extra + .borrow_tracker + .as_mut() + .unwrap() + .protected_tags + .push((alloc_id, new_tag)); this.machine .borrow_tracker .as_mut() @@ -275,7 +306,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' tree_borrows.perform_access( AccessKind::Read, orig_tag, - range, + Some(range), this.machine.borrow_tracker.as_ref().unwrap(), this.machine.current_span(), diagnostics::AccessCause::Reborrow, @@ -287,21 +318,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' // Also inform the data race model (but only if any bytes are actually affected). if range.size.bytes() > 0 { if let Some(data_race) = alloc_extra.data_race.as_ref() { - // We sometimes need to make it a write, since not all retags commute with reads! - // FIXME: Is that truly the semantics we want? Some optimizations are likely to be - // very unhappy without this. We'd tsill ge some UB just by picking a suitable - // interleaving, but wether UB happens can depend on whether a write occurs in the - // future... - let is_write = new_perm.initial_state.is_active() - || (new_perm.initial_state.is_reserved(None) && new_perm.protector.is_some()); - if is_write { - // Need to get mutable access to alloc_extra. - // (Cannot always do this as we can do read-only reborrowing on read-only allocations.) - let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?; - alloc_extra.data_race.as_mut().unwrap().write(alloc_id, range, machine)?; - } else { - data_race.read(alloc_id, range, &this.machine)?; - } + data_race.read(alloc_id, range, &this.machine)?; } } @@ -532,7 +549,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // if converting this alloc_id from a global to a local one // uncovers a non-supported `extern static`. let alloc_extra = this.get_alloc_extra(alloc_id)?; - trace!("Stacked Borrows tag {tag:?} exposed in {alloc_id:?}"); + trace!("Tree Borrows tag {tag:?} exposed in {alloc_id:?}"); alloc_extra.borrow_tracker_tb().borrow_mut().expose_tag(tag); } AllocKind::Function | AllocKind::VTable | AllocKind::Dead => { diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs index 3e019356ca746..bf72e902993b4 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs @@ -10,9 +10,18 @@ use crate::borrow_tracker::AccessKind; enum PermissionPriv { /// represents: a local reference that has not yet been written to; /// allows: child reads, foreign reads, foreign writes if type is freeze; - /// rejects: child writes (Active), foreign writes (Disabled, except if type is not freeze). - /// special case: behaves differently when protected to adhere more closely to noalias - Reserved { ty_is_freeze: bool }, + /// affected by: child writes (becomes Active), + /// rejects: foreign writes (Disabled, except if type is not freeze). + /// + /// special case: behaves differently when protected, which is where `conflicted` + /// is relevant + /// - `conflicted` is set on foreign reads, + /// - `conflicted` must not be set on child writes (there is UB otherwise). + /// This is so that the behavior of `Reserved` adheres to the rules of `noalias`: + /// - foreign-read then child-write is UB due to `conflicted`, + /// - child-write then foreign-read is UB since child-write will activate and then + /// foreign-read disables a protected `Active`, which is UB. + Reserved { ty_is_freeze: bool, conflicted: bool }, /// represents: a unique pointer; /// allows: child reads, child writes; /// rejects: foreign reads (Frozen), foreign writes (Disabled). @@ -29,10 +38,11 @@ enum PermissionPriv { use PermissionPriv::*; impl PartialOrd for PermissionPriv { - /// PermissionPriv is ordered as follows: - /// - Reserved(_) < Active < Frozen < Disabled; - /// - different kinds of `Reserved` (with or without interior mutability) - /// are incomparable to each other. + /// PermissionPriv is ordered by the reflexive transitive closure of + /// `Reserved(conflicted=false) < Reserved(conflicted=true) < Active < Frozen < Disabled`. + /// `Reserved` that have incompatible `ty_is_freeze` are incomparable to each other. + /// This ordering matches the reachability by transitions, as asserted by the exhaustive test + /// `permissionpriv_partialord_is_reachability`. fn partial_cmp(&self, other: &Self) -> Option { use Ordering::*; Some(match (self, other) { @@ -43,7 +53,17 @@ impl PartialOrd for PermissionPriv { (_, Frozen) => Less, (Active, _) => Greater, (_, Active) => Less, - (Reserved { .. }, Reserved { .. }) => return None, + ( + Reserved { ty_is_freeze: f1, conflicted: c1 }, + Reserved { ty_is_freeze: f2, conflicted: c2 }, + ) => { + // No transition ever changes `ty_is_freeze`. + if f1 != f2 { + return None; + } + // `bool` is ordered such that `false <= true`, so this works as intended. + c1.cmp(c2) + } }) } } @@ -51,7 +71,7 @@ impl PartialOrd for PermissionPriv { impl PermissionPriv { /// Check if `self` can be the initial state of a pointer. fn is_initial(&self) -> bool { - matches!(self, Reserved { ty_is_freeze: _ } | Frozen) + matches!(self, Reserved { conflicted: false, .. } | Frozen) } } @@ -66,12 +86,13 @@ mod transition { Some(match state { Disabled => return None, // The inner data `ty_is_freeze` of `Reserved` is always irrelevant for Read - // accesses, since the data is not being mutated. Hence the `{ .. }` + // accesses, since the data is not being mutated. Hence the `{ .. }`. readable @ (Reserved { .. } | Active | Frozen) => readable, }) } - /// A non-child node was read-accessed: noop on non-protected Reserved, advance to Frozen otherwise. + /// A non-child node was read-accessed: keep `Reserved` but mark it as `conflicted` if it + /// is protected; invalidate `Active`. fn foreign_read(state: PermissionPriv, protected: bool) -> Option { Some(match state { // Non-writeable states just ignore foreign reads. @@ -79,16 +100,14 @@ mod transition { // Writeable states are more tricky, and depend on whether things are protected. // The inner data `ty_is_freeze` of `Reserved` is always irrelevant for Read // accesses, since the data is not being mutated. Hence the `{ .. }` - res @ Reserved { .. } => - if protected { - // Someone else read, make sure we won't write. - // We could make this `Disabled` but it doesn't look like we get anything out of that extra UB. - Frozen - } else { - // Before activation and without protectors, foreign reads are fine. - // That's the entire point of 2-phase borrows. - res - }, + + // Someone else read. To make sure we won't write before function exit, + // we set the "conflicted" flag, which will disallow writes while we are protected. + Reserved { ty_is_freeze, .. } if protected => + Reserved { ty_is_freeze, conflicted: true }, + // Before activation and without protectors, foreign reads are fine. + // That's the entire point of 2-phase borrows. + res @ Reserved { .. } => res, Active => if protected { // We wrote, someone else reads -- that's bad. @@ -104,8 +123,12 @@ mod transition { /// A child node was write-accessed: `Reserved` must become `Active` to obtain /// write permissions, `Frozen` and `Disabled` cannot obtain such permissions and produce UB. - fn child_write(state: PermissionPriv, _protected: bool) -> Option { + fn child_write(state: PermissionPriv, protected: bool) -> Option { Some(match state { + // If the `conflicted` flag is set, then there was a foreign read during + // the function call that is still ongoing (still `protected`), + // this is UB (`noalias` violation). + Reserved { conflicted: true, .. } if protected => return None, // A write always activates the 2-phase borrow, even with interior // mutability Reserved { .. } | Active => Active, @@ -117,7 +140,8 @@ mod transition { /// non-protected interior mutable `Reserved` which stay the same. fn foreign_write(state: PermissionPriv, protected: bool) -> Option { Some(match state { - cell @ Reserved { ty_is_freeze: false } if !protected => cell, + Reserved { .. } if protected => Disabled, + res @ Reserved { ty_is_freeze: false, .. } => res, _ => Disabled, }) } @@ -166,7 +190,7 @@ impl Permission { /// Default initial permission of a reborrowed mutable reference. pub fn new_reserved(ty_is_freeze: bool) -> Self { - Self { inner: Reserved { ty_is_freeze } } + Self { inner: Reserved { ty_is_freeze, conflicted: false } } } /// Default initial permission of a reborrowed shared reference @@ -174,28 +198,6 @@ impl Permission { Self { inner: Frozen } } - pub fn is_active(self) -> bool { - matches!(self.inner, Active) - } - - // Leave `interior_mut` as `None` if interior mutability - // is irrelevant. - pub fn is_reserved(self, interior_mut: Option) -> bool { - match (interior_mut, self.inner) { - (None, Reserved { .. }) => true, - (Some(b1), Reserved { ty_is_freeze: b2 }) => b1 == b2, - _ => false, - } - } - - pub fn is_frozen(self) -> bool { - matches!(self.inner, Frozen) - } - - pub fn is_disabled(self) -> bool { - matches!(self.inner, Disabled) - } - /// Apply the transition to the inner PermissionPriv. pub fn perform_access( kind: AccessKind, @@ -251,8 +253,12 @@ pub mod diagnostics { f, "{}", match self { - Reserved { ty_is_freeze: true } => "Reserved", - Reserved { ty_is_freeze: false } => "Reserved (interior mutable)", + Reserved { ty_is_freeze: true, conflicted: false } => "Reserved", + Reserved { ty_is_freeze: true, conflicted: true } => "Reserved (conflicted)", + Reserved { ty_is_freeze: false, conflicted: false } => + "Reserved (interior mutable)", + Reserved { ty_is_freeze: false, conflicted: true } => + "Reserved (interior mutable, conflicted)", Active => "Active", Frozen => "Frozen", Disabled => "Disabled", @@ -280,11 +286,13 @@ pub mod diagnostics { // and also as `diagnostics::DisplayFmtPermission.uninit` otherwise // alignment will be incorrect. match self.inner { - Reserved { ty_is_freeze: true } => "Res", - Reserved { ty_is_freeze: false } => "Re*", - Active => "Act", - Frozen => "Frz", - Disabled => "Dis", + Reserved { ty_is_freeze: true, conflicted: false } => "Rs ", + Reserved { ty_is_freeze: true, conflicted: true } => "RsC ", + Reserved { ty_is_freeze: false, conflicted: false } => "RsM ", + Reserved { ty_is_freeze: false, conflicted: true } => "RsCM", + Active => "Act ", + Frozen => "Frz ", + Disabled => "Dis ", } } } @@ -292,15 +300,13 @@ pub mod diagnostics { impl PermTransition { /// Readable explanation of the consequences of an event. /// Fits in the sentence "This accessed caused {trans.summary()}". - /// - /// Important: for the purposes of this explanation, `Reserved` is considered - /// to have write permissions, because that's what the diagnostics care about - /// (otherwise `Reserved -> Frozen` would be considered a noop). pub fn summary(&self) -> &'static str { assert!(self.is_possible()); match (self.from, self.to) { (_, Active) => "the first write to a 2-phase borrowed mutable reference", (_, Frozen) => "a loss of write permissions", + (Reserved { conflicted: false, .. }, Reserved { conflicted: true, .. }) => + "a temporary loss of write permissions until function exit", (Frozen, Disabled) => "a loss of read permissions", (_, Disabled) => "a loss of read and write permissions", (old, new) => @@ -315,7 +321,7 @@ pub mod diagnostics { /// Irrelevant events: /// - modifications of write permissions when the error is related to read permissions /// (on failed reads and protected `Frozen -> Disabled`, ignore `Reserved -> Active`, - /// `Reserved -> Frozen`, and `Active -> Frozen`) + /// `Reserved(conflicted=false) -> Reserved(conflicted=true)`, and `Active -> Frozen`) /// - all transitions for attempts to deallocate strongly protected tags /// /// # Panics @@ -326,8 +332,9 @@ pub mod diagnostics { /// (Reserved < Active < Frozen < Disabled); /// - between `self` and `err` the permission should also be increasing, /// so all permissions inside `err` should be greater than `self.1`; - /// - `Active` and `Reserved` cannot cause an error due to insufficient permissions, - /// so `err` cannot be a `ChildAccessForbidden(_)` of either of them; + /// - `Active` and `Reserved(conflicted=false)` cannot cause an error + /// due to insufficient permissions, so `err` cannot be a `ChildAccessForbidden(_)` + /// of either of them; /// - `err` should not be `ProtectedDisabled(Disabled)`, because the protected /// tag should not have been `Disabled` in the first place (if this occurs it means /// we have unprotected tags that become protected) @@ -347,23 +354,28 @@ pub mod diagnostics { (Frozen, Frozen) => true, (Active, Frozen) => true, (Disabled, Disabled) => true, + (Reserved { conflicted: true, .. }, Reserved { conflicted: true, .. }) => + true, // A pointer being `Disabled` is a strictly stronger source of // errors than it being `Frozen`. If we try to access a `Disabled`, - // then where it became `Frozen` (or `Active`) is the least of our concerns for now. - (Active | Frozen, Disabled) => false, + // then where it became `Frozen` (or `Active` or `Reserved`) is the least + // of our concerns for now. + (Reserved { conflicted: true, .. } | Active | Frozen, Disabled) => false, + (Reserved { conflicted: true, .. }, Frozen) => false, // `Active` and `Reserved` have all permissions, so a // `ChildAccessForbidden(Reserved | Active)` can never exist. - (_, Active) | (_, Reserved { .. }) => + (_, Active) | (_, Reserved { conflicted: false, .. }) => unreachable!("this permission cannot cause an error"), - // No transition has `Reserved` as its `.to` unless it's a noop. - (Reserved { .. }, _) => unreachable!("self is a noop transition"), + // No transition has `Reserved(conflicted=false)` as its `.to` unless it's a noop. + (Reserved { conflicted: false, .. }, _) => + unreachable!("self is a noop transition"), // All transitions produced in normal executions (using `apply_access`) // change permissions in the order `Reserved -> Active -> Frozen -> Disabled`. // We assume that the error was triggered on the same location that // the transition `self` applies to, so permissions found must be increasing // in the order `self.from < self.to <= insufficient.inner` - (Disabled, Frozen) => + (Active | Frozen | Disabled, Reserved { .. }) | (Disabled, Frozen) => unreachable!("permissions between self and err must be increasing"), } } @@ -373,25 +385,34 @@ pub mod diagnostics { // This eliminates transitions like `Reserved -> Active` // when the error is a `Frozen -> Disabled`. match (self.to, before_disabled.inner) { - // We absolutely want to know where it was activated. + // We absolutely want to know where it was activated/frozen/marked + // conflicted. (Active, Active) => true, - // And knowing where it became Frozen is also important. (Frozen, Frozen) => true, + (Reserved { conflicted: true, .. }, Reserved { conflicted: true, .. }) => + true, // If the error is a transition `Frozen -> Disabled`, then we don't really // care whether before that was `Reserved -> Active -> Frozen` or - // `Reserved -> Frozen` or even `Frozen` directly. + // `Frozen` directly. // The error will only show either - // - created as Frozen, then Frozen -> Disabled is forbidden - // - created as Reserved, later became Frozen, then Frozen -> Disabled is forbidden - // In both cases the `Reserved -> Active` part is inexistant or irrelevant. + // - created as Reserved { conflicted: false }, + // then Reserved { .. } -> Disabled is forbidden + // - created as Reserved { conflicted: false }, + // then Active -> Disabled is forbidden + // A potential `Reserved { conflicted: false } + // -> Reserved { conflicted: true }` is inexistant or irrelevant, + // and so is the `Reserved { conflicted: false } -> Active` (Active, Frozen) => false, + (Reserved { conflicted: true, .. }, _) => false, (_, Disabled) => unreachable!( "permission that results in Disabled should not itself be Disabled in the first place" ), - // No transition has `Reserved` as its `.to` unless it's a noop. - (Reserved { .. }, _) => unreachable!("self is a noop transition"), + // No transition has `Reserved { conflicted: false }` as its `.to` + // unless it's a noop. + (Reserved { conflicted: false, .. }, _) => + unreachable!("self is a noop transition"), // Permissions only evolve in the order `Reserved -> Active -> Frozen -> Disabled`, // so permissions found must be increasing in the order @@ -417,6 +438,16 @@ pub mod diagnostics { } } +#[cfg(test)] +impl Permission { + pub fn is_reserved_with_conflicted(&self, expected_conflicted: bool) -> bool { + match self.inner { + Reserved { conflicted, .. } => conflicted == expected_conflicted, + _ => false, + } + } +} + #[cfg(test)] mod propagation_optimization_checks { pub use super::*; @@ -425,9 +456,10 @@ mod propagation_optimization_checks { impl Exhaustive for PermissionPriv { fn exhaustive() -> Box> { Box::new( - vec![Active, Frozen, Disabled] - .into_iter() - .chain(bool::exhaustive().map(|ty_is_freeze| Reserved { ty_is_freeze })), + vec![Active, Frozen, Disabled].into_iter().chain( + <[bool; 2]>::exhaustive() + .map(|[ty_is_freeze, conflicted]| Reserved { ty_is_freeze, conflicted }), + ), ) } } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs index eb466f89a8466..b63b0bdff1217 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs @@ -282,6 +282,113 @@ enum ContinueTraversal { SkipChildren, } +/// Stack of nodes left to explore in a tree traversal. +struct TreeVisitorStack { + /// Identifier of the original access. + initial: UniIndex, + /// Function to apply to each tag. + f_propagate: NodeApp, + /// Handler to add the required context to diagnostics. + err_builder: ErrHandler, + /// Mutable state of the visit: the tags left to handle. + /// Every tag pushed should eventually be handled, + /// and the precise order is relevant for diagnostics. + stack: Vec<(UniIndex, AccessRelatedness)>, +} + +impl TreeVisitorStack +where + NodeApp: Fn(NodeAppArgs<'_>) -> Result, + ErrHandler: Fn(ErrHandlerArgs<'_, InnErr>) -> OutErr, +{ + /// Apply the function to the current `tag`, and push its children + /// to the stack of future tags to visit. + fn exec_and_visit( + &mut self, + this: &mut TreeVisitor<'_>, + idx: UniIndex, + exclude: Option, + rel_pos: AccessRelatedness, + ) -> Result<(), OutErr> { + // 1. apply the propagation function + let node = this.nodes.get_mut(idx).unwrap(); + let recurse = + (self.f_propagate)(NodeAppArgs { node, perm: this.perms.entry(idx), rel_pos }) + .map_err(|error_kind| { + (self.err_builder)(ErrHandlerArgs { + error_kind, + conflicting_info: &this.nodes.get(idx).unwrap().debug_info, + accessed_info: &this.nodes.get(self.initial).unwrap().debug_info, + }) + })?; + let node = this.nodes.get(idx).unwrap(); + // 2. add the children to the stack for future traversal + if matches!(recurse, ContinueTraversal::Recurse) { + let general_child_rel = rel_pos.for_child(); + for &child in node.children.iter() { + // Some child might be excluded from here and handled separately, + // e.g. the initially accessed tag. + if Some(child) != exclude { + // We should still ensure that if we don't skip the initially accessed + // it will receive the proper `AccessRelatedness`. + let this_child_rel = if child == self.initial { + AccessRelatedness::This + } else { + general_child_rel + }; + self.stack.push((child, this_child_rel)); + } + } + } + Ok(()) + } + + fn new(initial: UniIndex, f_propagate: NodeApp, err_builder: ErrHandler) -> Self { + Self { initial, f_propagate, err_builder, stack: Vec::new() } + } + + /// Finish the exploration by applying `exec_and_visit` until + /// the stack is empty. + fn finish(&mut self, visitor: &mut TreeVisitor<'_>) -> Result<(), OutErr> { + while let Some((idx, rel_pos)) = self.stack.pop() { + self.exec_and_visit(visitor, idx, /* no children to exclude */ None, rel_pos)?; + } + Ok(()) + } + + /// Push all ancestors to the exploration stack in order of nearest ancestor + /// towards the top. + fn push_and_visit_strict_ancestors( + &mut self, + visitor: &mut TreeVisitor<'_>, + ) -> Result<(), OutErr> { + let mut path_ascend = Vec::new(); + // First climb to the root while recording the path + let mut curr = self.initial; + while let Some(ancestor) = visitor.nodes.get(curr).unwrap().parent { + path_ascend.push((ancestor, curr)); + curr = ancestor; + } + // Then descend: + // - execute f_propagate on each node + // - record children in visit + while let Some((ancestor, next_in_path)) = path_ascend.pop() { + // Explore ancestors in descending order. + // `next_in_path` is excluded from the recursion because it + // will be the `ancestor` of the next iteration. + // It also needs a different `AccessRelatedness` than the other + // children of `ancestor`. + self.exec_and_visit( + visitor, + ancestor, + Some(next_in_path), + AccessRelatedness::StrictChildAccess, + )?; + } + Ok(()) + } +} + impl<'tree> TreeVisitor<'tree> { // Applies `f_propagate` to every vertex of the tree top-down in the following order: first // all ancestors of `start`, then `start` itself, then children of `start`, then the rest. @@ -298,107 +405,40 @@ impl<'tree> TreeVisitor<'tree> { start: BorTag, f_propagate: impl Fn(NodeAppArgs<'_>) -> Result, err_builder: impl Fn(ErrHandlerArgs<'_, InnErr>) -> OutErr, - ) -> Result<(), OutErr> -where { - struct TreeVisitAux { - accessed_tag: UniIndex, - f_propagate: NodeApp, - err_builder: ErrHandler, - stack: Vec<(UniIndex, AccessRelatedness)>, - } - impl TreeVisitAux - where - NodeApp: Fn(NodeAppArgs<'_>) -> Result, - ErrHandler: Fn(ErrHandlerArgs<'_, InnErr>) -> OutErr, - { - fn pop(&mut self) -> Option<(UniIndex, AccessRelatedness)> { - self.stack.pop() - } - - /// Apply the function to the current `tag`, and push its children - /// to the stack of future tags to visit. - fn exec_and_visit( - &mut self, - this: &mut TreeVisitor<'_>, - tag: UniIndex, - exclude: Option, - rel_pos: AccessRelatedness, - ) -> Result<(), OutErr> { - // 1. apply the propagation function - let node = this.nodes.get_mut(tag).unwrap(); - let recurse = - (self.f_propagate)(NodeAppArgs { node, perm: this.perms.entry(tag), rel_pos }) - .map_err(|error_kind| { - (self.err_builder)(ErrHandlerArgs { - error_kind, - conflicting_info: &this.nodes.get(tag).unwrap().debug_info, - accessed_info: &this - .nodes - .get(self.accessed_tag) - .unwrap() - .debug_info, - }) - })?; - let node = this.nodes.get(tag).unwrap(); - // 2. add the children to the stack for future traversal - if matches!(recurse, ContinueTraversal::Recurse) { - let child_rel = rel_pos.for_child(); - for &child in node.children.iter() { - // some child might be excluded from here and handled separately - if Some(child) != exclude { - self.stack.push((child, child_rel)); - } - } - } - Ok(()) - } - } + ) -> Result<(), OutErr> { + let start_idx = self.tag_mapping.get(&start).unwrap(); + let mut stack = TreeVisitorStack::new(start_idx, f_propagate, err_builder); + stack.push_and_visit_strict_ancestors(&mut self)?; + // All (potentially zero) ancestors have been explored, + // it's time to explore the `start` tag. + stack.exec_and_visit( + &mut self, + start_idx, + /* no children to exclude */ None, + AccessRelatedness::This, + )?; + // Then finish with a normal DFS. + stack.finish(&mut self) + } + // Applies `f_propagate` to every non-child vertex of the tree (ancestors first). + // + // `f_propagate` should follow the following format: for a given `Node` it updates its + // `Permission` depending on the position relative to `start` (given by an + // `AccessRelatedness`). + // It outputs whether the tree traversal for this subree should continue or not. + fn traverse_nonchildren( + mut self, + start: BorTag, + f_propagate: impl Fn(NodeAppArgs<'_>) -> Result, + err_builder: impl Fn(ErrHandlerArgs<'_, InnErr>) -> OutErr, + ) -> Result<(), OutErr> { let start_idx = self.tag_mapping.get(&start).unwrap(); - let mut stack = - TreeVisitAux { accessed_tag: start_idx, f_propagate, err_builder, stack: Vec::new() }; - { - let mut path_ascend = Vec::new(); - // First climb to the root while recording the path - let mut curr = start_idx; - while let Some(ancestor) = self.nodes.get(curr).unwrap().parent { - path_ascend.push((ancestor, curr)); - curr = ancestor; - } - // Then descend: - // - execute f_propagate on each node - // - record children in visit - while let Some((ancestor, next_in_path)) = path_ascend.pop() { - // Explore ancestors in descending order. - // `next_in_path` is excluded from the recursion because it - // will be the `ancestor` of the next iteration. - // It also needs a different `AccessRelatedness` than the other - // children of `ancestor`. - stack.exec_and_visit( - &mut self, - ancestor, - Some(next_in_path), - AccessRelatedness::StrictChildAccess, - )?; - } - }; - // All (potentially zero) ancestors have been explored, call f_propagate on start - stack.exec_and_visit(&mut self, start_idx, None, AccessRelatedness::This)?; - // up to this point we have never popped from `stack`, hence if the - // path to the root is `root = p(n) <- p(n-1)... <- p(1) <- p(0) = start` - // then now `stack` contains - // `[ ... ]`, - // all of which are for now unexplored. - // This is the starting point of a standard DFS which will thus - // explore all non-ancestors of `start` in the following order: - // - all descendants of `start`; - // - then the unexplored descendants of `parent(start)`; - // ... - // - until finally the unexplored descendants of `root`. - while let Some((tag, rel_pos)) = stack.pop() { - stack.exec_and_visit(&mut self, tag, None, rel_pos)?; - } - Ok(()) + let mut stack = TreeVisitorStack::new(start_idx, f_propagate, err_builder); + stack.push_and_visit_strict_ancestors(&mut self)?; + // We *don't* visit the `start` tag, and we don't push its children. + // Only finish the DFS with the cousins. + stack.finish(&mut self) } } @@ -482,7 +522,7 @@ impl<'tcx> Tree { self.perform_access( AccessKind::Write, tag, - access_range, + Some(access_range), global, span, diagnostics::AccessCause::Dealloc, @@ -520,6 +560,11 @@ impl<'tcx> Tree { /// Map the per-node and per-location `LocationState::perform_access` /// to each location of `access_range`, on every tag of the allocation. /// + /// If `access_range` is `None`, this is interpreted as the special + /// access that is applied on protector release: + /// - the access will be applied only to initialized locations of the allocation, + /// - and it will not be visible to children. + /// /// `LocationState::perform_access` will take care of raising transition /// errors and updating the `initialized` status of each location, /// this traversal adds to that: @@ -530,56 +575,105 @@ impl<'tcx> Tree { &mut self, access_kind: AccessKind, tag: BorTag, - access_range: AllocRange, + access_range: Option, global: &GlobalState, span: Span, // diagnostics access_cause: diagnostics::AccessCause, // diagnostics ) -> InterpResult<'tcx> { - for (perms_range, perms) in self.rperms.iter_mut(access_range.start, access_range.size) { - TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, perms } - .traverse_parents_this_children_others( - tag, - |args: NodeAppArgs<'_>| -> Result { - let NodeAppArgs { node, mut perm, rel_pos } = args; + use std::ops::Range; + // Performs the per-node work: + // - insert the permission if it does not exist + // - perform the access + // - record the transition + // to which some optimizations are added: + // - skip the traversal of the children in some cases + // - do not record noop transitions + // + // `perms_range` is only for diagnostics (it is the range of + // the `RangeMap` on which we are currently working). + let node_app = |perms_range: Range, + args: NodeAppArgs<'_>| + -> Result { + let NodeAppArgs { node, mut perm, rel_pos } = args; + + let old_state = perm.or_insert(LocationState::new(node.default_initial_perm)); + + match old_state.skip_if_known_noop(access_kind, rel_pos) { + ContinueTraversal::SkipChildren => return Ok(ContinueTraversal::SkipChildren), + _ => {} + } - let old_state = - perm.or_insert_with(|| LocationState::new(node.default_initial_perm)); + let protected = global.borrow().protected_tags.contains_key(&node.tag); + let transition = old_state.perform_access(access_kind, rel_pos, protected)?; + + // Record the event as part of the history + if !transition.is_noop() { + node.debug_info.history.push(diagnostics::Event { + transition, + is_foreign: rel_pos.is_foreign(), + access_cause, + access_range, + transition_range: perms_range.clone(), + span, + }); + } + Ok(ContinueTraversal::Recurse) + }; - match old_state.skip_if_known_noop(access_kind, rel_pos) { - ContinueTraversal::SkipChildren => - return Ok(ContinueTraversal::SkipChildren), - _ => {} - } + // Error handler in case `node_app` goes wrong. + // Wraps the faulty transition in more context for diagnostics. + let err_handler = |perms_range: Range, + args: ErrHandlerArgs<'_, TransitionError>| + -> InterpError<'tcx> { + let ErrHandlerArgs { error_kind, conflicting_info, accessed_info } = args; + TbError { + conflicting_info, + access_cause, + error_offset: perms_range.start, + error_kind, + accessed_info, + } + .build() + }; - let protected = global.borrow().protected_tags.contains_key(&node.tag); - let transition = - old_state.perform_access(access_kind, rel_pos, protected)?; - - // Record the event as part of the history - if !transition.is_noop() { - node.debug_info.history.push(diagnostics::Event { - transition, - is_foreign: rel_pos.is_foreign(), - access_cause, - access_range, - transition_range: perms_range.clone(), - span, - }); - } - Ok(ContinueTraversal::Recurse) - }, - |args: ErrHandlerArgs<'_, TransitionError>| -> InterpError<'tcx> { - let ErrHandlerArgs { error_kind, conflicting_info, accessed_info } = args; - TbError { - conflicting_info, - access_cause, - error_offset: perms_range.start, - error_kind, - accessed_info, - } - .build() - }, - )?; + if let Some(access_range) = access_range { + // Default branch: this is a "normal" access through a known range. + // We iterate over affected locations and traverse the tree for each of them. + for (perms_range, perms) in self.rperms.iter_mut(access_range.start, access_range.size) + { + TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, perms } + .traverse_parents_this_children_others( + tag, + |args| node_app(perms_range.clone(), args), + |args| err_handler(perms_range.clone(), args), + )?; + } + } else { + // This is a special access through the entire allocation. + // It actually only affects `initialized` locations, so we need + // to filter on those before initiating the traversal. + // + // In addition this implicit access should not be visible to children, + // thus the use of `traverse_nonchildren`. + // See the test case `returned_mut_is_usable` from + // `tests/pass/tree_borrows/tree-borrows.rs` for an example of + // why this is important. + for (perms_range, perms) in self.rperms.iter_mut_all() { + let idx = self.tag_mapping.get(&tag).unwrap(); + // Only visit initialized permissions + if let Some(p) = perms.get(idx) && p.initialized { + TreeVisitor { + nodes: &mut self.nodes, + tag_mapping: &self.tag_mapping, + perms, + } + .traverse_nonchildren( + tag, + |args| node_app(perms_range.clone(), args), + |args| err_handler(perms_range.clone(), args), + )?; + } + } } Ok(()) } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs index 11c06d0b763f3..35f3b53afdb47 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs @@ -302,6 +302,9 @@ mod spurious_read { Ok(Self { state, prot: self.prot }) } + /// Remove the protector. + /// This does not perform the implicit read on function exit because + /// `LocStateProt` does not have enough context to apply its effect. fn end_protector(&self) -> Self { Self { prot: false, state: self.state } } @@ -351,7 +354,8 @@ mod spurious_read { } /// Perform a read on the given pointer if its state is `initialized`. - /// Must be called just after reborrowing a pointer. + /// Must be called just after reborrowing a pointer, and just after + /// removing a protector. fn read_if_initialized(self, ptr: PtrSelector) -> Result { let initialized = match ptr { PtrSelector::X => self.x.state.initialized, @@ -368,14 +372,16 @@ mod spurious_read { } } + /// Remove the protector of `x`, including the implicit read on function exit. fn end_protector_x(self) -> Result { let x = self.x.end_protector(); - Ok(Self { x, ..self }) + Self { x, ..self }.read_if_initialized(PtrSelector::X) } + /// Remove the protector of `y`, including the implicit read on function exit. fn end_protector_y(self) -> Result { let y = self.y.end_protector(); - Ok(Self { y, ..self }) + Self { y, ..self }.read_if_initialized(PtrSelector::Y) } fn retag_y(self, new_y: LocStateProt) -> Result { @@ -504,11 +510,9 @@ mod spurious_read { } #[test] - #[should_panic] - // This is why `Reserved -> Frozen` on foreign read for protected references - // prevents the insertion of spurious reads: the transition can cause UB in the target - // later down the line. - fn reserved_frozen_protected_distinguishable() { + // `Reserved(aliased=false)` and `Reserved(aliased=true)` are properly indistinguishable + // under the conditions where we want to insert a spurious read. + fn reserved_aliased_protected_indistinguishable() { let source = LocStateProtPair { xy_rel: RelPosXY::MutuallyForeign, x: LocStateProt { @@ -522,8 +526,8 @@ mod spurious_read { }; let acc = TestAccess { ptr: PtrSelector::X, kind: AccessKind::Read }; let target = source.clone().perform_test_access(&acc).unwrap(); - assert!(source.y.state.permission.is_reserved(None)); - assert!(target.y.state.permission.is_frozen()); + assert!(source.y.state.permission.is_reserved_with_conflicted(false)); + assert!(target.y.state.permission.is_reserved_with_conflicted(true)); assert!(!source.distinguishable::<(), ()>(&target)) } @@ -599,7 +603,6 @@ mod spurious_read { } #[test] - #[should_panic] /// For each of the patterns described above, execute it once /// as-is, and once with a spurious read inserted. Report any UB /// in the target but not in the source. diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs index 58af32385c507..d9cad9c8e0bd6 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs @@ -212,12 +212,9 @@ impl<'a, V> UniValMap { impl<'a, V> UniEntry<'a, V> { /// Insert in the map and get the value. - pub fn or_insert_with(&mut self, default: F) -> &mut V - where - F: FnOnce() -> V, - { + pub fn or_insert(&mut self, default: V) -> &mut V { if self.inner.is_none() { - *self.inner = Some(default()); + *self.inner = Some(default); } self.inner.as_mut().unwrap() } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index bd7ec88fc1c3b..930fa053d2091 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1387,8 +1387,34 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ) -> InterpResult<'tcx> { // We want this *before* the return value copy, because the return place itself is protected // until we do `end_call` here. - if let Some(borrow_tracker) = &ecx.machine.borrow_tracker { - borrow_tracker.borrow_mut().end_call(&frame.extra); + if let Some(global_borrow_tracker) = &ecx.machine.borrow_tracker { + // The body of this loop needs `global_borrow_tracker` immutably + // so we can't move this code inside the following `end_call`. + for (alloc_id, tag) in &frame + .extra + .borrow_tracker + .as_ref() + .expect("we should have borrow tracking data") + .protected_tags + { + // Just because the tag is protected doesn't guarantee that + // the allocation still exists (weak protectors allow deallocations) + // so we must check that the allocation exists. + // If it does exist, then we have the guarantee that the + // pointer is readable, and the implicit read access inserted + // will never cause UB on the pointer itself. + let (_, _, kind) = ecx.get_alloc_info(*alloc_id); + if matches!(kind, AllocKind::LiveData) { + let alloc_extra = ecx.get_alloc_extra(*alloc_id).unwrap(); + let alloc_borrow_tracker = &alloc_extra.borrow_tracker.as_ref().unwrap(); + alloc_borrow_tracker.release_protector( + &ecx.machine, + global_borrow_tracker, + *tag, + )?; + } + } + global_borrow_tracker.borrow_mut().end_call(&frame.extra); } Ok(()) } diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.tree.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.tree.stderr index 2a9b4d688a912..3271a04eae745 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.tree.stderr @@ -5,18 +5,18 @@ LL | *x = 1; | ^^^^^^ write access through is forbidden | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental - = help: the accessed tag has state Frozen which forbids this child write access + = help: the accessed tag has state Reserved (conflicted) which forbids this child write access help: the accessed tag was created here, in the initial state Reserved --> $DIR/aliasing_mut1.rs:LL:CC | LL | pub fn safe(x: &mut i32, y: &mut i32) { | ^ -help: the accessed tag later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4] +help: the accessed tag later transitioned to Reserved (conflicted) due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4] --> $DIR/aliasing_mut1.rs:LL:CC | LL | pub fn safe(x: &mut i32, y: &mut i32) { | ^ - = help: this transition corresponds to a loss of write permissions + = help: this transition corresponds to a temporary loss of write permissions until function exit = note: BACKTRACE (of the first span): = note: inside `safe` at $DIR/aliasing_mut1.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.tree.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.tree.stderr index d4858975ef103..f2694b51ca40a 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.tree.stderr @@ -5,18 +5,18 @@ LL | *y = 2; | ^^^^^^ write access through is forbidden | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental - = help: the accessed tag has state Frozen which forbids this child write access + = help: the accessed tag has state Reserved (conflicted) which forbids this child write access help: the accessed tag was created here, in the initial state Reserved --> $DIR/aliasing_mut2.rs:LL:CC | LL | pub fn safe(x: &i32, y: &mut i32) { | ^ -help: the accessed tag later transitioned to Frozen due to a foreign read access at offsets [0x0..0x4] +help: the accessed tag later transitioned to Reserved (conflicted) due to a foreign read access at offsets [0x0..0x4] --> $DIR/aliasing_mut2.rs:LL:CC | LL | let _v = *x; | ^^ - = help: this transition corresponds to a loss of write permissions + = help: this transition corresponds to a temporary loss of write permissions until function exit = note: BACKTRACE (of the first span): = note: inside `safe` at $DIR/aliasing_mut2.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.tree.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.tree.stderr index d1afca84a8b2e..595381c16ad97 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.tree.stderr @@ -5,18 +5,18 @@ LL | *x = 1; | ^^^^^^ write access through is forbidden | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental - = help: the accessed tag has state Frozen which forbids this child write access + = help: the accessed tag has state Reserved (conflicted) which forbids this child write access help: the accessed tag was created here, in the initial state Reserved --> $DIR/aliasing_mut3.rs:LL:CC | LL | pub fn safe(x: &mut i32, y: &i32) { | ^ -help: the accessed tag later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4] +help: the accessed tag later transitioned to Reserved (conflicted) due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4] --> $DIR/aliasing_mut3.rs:LL:CC | LL | pub fn safe(x: &mut i32, y: &i32) { | ^ - = help: this transition corresponds to a loss of write permissions + = help: this transition corresponds to a temporary loss of write permissions until function exit = note: BACKTRACE (of the first span): = note: inside `safe` at $DIR/aliasing_mut3.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.tree.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.tree.stderr index 19a05ec5dd3bf..456af0f1eac71 100644 --- a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.tree.stderr @@ -6,7 +6,7 @@ LL | unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) } | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental = help: the accessed tag is foreign to the protected tag (i.e., it is not a child) - = help: this deallocation (acting as a foreign write access) would cause the protected tag (currently Frozen) to become Disabled + = help: this deallocation (acting as a foreign write access) would cause the protected tag (currently Reserved (conflicted)) to become Disabled = help: protected tags must never be Disabled help: the accessed tag was created here --> $DIR/newtype_pair_retagging.rs:LL:CC @@ -18,12 +18,12 @@ help: the protected tag was created here, in the initial state Reserved | LL | fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) { | ^^ -help: the protected tag later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4] +help: the protected tag later transitioned to Reserved (conflicted) due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4] --> $DIR/newtype_pair_retagging.rs:LL:CC | LL | || drop(Box::from_raw(ptr)), | ^^^^^^^^^^^^^^^^^^ - = help: this transition corresponds to a loss of write permissions + = help: this transition corresponds to a temporary loss of write permissions until function exit = note: BACKTRACE (of the first span): = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC = note: inside `::deallocate` at RUSTLIB/alloc/src/alloc.rs:LL:CC diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.tree.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.tree.stderr index 6364c51122ac9..d21ec9eddc2f7 100644 --- a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.tree.stderr @@ -6,7 +6,7 @@ LL | unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) } | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental = help: the accessed tag is foreign to the protected tag (i.e., it is not a child) - = help: this deallocation (acting as a foreign write access) would cause the protected tag (currently Frozen) to become Disabled + = help: this deallocation (acting as a foreign write access) would cause the protected tag (currently Reserved (conflicted)) to become Disabled = help: protected tags must never be Disabled help: the accessed tag was created here --> $DIR/newtype_retagging.rs:LL:CC @@ -18,12 +18,12 @@ help: the protected tag was created here, in the initial state Reserved | LL | fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) { | ^^ -help: the protected tag later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4] +help: the protected tag later transitioned to Reserved (conflicted) due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4] --> $DIR/newtype_retagging.rs:LL:CC | LL | || drop(Box::from_raw(ptr)), | ^^^^^^^^^^^^^^^^^^ - = help: this transition corresponds to a loss of write permissions + = help: this transition corresponds to a temporary loss of write permissions until function exit = note: BACKTRACE (of the first span): = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC = note: inside `::deallocate` at RUSTLIB/alloc/src/alloc.rs:LL:CC diff --git a/src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.rs b/src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.rs deleted file mode 100644 index f192e76de1350..0000000000000 --- a/src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.rs +++ /dev/null @@ -1,29 +0,0 @@ -//@revisions: stack tree -//@compile-flags: -Zmiri-preemption-rate=0 -//@[tree]compile-flags: -Zmiri-tree-borrows -use std::thread; - -#[derive(Copy, Clone)] -struct SendPtr(*mut i32); -unsafe impl Send for SendPtr {} - -fn main() { - let mut mem = 0; - let ptr = SendPtr(&mut mem as *mut _); - - let t = thread::spawn(move || { - let ptr = ptr; - // We do a protected 2phase retag (but no write!) in this thread. - fn retag(_x: &mut i32) {} //~[tree]ERROR: Data race detected between (1) Read on thread `main` and (2) Write on thread `` - retag(unsafe { &mut *ptr.0 }); //~[stack]ERROR: Data race detected between (1) Read on thread `main` and (2) Write on thread `` - }); - - // We do a read in the main thread. - unsafe { ptr.0.read() }; - - // These two operations do not commute -- if the read happens after the retag, the retagged pointer - // gets frozen! So we want this to be considered UB so that we can still freely move the read around - // in this thread without worrying about reordering with retags in other threads. - - t.join().unwrap(); -} diff --git a/src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.tree.stderr b/src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.tree.stderr deleted file mode 100644 index 173acf4b96c03..0000000000000 --- a/src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.tree.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: Undefined Behavior: Data race detected between (1) Read on thread `main` and (2) Write on thread `` at ALLOC. (2) just happened here - --> $DIR/retag_data_race_protected_read.rs:LL:CC - | -LL | fn retag(_x: &mut i32) {} - | ^^ Data race detected between (1) Read on thread `main` and (2) Write on thread `` at ALLOC. (2) just happened here - | -help: and (1) occurred earlier here - --> $DIR/retag_data_race_protected_read.rs:LL:CC - | -LL | unsafe { ptr.0.read() }; - | ^^^^^^^^^^^^ - = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior - = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information - = note: BACKTRACE (of the first span): - = note: inside `main::{closure#0}::retag` at $DIR/retag_data_race_protected_read.rs:LL:CC -note: inside closure - --> $DIR/retag_data_race_protected_read.rs:LL:CC - | -LL | ... retag(unsafe { &mut *ptr.0 }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace - -error: aborting due to previous error - diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs new file mode 100644 index 0000000000000..670fe9858ed54 --- /dev/null +++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs @@ -0,0 +1,30 @@ +//@compile-flags: -Zmiri-preemption-rate=0 +use std::thread; + +#[derive(Copy, Clone)] +struct SendPtr(*mut i32); +unsafe impl Send for SendPtr {} + +fn main() { + let mut mem = 0; + let ptr = SendPtr(&mut mem as *mut _); + + let t = thread::spawn(move || { + let ptr = ptr; + // We do a protected mutable retag (but no write!) in this thread. + fn retag(_x: &mut i32) {} + retag(unsafe { &mut *ptr.0 }); //~ERROR: Data race detected between (1) Read on thread `main` and (2) Write on thread `` + }); + + // We do a read in the main thread. + unsafe { ptr.0.read() }; + + // These two operations do not commute! + // - In Stacked Borrows, if the read happens after the retag it will `Disable` the pointer. + // - In Tree Borrows, if the read happens after the retag, the retagged pointer gets frozen! + // Ideally we would want this to be considered UB so that we can still freely move the read around + // in this thread without worrying about reordering with retags in other threads, + // but in Tree Borrows we have found worse issues that occur if we make this a data race. + + t.join().unwrap(); +} diff --git a/src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.stack.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr similarity index 100% rename from src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.stack.stderr rename to src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr diff --git a/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr b/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr index 998ab956e1af5..fc92770ed165c 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr @@ -1,12 +1,12 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Re*| └─┬── -| Re*| ├─┬── -| Re*| │ └─┬── -| Re*| │ └──── Strongly protected -| Re*| └──── +0.. 1 +| Act | └─┬── +| RsM | └─┬── +| RsM | ├─┬── +| RsM | │ └─┬── +| RsM | │ └──── Strongly protected +| RsM | └──── ────────────────────────────────────────────────── error: Undefined Behavior: write access through (y, callee:y, caller:y) is forbidden --> $DIR/cell-protected-write.rs:LL:CC diff --git a/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.stderr b/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.stderr index f7e9fb9e3c3a4..4b4b8f24a68f5 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.stderr @@ -1,12 +1,12 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Res| └─┬── -| Res| ├─┬── -| Res| │ └─┬── -| Res| │ └──── Strongly protected -| Res| └──── +0.. 1 +| Act | └─┬── +| Rs | └─┬── +| Rs | ├─┬── +| Rs | │ └─┬── +| Rs | │ └──── Strongly protected +| Rs | └──── ────────────────────────────────────────────────── error: Undefined Behavior: write access through (y, callee:y, caller:y) is forbidden --> $DIR/int-protected-write.rs:LL:CC diff --git a/src/tools/miri/tests/fail/tree_borrows/spurious_read.rs b/src/tools/miri/tests/fail/tree_borrows/spurious_read.rs new file mode 100644 index 0000000000000..3f39dcb4b76ad --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/spurious_read.rs @@ -0,0 +1,117 @@ +// We ensure a deterministic execution. +// Note that we are *also* using barriers: the barriers enforce the +// specific interleaving of operations that we want, but only the preemption +// rate guarantees that the error message is also deterministic. +//@compile-flags: -Zmiri-preemption-rate=0 +//@compile-flags: -Zmiri-tree-borrows + +use std::sync::{Arc, Barrier}; +use std::thread; + +// A way to send raw pointers across threads. +// Note that when using this in closures will require explicit copying +// `let ptr = ptr;` to force the borrow checker to copy the `Send` wrapper +// instead of just copying the inner `!Send` field. +#[derive(Copy, Clone)] +struct SendPtr(*mut u8); +unsafe impl Send for SendPtr {} + +fn main() { + retagx_retagy_retx_writey_rety(); +} + +// We're going to enforce a specific interleaving of two +// threads, we use this macro in an effort to make it feasible +// to check in the output that the execution is properly synchronized. +// +// Provide `synchronized!(thread, msg)` where thread is +// a `(thread_id: usize, barrier: Arc)`, and `msg` the message +// to be displayed when the thread reaches this point in the execution. +macro_rules! synchronized { + ($thread:expr, $msg:expr) => {{ + let (thread_id, barrier) = &$thread; + eprintln!("Thread {} executing: {}", thread_id, $msg); + barrier.wait(); + }}; +} + +// Interleaving: +// retag x (protect) +// retag y (protect) +// spurious read x (target only, which we are *not* executing) +// ret x +// write y +// ret y +// +// This is an interleaving that will never *not* have UB in the target +// (`noalias` violation on `y`). +// For the spurious read to be allowed, we need to ensure there *is* UB +// in the source (i.e., without the spurious read). +// +// The interleaving differs from the one in `tests/pass/tree_borrows/spurious_read.rs` only +// in that it has the `write y` while `y` is still protected. +// When the write occurs after protection ends, both source and target are fine +// (checked by the `pass` test); when the write occurs during protection, both source +// and target are UB (checked by this test). +fn retagx_retagy_retx_writey_rety() { + let mut data = 0u8; + let ptr = SendPtr(std::ptr::addr_of_mut!(data)); + let barrier = Arc::new(Barrier::new(2)); + let bx = Arc::clone(&barrier); + let by = Arc::clone(&barrier); + + // This thread only needs to + // - retag `x` protected + // - do a read through `x` + // - remove `x`'s protector + // Most of the complexity here is synchronization. + let thread_x = thread::spawn(move || { + let b = (1, bx); + synchronized!(b, "start"); + let ptr = ptr; + synchronized!(b, "retag x (&mut, protect)"); + fn as_mut(x: &mut u8, b: (usize, Arc)) -> *mut u8 { + synchronized!(b, "retag y (&mut, protect)"); + synchronized!(b, "location where spurious read of x would happen in the target"); + // This is ensuring taht we have UB *without* the spurious read, + // so we don't read here. + synchronized!(b, "ret x"); + synchronized!(b, "write y"); + let x = x as *mut u8; + x + } + let _x = as_mut(unsafe { &mut *ptr.0 }, b.clone()); + synchronized!(b, "ret y"); + synchronized!(b, "end"); + }); + + // This thread's job is to + // - retag `y` protected + // - (wait for the other thread to return so that there is no foreign protector when we write) + // - attempt a write through `y`. + // - (UB should have occured by now, but the next step would be to + // remove `y`'s protector) + let thread_y = thread::spawn(move || { + let b = (2, by); + synchronized!(b, "start"); + let ptr = ptr; + synchronized!(b, "retag x (&mut, protect)"); + synchronized!(b, "retag y (&mut, protect)"); + fn as_mut(y: &mut u8, b: (usize, Arc)) -> *mut u8 { + synchronized!(b, "location where spurious read of x would happen in the target"); + synchronized!(b, "ret x"); + let y = y as *mut u8; + synchronized!(b, "write y"); + unsafe { + *y = 2; //~ERROR: /write access through .* is forbidden/ + } + synchronized!(b, "ret y"); + y + } + let _y = as_mut(unsafe { &mut *ptr.0 }, b.clone()); + synchronized!(b, "end"); + }); + + thread_x.join().unwrap(); + thread_y.join().unwrap(); +} diff --git a/src/tools/miri/tests/fail/tree_borrows/spurious_read.stderr b/src/tools/miri/tests/fail/tree_borrows/spurious_read.stderr new file mode 100644 index 0000000000000..99ffb84933901 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/spurious_read.stderr @@ -0,0 +1,44 @@ +Thread 1 executing: start +Thread 2 executing: start +Thread 2 executing: retag x (&mut, protect) +Thread 1 executing: retag x (&mut, protect) +Thread 1 executing: retag y (&mut, protect) +Thread 2 executing: retag y (&mut, protect) +Thread 2 executing: location where spurious read of x would happen in the target +Thread 1 executing: location where spurious read of x would happen in the target +Thread 1 executing: ret x +Thread 2 executing: ret x +Thread 2 executing: write y +Thread 1 executing: write y +Thread 1 executing: ret y +error: Undefined Behavior: write access through is forbidden + --> $DIR/spurious_read.rs:LL:CC + | +LL | *y = 2; + | ^^^^^^ write access through is forbidden + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: the accessed tag has state Reserved (conflicted) which forbids this child write access +help: the accessed tag was created here, in the initial state Reserved + --> $DIR/spurious_read.rs:LL:CC + | +LL | fn as_mut(y: &mut u8, b: (usize, Arc)) -> *mut u8 { + | ^ +help: the accessed tag later transitioned to Reserved (conflicted) due to a protector release (acting as a foreign read access) on every location previously accessed by this tag + --> $DIR/spurious_read.rs:LL:CC + | +LL | } + | ^ + = help: this transition corresponds to a temporary loss of write permissions until function exit + = note: BACKTRACE (of the first span): + = note: inside `retagx_retagy_retx_writey_rety::{closure#1}::as_mut` at $DIR/spurious_read.rs:LL:CC +note: inside closure + --> $DIR/spurious_read.rs:LL:CC + | +LL | let _y = as_mut(unsafe { &mut *ptr.0 }, b.clone()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr b/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr index f464e0b4f4948..57caa09c88836 100644 --- a/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr @@ -1,12 +1,12 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Re*| └──── +0.. 1 +| Act | └─┬── +| RsM | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └──── +0.. 1 +| Act | └─┬── +| Act | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/end-of-protector.stderr b/src/tools/miri/tests/pass/tree_borrows/end-of-protector.stderr index 265f6dfc9c834..69b8a17dc5e12 100644 --- a/src/tools/miri/tests/pass/tree_borrows/end-of-protector.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/end-of-protector.stderr @@ -1,36 +1,36 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Res| └─┬── -| Res| └──── +0.. 1 +| Act | └─┬── +| Rs | └─┬── +| Rs | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Res| └─┬── -| Res| └─┬── -| Res| └─┬── -| Res| └──── Strongly protected +0.. 1 +| Act | └─┬── +| Rs | └─┬── +| Rs | └─┬── +| Rs | └─┬── +| Rs | └──── Strongly protected ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Res| └─┬── -| Res| ├─┬── -| Res| │ └─┬── -| Res| │ └──── -| Res| └──── +0.. 1 +| Act | └─┬── +| Rs | └─┬── +| Rs | ├─┬── +| Rs | │ └─┬── +| Rs | │ └──── +| Rs | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └─┬── -| Dis| ├─┬── -| Dis| │ └─┬── -| Dis| │ └──── -| Act| └──── +0.. 1 +| Act | └─┬── +| Act | └─┬── +| Dis | ├─┬── +| Dis | │ └─┬── +| Dis | │ └──── +| Act | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/formatting.stderr b/src/tools/miri/tests/pass/tree_borrows/formatting.stderr index 673dae6210d88..235ab68fe0178 100644 --- a/src/tools/miri/tests/pass/tree_borrows/formatting.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/formatting.stderr @@ -1,31 +1,31 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1.. 2.. 10.. 11..100..101..1000..1001..1024 -| Act| Act| Act| Act| Act| Act| Act| Act| Act| └─┬── -| Res| Act| Res| Act| Res| Act| Res| Act| Res| └─┬── -|----| Act|----|?Dis|----|?Dis| ----| ?Dis| ----| ├──── -|----|----|----| Act|----|?Dis| ----| ?Dis| ----| ├──── -|----|----|----|----|----| Frz| ----| ?Dis| ----| ├──── -|----|----|----|----|----|----| ----| Act| ----| └──── +0.. 1.. 2.. 10.. 11.. 100.. 101..1000..1001..1024 +| Act | Act | Act | Act | Act | Act | Act | Act | Act | └─┬── +| Rs | Act | Rs | Act | Rs | Act | Rs | Act | Rs | └─┬── +|-----| Act |-----|?Dis |-----|?Dis |-----|?Dis |-----| ├──── +|-----|-----|-----| Act |-----|?Dis |-----|?Dis |-----| ├──── +|-----|-----|-----|-----|-----| Frz |-----|?Dis |-----| ├──── +|-----|-----|-----|-----|-----|-----|-----| Act |-----| └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Frz| └─┬── -| Frz| ├─┬── -| Frz| │ ├──── -| Frz| │ └──── -| Frz| ├─┬── -| Frz| │ └─┬── -| Frz| │ └─┬── -| Frz| │ └─┬── -| Frz| │ └──── -| Frz| └─┬── -| Frz| ├─┬── -| Frz| │ ├──── -| Frz| │ └──── -| Frz| └─┬── -| Frz| ├──── -| Frz| └──── +0.. 1 +| Act | └─┬── +| Frz | └─┬── +| Frz | ├─┬── +| Frz | │ ├──── +| Frz | │ └──── +| Frz | ├─┬── +| Frz | │ └─┬── +| Frz | │ └─┬── +| Frz | │ └─┬── +| Frz | │ └──── +| Frz | └─┬── +| Frz | ├─┬── +| Frz | │ ├──── +| Frz | │ └──── +| Frz | └─┬── +| Frz | ├──── +| Frz | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/read_retag_no_race.rs b/src/tools/miri/tests/pass/tree_borrows/read_retag_no_race.rs new file mode 100644 index 0000000000000..d9897a1033fbe --- /dev/null +++ b/src/tools/miri/tests/pass/tree_borrows/read_retag_no_race.rs @@ -0,0 +1,114 @@ +//@compile-flags: -Zmiri-tree-borrows +// This test relies on a specific interleaving that cannot be enforced +// with just barriers. We must remove preemption so that the execution and the +// error messages are deterministic. +//@compile-flags: -Zmiri-preemption-rate=0 +use std::ptr::addr_of_mut; +use std::sync::{Arc, Barrier}; +use std::thread; + +#[derive(Copy, Clone)] +struct SendPtr(*mut u8); + +unsafe impl Send for SendPtr {} + +// This test features the problematic pattern +// +// read x || retag y (&mut, protect) +// -- sync -- +// || write y +// +// In which +// - one interleaving (`1:read; 2:retag; 2:write`) does not have UB if retags +// count only as reads for the data race model, +// - the other interleaving (`2:retag; 1:read; 2:write`) has UB (`noalias` violation). +// +// The interleaving executed here is the one that does not have UB, +// i.e. +// 1:read x +// 2:retag y +// 2:write y +// +// Tree Borrows considers that the read of `x` cannot be in conflict +// with `y` because `y` did not even exist yet when `x` was accessed. +// +// As long as we are not emitting any writes for the data race model +// upon retags of mutable references, it should not have any issue with +// this code either. +// We do not want to emit a write for the data race model, because +// although there is race-like behavior going on in this pattern +// (where some but not all interleavings contain UB), making this an actual +// data race has the confusing consequence of one single access being treated +// as being of different `AccessKind`s by different parts of Miri +// (a retag would be always a read for the aliasing model, and sometimes a write +// for the data race model). + +// The other interleaving is a subsequence of `tests/fail/tree_borrows/spurious_read.rs` +// which asserts that +// 2:retag y +// 1:read x +// 2:write y +// is UB. + +type IdxBarrier = (usize, Arc); +// We're going to enforce a specific interleaving of two +// threads, we use this macro in an effort to make it feasible +// to check in the output that the execution is properly synchronized. +// +// Provide `synchronized!(thread, msg)` where thread is +// a `(thread_id: usize, barrier: Arc)`, and `msg` the message +// to be displayed when the thread reaches this point in the execution. +macro_rules! synchronized { + ($thread:expr, $msg:expr) => {{ + let (thread_id, barrier) = &$thread; + eprintln!("Thread {} executing: {}", thread_id, $msg); + barrier.wait(); + }}; +} + +fn thread_1(x: SendPtr, barrier: IdxBarrier) { + let x = unsafe { &mut *x.0 }; + synchronized!(barrier, "spawn"); + + synchronized!(barrier, "read x || retag y"); + // This is the interleaving without UB: by the time + // the other thread starts retagging, this thread + // has already finished all its work using `y`. + let _v = *x; + synchronized!(barrier, "write y"); + synchronized!(barrier, "exit"); +} + +fn thread_2(y: SendPtr, barrier: IdxBarrier) { + let y = unsafe { &mut *y.0 }; + synchronized!(barrier, "spawn"); + + fn write(y: &mut u8, v: u8, barrier: &IdxBarrier) { + synchronized!(barrier, "write y"); + *y = v; + } + synchronized!(barrier, "read x || retag y"); + // We don't use a barrier here so that *if* the retag counted as a write + // for the data race model, then it would be UB. + // We still want to make sure that the other thread goes first as per the + // interleaving that we are testing, so we use `yield_now + preemption-rate=0` + // which has the effect of forcing a specific interleaving while still + // not counting as "synchronization" from the point of view of the data + // race model. + thread::yield_now(); + write(&mut *y, 42, &barrier); + synchronized!(barrier, "exit"); +} + +fn main() { + let mut data = 0u8; + let p = SendPtr(addr_of_mut!(data)); + let barrier = Arc::new(Barrier::new(2)); + let b1 = (1, Arc::clone(&barrier)); + let b2 = (2, Arc::clone(&barrier)); + + let h1 = thread::spawn(move || thread_1(p, b1)); + let h2 = thread::spawn(move || thread_2(p, b2)); + h1.join().unwrap(); + h2.join().unwrap(); +} diff --git a/src/tools/miri/tests/pass/tree_borrows/read_retag_no_race.stderr b/src/tools/miri/tests/pass/tree_borrows/read_retag_no_race.stderr new file mode 100644 index 0000000000000..f090300851115 --- /dev/null +++ b/src/tools/miri/tests/pass/tree_borrows/read_retag_no_race.stderr @@ -0,0 +1,8 @@ +Thread 1 executing: spawn +Thread 2 executing: spawn +Thread 2 executing: read x || retag y +Thread 1 executing: read x || retag y +Thread 1 executing: write y +Thread 2 executing: write y +Thread 2 executing: exit +Thread 1 executing: exit diff --git a/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.stderr b/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.stderr index b23d78a71566e..f09aa52f1a10a 100644 --- a/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.stderr @@ -1,15 +1,15 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └─┬── -| Act| └──── +0.. 1 +| Act | └─┬── +| Act | └─┬── +| Act | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └─┬── -| Frz| ├──── -| Res| └──── +0.. 1 +| Act | └─┬── +| Act | └─┬── +| Frz | ├──── +| Rs | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/reserved.stderr b/src/tools/miri/tests/pass/tree_borrows/reserved.stderr index 691fe8b77444d..0d0d52c717fed 100644 --- a/src/tools/miri/tests/pass/tree_borrows/reserved.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/reserved.stderr @@ -1,58 +1,58 @@ [interior mut + protected] Foreign Read: Re* -> Frz ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Re*| └─┬── -| Re*| ├─┬── -| Re*| │ └─┬── -| Frz| │ └──── -| Re*| └──── +0.. 1 +| Act | └─┬── +| RsM | └─┬── +| RsM | ├─┬── +| RsM | │ └─┬── +| RsCM| │ └──── +| RsM | └──── ────────────────────────────────────────────────── [interior mut] Foreign Read: Re* -> Re* ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 8 -| Act| └─┬── -| Re*| └─┬── -| Re*| ├──── -| Re*| └──── +0.. 8 +| Act | └─┬── +| RsM | └─┬── +| RsM | ├──── +| RsM | └──── ────────────────────────────────────────────────── [interior mut] Foreign Write: Re* -> Re* ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 8 -| Act| └─┬── -| Act| └─┬── -| Re*| ├──── -| Act| └──── +0.. 8 +| Act | └─┬── +| Act | └─┬── +| RsM | ├──── +| Act | └──── ────────────────────────────────────────────────── [protected] Foreign Read: Res -> Frz ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Res| └─┬── -| Res| ├─┬── -| Res| │ └─┬── -| Frz| │ └──── -| Res| └──── +0.. 1 +| Act | └─┬── +| Rs | └─┬── +| Rs | ├─┬── +| Rs | │ └─┬── +| RsC | │ └──── +| Rs | └──── ────────────────────────────────────────────────── [] Foreign Read: Res -> Res ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Res| └─┬── -| Res| ├──── -| Res| └──── +0.. 1 +| Act | └─┬── +| Rs | └─┬── +| Rs | ├──── +| Rs | └──── ────────────────────────────────────────────────── [] Foreign Write: Res -> Dis ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └─┬── -| Dis| ├──── -| Act| └──── +0.. 1 +| Act | └─┬── +| Act | └─┬── +| Dis | ├──── +| Act | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/spurious_read.rs b/src/tools/miri/tests/pass/tree_borrows/spurious_read.rs new file mode 100644 index 0000000000000..71e93d2f84f57 --- /dev/null +++ b/src/tools/miri/tests/pass/tree_borrows/spurious_read.rs @@ -0,0 +1,115 @@ +// We ensure a deterministic execution. +// Note that we are *also* using barriers: the barriers enforce the +// specific interleaving of operations that we want, but only the preemption +// rate guarantees that the error message is also deterministic. +//@compile-flags: -Zmiri-preemption-rate=0 +//@compile-flags: -Zmiri-tree-borrows + +use std::sync::{Arc, Barrier}; +use std::thread; + +// A way to send raw pointers across threads. +// Note that when using this in closures will require explicit copying +// `let ptr = ptr;` to force the borrow checker to copy the `Send` wrapper +// instead of just copying the inner `!Send` field. +#[derive(Copy, Clone)] +struct SendPtr(*mut u8); +unsafe impl Send for SendPtr {} + +fn main() { + retagx_retagy_spuriousx_retx_rety_writey(); +} + +// We're going to enforce a specific interleaving of two +// threads, we use this macro in an effort to make it feasible +// to check in the output that the execution is properly synchronized. +// +// Provide `synchronized!(thread, msg)` where thread is +// a `(thread_id: usize, barrier: Arc)`, and `msg` the message +// to be displayed when the thread reaches this point in the execution. +macro_rules! synchronized { + ($thread:expr, $msg:expr) => {{ + let (thread_id, barrier) = &$thread; + eprintln!("Thread {} executing: {}", thread_id, $msg); + barrier.wait(); + }}; +} + +// Interleaving: +// retag x (protect) +// retag y (protect) +// spurious read x (target only, which we are executing) +// ret x +// ret y +// write y +// +// This is an interleaving that will never have UB in the source +// (`x` is never accessed for the entire time that `y` is protected). +// For the spurious read to be allowed, we need to check that there is +// no UB in the target (i.e., *with* the spurious read). +// +// The interleaving differs from the one in `tests/fail/tree_borrows/spurious_read.rs` only +// in that it has the `write y` while `y` is no longer protected. +// When the write occurs after protection ends, both source and target are fine +// (checked by this test); when the write occurs during protection, both source +// and target are UB (checked by the `fail` test). +fn retagx_retagy_spuriousx_retx_rety_writey() { + let mut data = 0u8; + let ptr = SendPtr(std::ptr::addr_of_mut!(data)); + let barrier = Arc::new(Barrier::new(2)); + let bx = Arc::clone(&barrier); + let by = Arc::clone(&barrier); + + // This thread only needs to + // - retag `x` protected + // - do a read through `x` + // - remove `x`'s protector + // Most of the complexity here is synchronization. + let thread_x = thread::spawn(move || { + let b = (1, bx); + synchronized!(b, "start"); + let ptr = ptr; + synchronized!(b, "retag x (&mut, protect)"); + fn as_mut(x: &mut u8, b: (usize, Arc)) -> *mut u8 { + synchronized!(b, "retag y (&mut, protect)"); + synchronized!(b, "spurious read x"); + let _v = *x; + synchronized!(b, "ret x"); + let x = x as *mut u8; + x + } + let _x = as_mut(unsafe { &mut *ptr.0 }, b.clone()); + synchronized!(b, "ret y"); + synchronized!(b, "write y"); + synchronized!(b, "end"); + }); + + // This thread's job is to + // - retag `y` protected + // - (wait a bit that the other thread performs its spurious read) + // - remove `y`'s protector + // - attempt a write through `y`. + let thread_y = thread::spawn(move || { + let b = (2, by); + synchronized!(b, "start"); + let ptr = ptr; + synchronized!(b, "retag x (&mut, protect)"); + synchronized!(b, "retag y (&mut, protect)"); + fn as_mut(y: &mut u8, b: (usize, Arc)) -> *mut u8 { + synchronized!(b, "spurious read x"); + synchronized!(b, "ret x"); + let y = y as *mut u8; + y + } + let y = as_mut(unsafe { &mut *ptr.0 }, b.clone()); + synchronized!(b, "ret y"); + synchronized!(b, "write y"); + unsafe { + *y = 2; + } + synchronized!(b, "end"); + }); + + thread_x.join().unwrap(); + thread_y.join().unwrap(); +} diff --git a/src/tools/miri/tests/pass/tree_borrows/spurious_read.stderr b/src/tools/miri/tests/pass/tree_borrows/spurious_read.stderr new file mode 100644 index 0000000000000..45191eaf9c42f --- /dev/null +++ b/src/tools/miri/tests/pass/tree_borrows/spurious_read.stderr @@ -0,0 +1,16 @@ +Thread 1 executing: start +Thread 2 executing: start +Thread 2 executing: retag x (&mut, protect) +Thread 1 executing: retag x (&mut, protect) +Thread 1 executing: retag y (&mut, protect) +Thread 2 executing: retag y (&mut, protect) +Thread 2 executing: spurious read x +Thread 1 executing: spurious read x +Thread 1 executing: ret x +Thread 2 executing: ret x +Thread 2 executing: ret y +Thread 1 executing: ret y +Thread 1 executing: write y +Thread 2 executing: write y +Thread 2 executing: end +Thread 1 executing: end diff --git a/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs b/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs index 531543441c253..89752bffe9f9d 100644 --- a/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs +++ b/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs @@ -12,6 +12,7 @@ fn main() { two_mut_protected_same_alloc(); direct_mut_to_const_raw(); local_addr_of_mut(); + returned_mut_is_usable(); // Stacked Borrows tests read_does_not_invalidate1(); @@ -93,6 +94,24 @@ fn two_mut_protected_same_alloc() { write_second(&mut data.0, &mut data.1); } +// This checks that a reborrowed mutable reference returned from a function +// is actually writeable. +// The fact that this is not obvious is due to the addition of +// implicit reads on function exit that might freeze the return value. +fn returned_mut_is_usable() { + fn reborrow(x: &mut u8) -> &mut u8 { + let y = &mut *x; + // Activate the reference so that it is vulnerable to foreign reads. + *y = *y; + y + // An implicit read through `x` is inserted here. + } + let mut data = 0; + let x = &mut data; + let y = reborrow(x); + *y = 1; +} + // ----- The tests below were taken from Stacked Borrows ---- // Make sure that reading from an `&mut` does, like reborrowing to `&`, diff --git a/src/tools/miri/tests/pass/tree_borrows/unique.default.stderr b/src/tools/miri/tests/pass/tree_borrows/unique.default.stderr index f870d3bdec00c..6e774e5014d41 100644 --- a/src/tools/miri/tests/pass/tree_borrows/unique.default.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/unique.default.stderr @@ -1,21 +1,21 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Res| └─┬── -| Res| └──── +0.. 1 +| Act | └─┬── +| Rs | └─┬── +| Rs | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └─┬── -| Act| └──── +0.. 1 +| Act | └─┬── +| Act | └─┬── +| Act | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └─┬── -| Act| └──── +0.. 1 +| Act | └─┬── +| Act | └─┬── +| Act | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/unique.uniq.stderr b/src/tools/miri/tests/pass/tree_borrows/unique.uniq.stderr index 9ab6b879aa762..26d9ad2ad3838 100644 --- a/src/tools/miri/tests/pass/tree_borrows/unique.uniq.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/unique.uniq.stderr @@ -1,24 +1,24 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Res| └─┬── -| Res| └─┬── -|----| └──── +0.. 1 +| Act | └─┬── +| Rs | └─┬── +| Rs | └─┬── +|-----| └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └─┬── -| Act| └─┬── -| Act| └──── +0.. 1 +| Act | └─┬── +| Act | └─┬── +| Act | └─┬── +| Act | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └─┬── -| Act| └─┬── -| Dis| └──── +0.. 1 +| Act | └─┬── +| Act | └─┬── +| Act | └─┬── +| Dis | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/vec_unique.default.stderr b/src/tools/miri/tests/pass/tree_borrows/vec_unique.default.stderr index a7712ae91fba8..f63aa1f683497 100644 --- a/src/tools/miri/tests/pass/tree_borrows/vec_unique.default.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/vec_unique.default.stderr @@ -1,6 +1,6 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 2 -| Act| └─┬── -| Res| └──── +0.. 2 +| Act | └─┬── +| Rs | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr b/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr index e9f1cb3b1ed93..7942e9884f401 100644 --- a/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr @@ -1,8 +1,8 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 2 -| Act| └─┬── -|----| └─┬── -|----| └─┬── -|----| └──── +0.. 2 +| Act | └─┬── +|-----| └─┬── +|-----| └─┬── +|-----| └──── ────────────────────────────────────────────────── From e1e880e9c6a8c756195720a51c0c0b5b1819d959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Fri, 6 Oct 2023 15:12:36 +0200 Subject: [PATCH 17/21] Do not use host floats in `simd_{ceil,floor,round,trunc}` --- src/tools/miri/src/shims/intrinsics/simd.rs | 57 ++++++++++----------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index 200f37efa27b1..70f90aac2c23f 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -32,28 +32,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { assert_eq!(dest_len, op_len); - #[derive(Copy, Clone)] - enum HostFloatOp { - Ceil, - Floor, - Round, - Trunc, - Sqrt, - } #[derive(Copy, Clone)] enum Op { MirOp(mir::UnOp), Abs, - HostOp(HostFloatOp), + Sqrt, + Round(rustc_apfloat::Round), } let which = match intrinsic_name { "neg" => Op::MirOp(mir::UnOp::Neg), "fabs" => Op::Abs, - "ceil" => Op::HostOp(HostFloatOp::Ceil), - "floor" => Op::HostOp(HostFloatOp::Floor), - "round" => Op::HostOp(HostFloatOp::Round), - "trunc" => Op::HostOp(HostFloatOp::Trunc), - "fsqrt" => Op::HostOp(HostFloatOp::Sqrt), + "fsqrt" => Op::Sqrt, + "ceil" => Op::Round(rustc_apfloat::Round::TowardPositive), + "floor" => Op::Round(rustc_apfloat::Round::TowardNegative), + "round" => Op::Round(rustc_apfloat::Round::NearestTiesToAway), + "trunc" => Op::Round(rustc_apfloat::Round::TowardZero), _ => unreachable!(), }; @@ -73,7 +66,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { FloatTy::F64 => Scalar::from_f64(op.to_f64()?.abs()), } } - Op::HostOp(host_op) => { + Op::Sqrt => { let ty::Float(float_ty) = op.layout.ty.kind() else { span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name) }; @@ -81,28 +74,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { match float_ty { FloatTy::F32 => { let f = f32::from_bits(op.to_scalar().to_u32()?); - let res = match host_op { - HostFloatOp::Ceil => f.ceil(), - HostFloatOp::Floor => f.floor(), - HostFloatOp::Round => f.round(), - HostFloatOp::Trunc => f.trunc(), - HostFloatOp::Sqrt => f.sqrt(), - }; + let res = f.sqrt(); Scalar::from_u32(res.to_bits()) } FloatTy::F64 => { let f = f64::from_bits(op.to_scalar().to_u64()?); - let res = match host_op { - HostFloatOp::Ceil => f.ceil(), - HostFloatOp::Floor => f.floor(), - HostFloatOp::Round => f.round(), - HostFloatOp::Trunc => f.trunc(), - HostFloatOp::Sqrt => f.sqrt(), - }; + let res = f.sqrt(); Scalar::from_u64(res.to_bits()) } } - + } + Op::Round(rounding) => { + let ty::Float(float_ty) = op.layout.ty.kind() else { + span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name) + }; + match float_ty { + FloatTy::F32 => { + let f = op.to_scalar().to_f32()?; + let res = f.round_to_integral(rounding).value; + Scalar::from_f32(res) + } + FloatTy::F64 => { + let f = op.to_scalar().to_f64()?; + let res = f.round_to_integral(rounding).value; + Scalar::from_f64(res) + } + } } }; this.write_scalar(val, &dest)?; From ea56007362cf04da6d776a89fa45f536c537c448 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 6 Oct 2023 18:15:12 +0200 Subject: [PATCH 18/21] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index b60de8344d948..dc2601e9e9f02 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -bb6c66be3793ac5c738eeac91ecdc4b99388d0b4 +1bc0463b183392ad4e0ae9c5f7a76630d487230d From d322243e38808ab0078a8ecad32d31c8f5d8060e Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Sat, 7 Oct 2023 05:01:29 +0000 Subject: [PATCH 19/21] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index dc2601e9e9f02..8f0a0a045abdb 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -1bc0463b183392ad4e0ae9c5f7a76630d487230d +4ea5190026dbc1302b644d938e68bc6843cb8b24 From 5aecfe467b94c1d1a5124b119a8864d6dce8596f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 7 Oct 2023 07:55:48 +0200 Subject: [PATCH 20/21] update lockfile --- Cargo.lock | 52 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db316e998c1d2..3ad9d61e4877c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -391,7 +391,7 @@ dependencies = [ name = "cargo-miri" version = "0.1.0" dependencies = [ - "cargo_metadata", + "cargo_metadata 0.18.0", "directories", "rustc-build-sysroot", "rustc_tools_util", @@ -423,6 +423,20 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cargo_metadata" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb9ac64500cc83ce4b9f8dafa78186aa008c8dea77a09b94cd307fd0cd5022a8" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "cargotest2" version = "0.1.0" @@ -551,7 +565,7 @@ name = "clippy_lints" version = "0.1.75" dependencies = [ "arrayvec", - "cargo_metadata", + "cargo_metadata 0.15.4", "clippy_utils", "declare_clippy_lint", "if_chain", @@ -1038,11 +1052,11 @@ dependencies = [ [[package]] name = "directories" -version = "4.0.1" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" dependencies = [ - "dirs-sys", + "dirs-sys 0.4.1", ] [[package]] @@ -1051,7 +1065,7 @@ version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" dependencies = [ - "dirs-sys", + "dirs-sys 0.3.7", ] [[package]] @@ -1075,6 +1089,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -2664,6 +2690,12 @@ dependencies = [ "zip", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "overload" version = "0.1.1" @@ -4686,7 +4718,7 @@ dependencies = [ "annotate-snippets", "anyhow", "bytecount", - "cargo_metadata", + "cargo_metadata 0.15.4", "clap", "diff", "dirs", @@ -5358,7 +5390,7 @@ name = "tidy" version = "0.1.0" dependencies = [ "cargo-platform", - "cargo_metadata", + "cargo_metadata 0.15.4", "ignore", "lazy_static", "miropt-test-tools", @@ -5663,7 +5695,7 @@ dependencies = [ "anyhow", "bstr", "cargo-platform", - "cargo_metadata", + "cargo_metadata 0.15.4", "color-eyre", "colored", "comma", @@ -5690,7 +5722,7 @@ dependencies = [ "anyhow", "bstr", "cargo-platform", - "cargo_metadata", + "cargo_metadata 0.15.4", "color-eyre", "colored", "comma", From a04b7a374458b640960798dffe83e614f7907562 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 7 Oct 2023 07:56:15 +0200 Subject: [PATCH 21/21] allow option-ext as a tool dependency (MPL licensed) --- src/tools/tidy/src/deps.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 7d3ef4197a73e..49210967c4454 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -47,6 +47,7 @@ const EXCEPTIONS: &[(&str, &str)] = &[ ("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot ("mdbook", "MPL-2.0"), // mdbook ("openssl", "Apache-2.0"), // opt-dist + ("option-ext", "MPL-2.0"), // cargo-miri (via `directories`) ("rustc_apfloat", "Apache-2.0 WITH LLVM-exception"), // rustc (license is the same as LLVM uses) ("ryu", "Apache-2.0 OR BSL-1.0"), // cargo/... (because of serde) ("self_cell", "Apache-2.0"), // rustc (fluent translations)