diff --git a/cargo-miri/src/phases.rs b/cargo-miri/src/phases.rs index e51bfa3798..37f66d0033 100644 --- a/cargo-miri/src/phases.rs +++ b/cargo-miri/src/phases.rs @@ -185,7 +185,7 @@ pub fn phase_cargo_miri(mut args: impl Iterator) { // explicitly do this even if RUSTC_STAGE is set, since for these builds we do *not* want the // bootstrap `rustc` thing in our way! Instead, we have MIRI_HOST_SYSROOT to use for host // builds. - cmd.env("RUSTC", &fs::canonicalize(find_miri()).unwrap()); + cmd.env("RUSTC", fs::canonicalize(find_miri()).unwrap()); cmd.env("MIRI_BE_RUSTC", "target"); // we better remember to *unset* this in the other phases! // Set rustdoc to us as well, so we can run doctests. diff --git a/ci.sh b/ci.sh index b35f7370d6..e01bfbc74d 100755 --- a/ci.sh +++ b/ci.sh @@ -108,7 +108,8 @@ case $HOST_TARGET in MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple atomic data_race env/var 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 + 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=tests/avr.json MIRI_NO_STD=1 run_tests_minimal no_std # JSON target file ;; diff --git a/rust-version b/rust-version index ee75e7a293..cf6d9c2808 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -4f4d0586ad20c66a16d547581ca379beafece93a +c54c8cbac882e149e04a9e1f2d146fd548ae30ae diff --git a/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/borrow_tracker/stacked_borrows/diagnostics.rs index 5f132bf11a..2cc8f03546 100644 --- a/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -88,11 +88,7 @@ impl fmt::Display for InvalidationCause { match self { InvalidationCause::Access(kind) => write!(f, "{kind}"), InvalidationCause::Retag(perm, kind) => - if *kind == RetagCause::FnEntry { - write!(f, "{perm:?} FnEntry retag") - } else { - write!(f, "{perm:?} retag") - }, + write!(f, "{perm:?} {retag}", retag = kind.summary()), } } } @@ -193,7 +189,7 @@ struct RetagOp { #[derive(Debug, Clone, Copy, PartialEq)] pub enum RetagCause { Normal, - FnReturn, + FnReturnPlace, FnEntry, TwoPhase, } @@ -495,8 +491,8 @@ impl RetagCause { fn summary(&self) -> String { match self { RetagCause::Normal => "retag", - RetagCause::FnEntry => "FnEntry retag", - RetagCause::FnReturn => "FnReturn retag", + RetagCause::FnEntry => "function-entry retag", + RetagCause::FnReturnPlace => "return-place retag", RetagCause::TwoPhase => "two-phase retag", } .to_string() diff --git a/src/borrow_tracker/stacked_borrows/mod.rs b/src/borrow_tracker/stacked_borrows/mod.rs index bcdf2e7517..ec555ba289 100644 --- a/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/borrow_tracker/stacked_borrows/mod.rs @@ -998,7 +998,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { access: Some(AccessKind::Write), protector: Some(ProtectorKind::StrongProtector), }; - let val = this.sb_retag_reference(&val, new_perm, RetagCause::FnReturn)?; + let val = this.sb_retag_reference(&val, new_perm, RetagCause::FnReturnPlace)?; // And use reborrowed pointer for return place. let return_place = this.ref_to_mplace(&val)?; this.frame_mut().return_place = return_place.into(); diff --git a/src/helpers.rs b/src/helpers.rs index c11c6104c2..527d31d1f0 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -943,7 +943,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { link_name: Symbol, ) -> InterpResult<'tcx, ()> { self.check_abi(abi, exp_abi)?; - if let Some((body, _)) = self.eval_context_mut().lookup_exported_symbol(link_name)? { + 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 + // 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) + if self.eval_context_ref().tcx.is_compiler_builtins(instance.def_id().krate) { + return Ok(()); + } + throw_machine_stop!(TerminationInfo::SymbolShimClashing { link_name, span: body.span.data(), diff --git a/src/range_map.rs b/src/range_map.rs index c8ff06a366..6219806182 100644 --- a/src/range_map.rs +++ b/src/range_map.rs @@ -219,7 +219,6 @@ mod tests { /// Query the map at every offset in the range and collect the results. fn to_vec(map: &RangeMap, offset: u64, len: u64) -> Vec { (offset..offset + len) - .into_iter() .map(|i| { map.iter(Size::from_bytes(i), Size::from_bytes(1)).next().map(|(_, &t)| t).unwrap() }) diff --git a/src/shims/env.rs b/src/shims/env.rs index e049eec57a..ce24b23ca3 100644 --- a/src/shims/env.rs +++ b/src/shims/env.rs @@ -166,7 +166,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // `buf_size` represents the size in characters. let buf_size = u64::from(this.read_scalar(size_op)?.to_u32()?); Scalar::from_u32(windows_check_buffer_size( - this.write_os_str_to_wide_str(&var, buf_ptr, buf_size)?, + this.write_os_str_to_wide_str( + &var, buf_ptr, buf_size, /*truncate*/ false, + )?, )) } None => { @@ -366,7 +368,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { match env::current_dir() { Ok(cwd) => return Ok(Scalar::from_u32(windows_check_buffer_size( - this.write_path_to_wide_str(&cwd, buf, size)?, + this.write_path_to_wide_str(&cwd, buf, size, /*truncate*/ false)?, ))), Err(e) => this.set_last_error_from_io_error(e.kind())?, } diff --git a/src/shims/os_str.rs b/src/shims/os_str.rs index 0375a228a2..f010d4251f 100644 --- a/src/shims/os_str.rs +++ b/src/shims/os_str.rs @@ -101,17 +101,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { self.eval_context_mut().write_c_str(bytes, ptr, size) } - /// Helper function to write an OsStr as a 0x0000-terminated u16-sequence, which is what - /// the Windows APIs usually handle. This function returns `Ok((false, length))` without trying - /// to write if `size` is not large enough to fit the contents of `os_string` plus a null - /// terminator. It returns `Ok((true, length))` if the writing process was successful. The - /// string length returned does include the null terminator. Length is measured in units of - /// `u16.` + /// Helper function to write an OsStr as a 0x0000-terminated u16-sequence, which is what the + /// Windows APIs usually handle. + /// + /// If `truncate == false` (the usual mode of operation), this function returns `Ok((false, + /// length))` without trying to write if `size` is not large enough to fit the contents of + /// `os_string` plus a null terminator. It returns `Ok((true, length))` if the writing process + /// was successful. The string length returned does include the null terminator. Length is + /// measured in units of `u16.` + /// + /// If `truncate == true`, then in case `size` is not large enough it *will* write the first + /// `size.saturating_sub(1)` many items, followed by a null terminator (if `size > 0`). fn write_os_str_to_wide_str( &mut self, os_str: &OsStr, ptr: Pointer>, size: u64, + truncate: bool, ) -> InterpResult<'tcx, (bool, u64)> { #[cfg(windows)] fn os_str_to_u16vec<'tcx>(os_str: &OsStr) -> InterpResult<'tcx, Vec> { @@ -129,7 +135,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } let u16_vec = os_str_to_u16vec(os_str)?; - self.eval_context_mut().write_wide_str(&u16_vec, ptr, size) + let (written, size_needed) = self.eval_context_mut().write_wide_str(&u16_vec, ptr, size)?; + if truncate && !written && size > 0 { + // Write the truncated part that fits. + let truncated_data = &u16_vec[..size.saturating_sub(1).try_into().unwrap()]; + let (written, written_len) = + self.eval_context_mut().write_wide_str(truncated_data, ptr, size)?; + assert!(written && written_len == size); + } + Ok((written, size_needed)) } /// Allocate enough memory to store the given `OsStr` as a null-terminated sequence of bytes. @@ -143,7 +157,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let arg_type = this.tcx.mk_array(this.tcx.types.u8, size); let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind)?; - assert!(self.write_os_str_to_c_str(os_str, arg_place.ptr, size).unwrap().0); + let (written, _) = self.write_os_str_to_c_str(os_str, arg_place.ptr, size).unwrap(); + assert!(written); Ok(arg_place.ptr) } @@ -158,7 +173,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let arg_type = this.tcx.mk_array(this.tcx.types.u16, size); let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind)?; - assert!(self.write_os_str_to_wide_str(os_str, arg_place.ptr, size).unwrap().0); + let (written, _) = + self.write_os_str_to_wide_str(os_str, arg_place.ptr, size, /*truncate*/ false).unwrap(); + assert!(written); Ok(arg_place.ptr) } @@ -212,11 +229,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { path: &Path, ptr: Pointer>, size: u64, + truncate: bool, ) -> InterpResult<'tcx, (bool, u64)> { let this = self.eval_context_mut(); let os_str = this.convert_path(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget); - this.write_os_str_to_wide_str(&os_str, ptr, size) + this.write_os_str_to_wide_str(&os_str, ptr, size, truncate) } /// Allocate enough memory to store a Path as a null-terminated sequence of bytes, @@ -232,6 +250,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.alloc_os_str_as_c_str(&os_str, memkind) } + /// Allocate enough memory to store a Path as a null-terminated sequence of `u16`s, + /// adjusting path separators if needed. + fn alloc_path_as_wide_str( + &mut self, + path: &Path, + memkind: MemoryKind, + ) -> InterpResult<'tcx, Pointer>> { + let this = self.eval_context_mut(); + let os_str = + this.convert_path(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget); + this.alloc_os_str_as_wide_str(&os_str, memkind) + } + #[allow(clippy::get_first)] fn convert_path<'a>( &self, diff --git a/src/shims/windows/foreign_items.rs b/src/shims/windows/foreign_items.rs index 1da8f7c0e3..f310d16e86 100644 --- a/src/shims/windows/foreign_items.rs +++ b/src/shims/windows/foreign_items.rs @@ -381,6 +381,46 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(Scalar::from_u32(1), dest)?; } + "GetModuleFileNameW" => { + let [handle, filename, size] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + this.check_no_isolation("`GetModuleFileNameW`")?; + + let handle = this.read_machine_usize(handle)?; + let filename = this.read_pointer(filename)?; + let size = this.read_scalar(size)?.to_u32()?; + + if handle != 0 { + throw_unsup_format!("`GetModuleFileNameW` only supports the NULL handle"); + } + + // Using the host current_exe is a bit off, but consistent with Linux + // (where stdlib reads /proc/self/exe). + // Unfortunately this Windows function has a crazy behavior so we can't just use + // `write_path_to_wide_str`... + let path = std::env::current_exe().unwrap(); + let (all_written, size_needed) = this.write_path_to_wide_str( + &path, + filename, + size.into(), + /*truncate*/ true, + )?; + + if all_written { + // If the function succeeds, the return value is the length of the string that + // is copied to the buffer, in characters, not including the terminating null + // character. + this.write_int(size_needed.checked_sub(1).unwrap(), dest)?; + } else { + // If the buffer is too small to hold the module name, the string is truncated + // to nSize characters including the terminating null character, the function + // returns nSize, and the function sets the last error to + // ERROR_INSUFFICIENT_BUFFER. + this.write_int(size, dest)?; + let insufficient_buffer = this.eval_windows("c", "ERROR_INSUFFICIENT_BUFFER"); + this.set_last_error(insufficient_buffer)?; + } + } // Threading "CreateThread" => { diff --git a/test_dependencies/Cargo.lock b/test_dependencies/Cargo.lock index bf7f0411be..a84ed85976 100644 --- a/test_dependencies/Cargo.lock +++ b/test_dependencies/Cargo.lock @@ -14,6 +14,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bumpalo" +version = "3.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" + [[package]] name = "bytes" version = "1.3.0" @@ -44,8 +50,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -57,6 +65,15 @@ dependencies = [ "libc", ] +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "libc" version = "0.2.139" @@ -123,6 +140,12 @@ dependencies = [ "libc", ] +[[package]] +name = "once_cell" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" + [[package]] name = "page_size" version = "0.5.0" @@ -269,9 +292,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46" +checksum = "38a54aca0c15d014013256222ba0ebed095673f89345dd79119d912eb561b7a8" dependencies = [ "autocfg", "bytes", @@ -316,6 +339,60 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + [[package]] name = "winapi" version = "0.3.9" diff --git a/test_dependencies/Cargo.toml b/test_dependencies/Cargo.toml index 1df35bbbe2..f5ab6acf00 100644 --- a/test_dependencies/Cargo.toml +++ b/test_dependencies/Cargo.toml @@ -13,11 +13,11 @@ libc = "0.2" num_cpus = "1.10.1" getrandom_1 = { package = "getrandom", version = "0.1" } -getrandom = { version = "0.2" } +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" -tokio = { version = "1.0", features = ["full"] } +tokio = { version = "1.23", features = ["full"] } [workspace] diff --git a/tests/fail/stacked_borrows/aliasing_mut3.stderr b/tests/fail/stacked_borrows/aliasing_mut3.stderr index 55aaed62f4..ae54d0248d 100644 --- a/tests/fail/stacked_borrows/aliasing_mut3.stderr +++ b/tests/fail/stacked_borrows/aliasing_mut3.stderr @@ -5,7 +5,7 @@ LL | pub fn safe(_x: &mut i32, _y: &i32) {} | ^^ | | | trying to retag from for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of FnEntry retag at ALLOC[0x0..0x4] + | this error occurs as part of function-entry retag at ALLOC[0x0..0x4] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information @@ -14,7 +14,7 @@ help: was created by a SharedReadOnly retag at offsets [0x0..0x4] | LL | safe_raw(xraw, xshr); | ^^^^ -help: was later invalidated at offsets [0x0..0x4] by a Unique FnEntry retag inside this call +help: was later invalidated at offsets [0x0..0x4] by a Unique function-entry retag inside this call --> $DIR/aliasing_mut3.rs:LL:CC | LL | safe_raw(xraw, xshr); diff --git a/tests/fail/stacked_borrows/fnentry_invalidation.stderr b/tests/fail/stacked_borrows/fnentry_invalidation.stderr index e3bffde1f0..236c8fb018 100644 --- a/tests/fail/stacked_borrows/fnentry_invalidation.stderr +++ b/tests/fail/stacked_borrows/fnentry_invalidation.stderr @@ -14,7 +14,7 @@ help: was created by a SharedReadWrite retag at offsets [0x0..0x4] | LL | let z = &mut x as *mut i32; | ^^^^^^ -help: was later invalidated at offsets [0x0..0x4] by a Unique FnEntry retag inside this call +help: was later invalidated at offsets [0x0..0x4] by a Unique function-entry retag inside this call --> $DIR/fnentry_invalidation.rs:LL:CC | LL | x.do_bad(); diff --git a/tests/fail/stacked_borrows/fnentry_invalidation2.stderr b/tests/fail/stacked_borrows/fnentry_invalidation2.stderr index b104de4b8d..45c2197050 100644 --- a/tests/fail/stacked_borrows/fnentry_invalidation2.stderr +++ b/tests/fail/stacked_borrows/fnentry_invalidation2.stderr @@ -14,7 +14,7 @@ help: was created by a SharedReadOnly retag at offsets [0x0..0xc] | LL | let ptr = t.sli.as_ptr(); | ^^^^^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0xc] by a Unique FnEntry retag inside this call +help: was later invalidated at offsets [0x0..0xc] by a Unique function-entry retag inside this call --> $DIR/fnentry_invalidation2.rs:LL:CC | LL | let _ = t.sli.as_mut_ptr(); diff --git a/tests/pass/concurrency/tls_lib_drop.rs b/tests/pass/concurrency/tls_lib_drop.rs index 04e89ec361..7ccafec603 100644 --- a/tests/pass/concurrency/tls_lib_drop.rs +++ b/tests/pass/concurrency/tls_lib_drop.rs @@ -186,8 +186,65 @@ fn join_orders_after_tls_destructors() { } } +fn dtors_in_dtors_in_dtors() { + use std::cell::UnsafeCell; + use std::sync::{Arc, Condvar, Mutex}; + + #[derive(Clone, Default)] + struct Signal(Arc<(Mutex, Condvar)>); + + impl Signal { + fn notify(&self) { + let (set, cvar) = &*self.0; + *set.lock().unwrap() = true; + cvar.notify_one(); + } + + fn wait(&self) { + let (set, cvar) = &*self.0; + let mut set = set.lock().unwrap(); + while !*set { + set = cvar.wait(set).unwrap(); + } + } + } + + struct NotifyOnDrop(Signal); + + impl Drop for NotifyOnDrop { + fn drop(&mut self) { + let NotifyOnDrop(ref f) = *self; + f.notify(); + } + } + + struct S1(Signal); + thread_local!(static K1: UnsafeCell> = UnsafeCell::new(None)); + thread_local!(static K2: UnsafeCell> = UnsafeCell::new(None)); + + impl Drop for S1 { + fn drop(&mut self) { + let S1(ref signal) = *self; + unsafe { + let _ = K2.try_with(|s| *s.get() = Some(NotifyOnDrop(signal.clone()))); + } + } + } + + let signal = Signal::default(); + let signal2 = signal.clone(); + let _t = thread::spawn(move || unsafe { + let mut signal = Some(signal2); + K1.with(|s| *s.get() = Some(S1(signal.take().unwrap()))); + }); + // Note that this test will deadlock if TLS destructors aren't run (this + // requires the destructor to be run to pass the test). + signal.wait(); +} + fn main() { check_destructors(); check_blocking(); join_orders_after_tls_destructors(); + dtors_in_dtors_in_dtors(); } diff --git a/tests/pass/shims/env/current_exe.rs b/tests/pass/shims/env/current_exe.rs index 3f1153d265..898a42b72d 100644 --- a/tests/pass/shims/env/current_exe.rs +++ b/tests/pass/shims/env/current_exe.rs @@ -1,4 +1,3 @@ -//@ignore-target-windows: current_exe not supported on Windows //@only-on-host: the Linux std implementation opens /proc/self/exe, which doesn't work cross-target //@compile-flags: -Zmiri-disable-isolation use std::env;