From 37a34c042d945dd8198647ecbdd8638d5775a051 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Wed, 9 Apr 2025 18:00:23 -0700 Subject: [PATCH 01/24] Implement DeleteFileW --- .../miri/src/shims/windows/foreign_items.rs | 5 ++++ src/tools/miri/src/shims/windows/fs.rs | 19 ++++++++++++++ .../miri/tests/pass-dep/shims/windows-fs.rs | 25 ++++++++++++++++--- src/tools/miri/tests/pass/shims/fs.rs | 2 +- 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index 8dcadbed130c0..c80858c63639a 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -317,6 +317,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let res = this.GetFileInformationByHandle(handle, info)?; this.write_scalar(res, dest)?; } + "DeleteFileW" => { + let [file_name] = this.check_shim(abi, sys_conv, link_name, args)?; + let res = this.DeleteFileW(file_name)?; + this.write_scalar(res, dest)?; + } // Allocation "HeapAlloc" => { diff --git a/src/tools/miri/src/shims/windows/fs.rs b/src/tools/miri/src/shims/windows/fs.rs index 32bab54896938..7561bf45219ba 100644 --- a/src/tools/miri/src/shims/windows/fs.rs +++ b/src/tools/miri/src/shims/windows/fs.rs @@ -371,6 +371,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(this.eval_windows("c", "TRUE")) } + + fn DeleteFileW( + &mut self, + file_name: &OpTy<'tcx>, // LPCWSTR + ) -> InterpResult<'tcx, Scalar> { + // ^ Returns BOOL (i32 on Windows) + let this = self.eval_context_mut(); + this.assert_target_os("windows", "DeleteFileW"); + this.check_no_isolation("`DeleteFileW`")?; + + let file_name = this.read_path_from_wide_str(this.read_pointer(file_name)?)?; + match std::fs::remove_file(file_name) { + Ok(_) => interp_ok(this.eval_windows("c", "TRUE")), + Err(e) => { + this.set_last_error(e)?; + interp_ok(this.eval_windows("c", "FALSE")) + } + } + } } /// Windows FILETIME is measured in 100-nanosecs since 1601 diff --git a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs index a015464dbde32..698ca4e0b4ba6 100644 --- a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs +++ b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs @@ -2,6 +2,7 @@ //@compile-flags: -Zmiri-disable-isolation #![allow(nonstandard_style)] +use std::io::ErrorKind; use std::os::windows::ffi::OsStrExt; use std::path::Path; use std::ptr; @@ -15,10 +16,10 @@ use windows_sys::Win32::Foundation::{ STATUS_IO_DEVICE_ERROR, }; use windows_sys::Win32::Storage::FileSystem::{ - BY_HANDLE_FILE_INFORMATION, CREATE_ALWAYS, CREATE_NEW, CreateFileW, FILE_ATTRIBUTE_DIRECTORY, - FILE_ATTRIBUTE_NORMAL, FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT, - FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, GetFileInformationByHandle, OPEN_ALWAYS, - OPEN_EXISTING, + BY_HANDLE_FILE_INFORMATION, CREATE_ALWAYS, CREATE_NEW, CreateFileW, DeleteFileW, + FILE_ATTRIBUTE_DIRECTORY, FILE_ATTRIBUTE_NORMAL, FILE_FLAG_BACKUP_SEMANTICS, + FILE_FLAG_OPEN_REPARSE_POINT, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, + GetFileInformationByHandle, OPEN_ALWAYS, OPEN_EXISTING, }; fn main() { @@ -28,6 +29,7 @@ fn main() { test_create_always_twice(); test_open_always_twice(); test_open_dir_reparse(); + test_delete_file(); test_ntstatus_to_dos(); } } @@ -194,6 +196,21 @@ unsafe fn test_open_dir_reparse() { }; } +unsafe fn test_delete_file() { + let temp = utils::tmp().join("test_delete_file.txt"); + let raw_path = to_wide_cstr(&temp); + let _ = std::fs::File::create(&temp).unwrap(); + + if DeleteFileW(raw_path.as_ptr()) == 0 { + panic!("Failed to delete file"); + } + + match std::fs::File::open(temp) { + Ok(_) => panic!("File not deleted"), + Err(e) => assert!(e.kind() == ErrorKind::NotFound, "File not deleted"), + } +} + unsafe fn test_ntstatus_to_dos() { // We won't test all combinations, just a couple common ones assert_eq!(RtlNtStatusToDosError(STATUS_IO_DEVICE_ERROR), ERROR_IO_DEVICE); diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs index 6ad23055f30eb..d0a7f245ee0ff 100644 --- a/src/tools/miri/tests/pass/shims/fs.rs +++ b/src/tools/miri/tests/pass/shims/fs.rs @@ -17,10 +17,10 @@ mod utils; fn main() { test_path_conversion(); + test_file_create_new(); // Windows file handling is very incomplete. if cfg!(not(windows)) { test_file(); - test_file_create_new(); test_seek(); test_file_clone(); test_metadata(); From 9f1e27b61e4610d11ba74bba33a6fb9207a6e5e0 Mon Sep 17 00:00:00 2001 From: Patrick-6 Date: Fri, 11 Apr 2025 13:32:38 +0200 Subject: [PATCH 02/24] Expose Pointer to/from AllocId conversion functions, make some arguments optional --- src/tools/miri/src/alloc_addresses/mod.rs | 111 ++++++++++++---------- 1 file changed, 62 insertions(+), 49 deletions(-) diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index c263e86c08266..335e8d76999cf 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -107,47 +107,6 @@ fn align_addr(addr: u64, align: u64) -> u64 { impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { - // Returns the exposed `AllocId` that corresponds to the specified addr, - // or `None` if the addr is out of bounds - fn alloc_id_from_addr(&self, addr: u64, size: i64) -> Option { - let this = self.eval_context_ref(); - let global_state = this.machine.alloc_addresses.borrow(); - assert!(global_state.provenance_mode != ProvenanceMode::Strict); - - // We always search the allocation to the right of this address. So if the size is structly - // negative, we have to search for `addr-1` instead. - let addr = if size >= 0 { addr } else { addr.saturating_sub(1) }; - let pos = global_state.int_to_ptr_map.binary_search_by_key(&addr, |(addr, _)| *addr); - - // Determine the in-bounds provenance for this pointer. - let alloc_id = match pos { - Ok(pos) => Some(global_state.int_to_ptr_map[pos].1), - Err(0) => None, - Err(pos) => { - // This is the largest of the addresses smaller than `int`, - // i.e. the greatest lower bound (glb) - let (glb, alloc_id) = global_state.int_to_ptr_map[pos - 1]; - // This never overflows because `addr >= glb` - let offset = addr - glb; - // We require this to be strict in-bounds of the allocation. This arm is only - // entered for addresses that are not the base address, so even zero-sized - // allocations will get recognized at their base address -- but all other - // allocations will *not* be recognized at their "end" address. - let size = this.get_alloc_info(alloc_id).size; - if offset < size.bytes() { Some(alloc_id) } else { None } - } - }?; - - // We only use this provenance if it has been exposed. - if global_state.exposed.contains(&alloc_id) { - // This must still be live, since we remove allocations from `int_to_ptr_map` when they get freed. - debug_assert!(this.is_alloc_live(alloc_id)); - Some(alloc_id) - } else { - None - } - } - fn addr_from_alloc_id_uncached( &self, global_state: &mut GlobalStateInner, @@ -242,11 +201,65 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(base_addr) } } +} +impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} +pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + // Returns the `AllocId` that corresponds to the specified addr, + // or `None` if the addr is out of bounds. + // Setting `only_exposed_allocations` selects whether only exposed allocations are considered. + fn alloc_id_from_addr( + &self, + addr: u64, + size: i64, + only_exposed_allocations: bool, + ) -> Option { + let this = self.eval_context_ref(); + let global_state = this.machine.alloc_addresses.borrow(); + assert!(global_state.provenance_mode != ProvenanceMode::Strict); + + // We always search the allocation to the right of this address. So if the size is strictly + // negative, we have to search for `addr-1` instead. + let addr = if size >= 0 { addr } else { addr.saturating_sub(1) }; + let pos = global_state.int_to_ptr_map.binary_search_by_key(&addr, |(addr, _)| *addr); + + // Determine the in-bounds provenance for this pointer. + let alloc_id = match pos { + Ok(pos) => Some(global_state.int_to_ptr_map[pos].1), + Err(0) => None, + Err(pos) => { + // This is the largest of the addresses smaller than `int`, + // i.e. the greatest lower bound (glb) + let (glb, alloc_id) = global_state.int_to_ptr_map[pos - 1]; + // This never overflows because `addr >= glb` + let offset = addr - glb; + // We require this to be strict in-bounds of the allocation. This arm is only + // entered for addresses that are not the base address, so even zero-sized + // allocations will get recognized at their base address -- but all other + // allocations will *not* be recognized at their "end" address. + let size = this.get_alloc_info(alloc_id).size; + if offset < size.bytes() { Some(alloc_id) } else { None } + } + }?; + + // We only use this provenance if it has been exposed, or if the caller requested also non-exposed allocations + if !only_exposed_allocations || global_state.exposed.contains(&alloc_id) { + // This must still be live, since we remove allocations from `int_to_ptr_map` when they get freed. + debug_assert!(this.is_alloc_live(alloc_id)); + Some(alloc_id) + } else { + None + } + } + + /// Returns the base address of an allocation, or an error if no base address could be found + /// + /// # Panics + /// If `memory_kind = None` and the `alloc_id` is not cached, meaning that the first call to this function per `alloc_id` must get the `memory_kind`. fn addr_from_alloc_id( &self, alloc_id: AllocId, - memory_kind: MemoryKind, + memory_kind: Option, ) -> InterpResult<'tcx, u64> { let this = self.eval_context_ref(); let mut global_state = this.machine.alloc_addresses.borrow_mut(); @@ -256,8 +269,10 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { Some(&addr) => interp_ok(addr), None => { // First time we're looking for the absolute address of this allocation. + let memory_kind = + memory_kind.expect("memory_kind is required since alloc_id is not cached"); let base_addr = - self.addr_from_alloc_id_uncached(global_state, alloc_id, memory_kind)?; + this.addr_from_alloc_id_uncached(global_state, alloc_id, memory_kind)?; trace!("Assigning base address {:#x} to allocation {:?}", base_addr, alloc_id); // Store address in cache. @@ -283,10 +298,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } } } -} -impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} -pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn expose_provenance(&self, provenance: Provenance) -> InterpResult<'tcx> { let this = self.eval_context_ref(); let mut global_state = this.machine.alloc_addresses.borrow_mut(); @@ -365,7 +377,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let alloc_id = prov.alloc_id(); // Get a pointer to the beginning of this allocation. - let base_addr = this.addr_from_alloc_id(alloc_id, kind)?; + let base_addr = this.addr_from_alloc_id(alloc_id, Some(kind))?; let base_ptr = interpret::Pointer::new( Provenance::Concrete { alloc_id, tag }, Size::from_bytes(base_addr), @@ -388,7 +400,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`. // This additional call ensures that some `MiriAllocBytes` are always prepared, just in case // this function gets called before the first time `addr_from_alloc_id` gets called. - this.addr_from_alloc_id(id, MiriMemoryKind::Global.into())?; + this.addr_from_alloc_id(id, Some(MiriMemoryKind::Global.into()))?; // The memory we need here will have already been allocated during an earlier call to // `addr_from_alloc_id` for this allocation. So don't create a new `MiriAllocBytes` here, instead // fetch the previously prepared bytes from `prepared_alloc_bytes`. @@ -423,7 +435,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { alloc_id } else { // A wildcard pointer. - this.alloc_id_from_addr(addr.bytes(), size)? + let only_exposed_allocations = true; + this.alloc_id_from_addr(addr.bytes(), size, only_exposed_allocations)? }; // This cannot fail: since we already have a pointer with that provenance, adjust_alloc_root_pointer From 6db8e867d26814911994457874be066ed9c7639a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 16 Apr 2025 14:34:09 +0200 Subject: [PATCH 03/24] use std-declared intrinsics rather than copying the declaration --- src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs | 9 ++------- src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs | 9 ++------- .../miri/tests/fail/intrinsics/float_to_int_32_inf1.rs | 6 ++---- .../tests/fail/intrinsics/float_to_int_32_infneg1.rs | 6 ++---- .../miri/tests/fail/intrinsics/float_to_int_32_nan.rs | 6 ++---- .../miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs | 6 ++---- .../miri/tests/fail/intrinsics/float_to_int_32_neg.rs | 6 ++---- .../tests/fail/intrinsics/float_to_int_32_too_big1.rs | 6 ++---- .../tests/fail/intrinsics/float_to_int_32_too_big2.rs | 6 ++---- .../tests/fail/intrinsics/float_to_int_32_too_small1.rs | 6 ++---- .../miri/tests/fail/intrinsics/float_to_int_64_inf1.rs | 6 ++---- .../tests/fail/intrinsics/float_to_int_64_infneg1.rs | 6 ++---- .../tests/fail/intrinsics/float_to_int_64_infneg2.rs | 6 ++---- .../miri/tests/fail/intrinsics/float_to_int_64_nan.rs | 6 ++---- .../miri/tests/fail/intrinsics/float_to_int_64_neg.rs | 6 ++---- .../tests/fail/intrinsics/float_to_int_64_too_big1.rs | 6 ++---- .../tests/fail/intrinsics/float_to_int_64_too_big2.rs | 6 ++---- .../tests/fail/intrinsics/float_to_int_64_too_big3.rs | 6 ++---- .../tests/fail/intrinsics/float_to_int_64_too_big4.rs | 6 ++---- .../tests/fail/intrinsics/float_to_int_64_too_big5.rs | 6 ++---- .../tests/fail/intrinsics/float_to_int_64_too_big6.rs | 6 ++---- .../tests/fail/intrinsics/float_to_int_64_too_big7.rs | 6 ++---- .../tests/fail/intrinsics/float_to_int_64_too_small1.rs | 6 ++---- .../tests/fail/intrinsics/float_to_int_64_too_small2.rs | 6 ++---- .../tests/fail/intrinsics/float_to_int_64_too_small3.rs | 6 ++---- 25 files changed, 50 insertions(+), 106 deletions(-) diff --git a/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs b/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs index f73c1b6acb70f..3da54b9188262 100644 --- a/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs +++ b/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs @@ -1,13 +1,8 @@ -#![feature(intrinsics)] - -mod rusti { - #[rustc_intrinsic] - pub unsafe fn ctlz_nonzero(x: T) -> u32; -} +#![feature(core_intrinsics)] pub fn main() { unsafe { - use crate::rusti::*; + use std::intrinsics::*; ctlz_nonzero(0u8); //~ ERROR: `ctlz_nonzero` called on 0 } diff --git a/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs b/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs index a41cb8b15536f..2b68f6713d806 100644 --- a/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs +++ b/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs @@ -1,13 +1,8 @@ -#![feature(intrinsics)] - -mod rusti { - #[rustc_intrinsic] - pub unsafe fn cttz_nonzero(x: T) -> u32; -} +#![feature(core_intrinsics)] pub fn main() { unsafe { - use crate::rusti::*; + use std::intrinsics::*; cttz_nonzero(0u8); //~ ERROR: `cttz_nonzero` called on 0 } diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs index 7ee0117ffb33f..831a65966ce20 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs index 22bf881cef0ac..a7032e97430e7 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs index 571121f4019fa..e8c987619568d 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs index 12600ef612558..c8b29cbcfe99f 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs index f848a137c2797..0996d0244e882 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs index 43ef4a95738f8..f28227134d868 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs index 83432c2b77c0b..9e400b4ad4065 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs index 609443e6d4efd..9aca349b918c5 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs index fb3eb11c0bb54..54361f6c32c4a 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs index b46c4777ba71f..75f5229636730 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs index 8a3b9dbdc7105..20d8fa1ae801f 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs index e0c826cb0463e..611a0ade0a56f 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs index c7c5bf402264f..8ff8c3bee00be 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs index fb3d7bda4e478..1f662e6c32a46 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs index 2cf27b33553cc..fad172801eaa7 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs index 22dca505e64b6..7eb3559527aa0 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs index b59c8fa8e0c2a..351fc6c6f1cba 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs index 4ad0cd343a406..a6f73c7971073 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs index fd47dfc03d7a6..b01ff3aafc039 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs index 680ebda1c96bf..a573e4e852c84 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs index e4cb36c5d2ebe..4fb38c9bc2e79 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs index fe4bac92bd3e3..c4c0d3c17f03b 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs index 219efd8031623..de7d2215fd624 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs @@ -1,8 +1,6 @@ -#![feature(intrinsics)] - +#![feature(core_intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -#[rustc_intrinsic] -unsafe fn float_to_int_unchecked(value: Float) -> Int; +use std::intrinsics::float_to_int_unchecked; fn main() { unsafe { From f3ae022ed667bff30e0a64cdf7ca843bf1756f69 Mon Sep 17 00:00:00 2001 From: geetanshjuneja Date: Thu, 10 Apr 2025 13:32:04 +0530 Subject: [PATCH 04/24] replaced check_shim with check_shim_abi for env, file, sockets and time related shims Making type consistent in shims pread return type fix make clock_gettime shim type consistent --- src/tools/miri/src/helpers.rs | 2 +- src/tools/miri/src/shims/time.rs | 29 +- .../miri/src/shims/unix/foreign_items.rs | 433 +++++++++++++++--- src/tools/miri/src/shims/unix/fs.rs | 17 +- .../shims/vararg_caller_signature_mismatch.rs | 2 +- .../vararg_caller_signature_mismatch.stderr | 4 +- 6 files changed, 405 insertions(+), 82 deletions(-) diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index b4098ca0750c0..0932f2a3910e8 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -1017,7 +1017,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } /// Check that the given `caller_fn_abi` matches the expected ABI described by - /// `callee_abi`, `callee_input_tys`, `callee_output_ty`, and the return the list of + /// `callee_abi`, `callee_input_tys`, `callee_output_ty`, and then returns the list of /// arguments. fn check_shim_abi<'a, const N: usize>( &mut self, diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index fb80a36af9fc2..c98d6e2b408a2 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -21,7 +21,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &mut self, clk_id_op: &OpTy<'tcx>, tp_op: &OpTy<'tcx>, - ) -> InterpResult<'tcx, Scalar> { + dest: &MPlaceTy<'tcx>, + ) -> InterpResult<'tcx> { // This clock support is deliberately minimal because a lot of clock types have fiddly // properties (is it possible for Miri to be suspended independently of the host?). If you // have a use for another clock type, please open an issue. @@ -29,8 +30,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); this.assert_target_os_is_unix("clock_gettime"); + let clockid_t_size = this.libc_ty_layout("clockid_t").size; - let clk_id = this.read_scalar(clk_id_op)?.to_i32()?; + let clk_id = this.read_scalar(clk_id_op)?.to_int(clockid_t_size)?; let tp = this.deref_pointer_as(tp_op, this.libc_ty_layout("timespec"))?; let absolute_clocks; @@ -43,34 +45,34 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Linux further distinguishes regular and "coarse" clocks, but the "coarse" version // is just specified to be "faster and less precise", so we implement both the same way. absolute_clocks = vec![ - this.eval_libc_i32("CLOCK_REALTIME"), - this.eval_libc_i32("CLOCK_REALTIME_COARSE"), + this.eval_libc("CLOCK_REALTIME").to_int(clockid_t_size)?, + this.eval_libc("CLOCK_REALTIME_COARSE").to_int(clockid_t_size)?, ]; // The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are // never allowed to go backwards. We don't need to do any additional monotonicity // enforcement because std::time::Instant already guarantees that it is monotonic. relative_clocks = vec![ - this.eval_libc_i32("CLOCK_MONOTONIC"), - this.eval_libc_i32("CLOCK_MONOTONIC_COARSE"), + this.eval_libc("CLOCK_MONOTONIC").to_int(clockid_t_size)?, + this.eval_libc("CLOCK_MONOTONIC_COARSE").to_int(clockid_t_size)?, ]; } "macos" => { - absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")]; - relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")]; + absolute_clocks = vec![this.eval_libc("CLOCK_REALTIME").to_int(clockid_t_size)?]; + relative_clocks = vec![this.eval_libc("CLOCK_MONOTONIC").to_int(clockid_t_size)?]; // `CLOCK_UPTIME_RAW` supposed to not increment while the system is asleep... but // that's not really something a program running inside Miri can tell, anyway. // We need to support it because std uses it. - relative_clocks.push(this.eval_libc_i32("CLOCK_UPTIME_RAW")); + relative_clocks.push(this.eval_libc("CLOCK_UPTIME_RAW").to_int(clockid_t_size)?); } "solaris" | "illumos" => { // The REALTIME clock returns the actual time since the Unix epoch. - absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")]; + absolute_clocks = vec![this.eval_libc("CLOCK_REALTIME").to_int(clockid_t_size)?]; // MONOTONIC, in the other hand, is the high resolution, non-adjustable // clock from an arbitrary time in the past. // Note that the man page mentions HIGHRES but it is just // an alias of MONOTONIC and the libc crate does not expose it anyway. // https://docs.oracle.com/cd/E23824_01/html/821-1465/clock-gettime-3c.html - relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")]; + relative_clocks = vec![this.eval_libc("CLOCK_MONOTONIC").to_int(clockid_t_size)?]; } target => throw_unsup_format!("`clock_gettime` is not supported on target OS {target}"), } @@ -81,15 +83,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } else if relative_clocks.contains(&clk_id) { this.machine.monotonic_clock.now().duration_since(this.machine.monotonic_clock.epoch()) } else { - return this.set_last_error_and_return_i32(LibcError("EINVAL")); + return this.set_last_error_and_return(LibcError("EINVAL"), dest); }; let tv_sec = duration.as_secs(); let tv_nsec = duration.subsec_nanos(); this.write_int_fields(&[tv_sec.into(), tv_nsec.into()], &tp)?; + this.write_int(0, dest)?; - interp_ok(Scalar::from_i32(0)) + interp_ok(()) } fn gettimeofday( diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 5e6259c35744b..026aa1f950399 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -112,51 +112,122 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // Environment related shims "getenv" => { - let [name] = this.check_shim(abi, Conv::C, link_name, args)?; + let [name] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty], + this.machine.layouts.mut_raw_ptr.ty, + args, + )?; let result = this.getenv(name)?; this.write_pointer(result, dest)?; } "unsetenv" => { - let [name] = this.check_shim(abi, Conv::C, link_name, args)?; + let [name] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.unsetenv(name)?; this.write_scalar(result, dest)?; } "setenv" => { - let [name, value, overwrite] = this.check_shim(abi, Conv::C, link_name, args)?; + let [name, value, overwrite] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [ + this.machine.layouts.const_raw_ptr.ty, + this.machine.layouts.const_raw_ptr.ty, + this.tcx.types.i32, + ], + this.tcx.types.i32, + args, + )?; this.read_scalar(overwrite)?.to_i32()?; let result = this.setenv(name, value)?; this.write_scalar(result, dest)?; } "getcwd" => { - let [buf, size] = this.check_shim(abi, Conv::C, link_name, args)?; + let [buf, size] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.mut_raw_ptr.ty, this.tcx.types.usize], + this.machine.layouts.mut_raw_ptr.ty, + args, + )?; let result = this.getcwd(buf, size)?; this.write_pointer(result, dest)?; } "chdir" => { - let [path] = this.check_shim(abi, Conv::C, link_name, args)?; + let [path] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.chdir(path)?; this.write_scalar(result, dest)?; } "getpid" => { - let [] = this.check_shim(abi, Conv::C, link_name, args)?; + let [] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [], + this.libc_ty_layout("pid_t").ty, + args, + )?; let result = this.getpid()?; this.write_scalar(result, dest)?; } "sysconf" => { - let [val] = this.check_shim(abi, Conv::C, link_name, args)?; + let [val] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32], + this.tcx.types.isize, + args, + )?; let result = this.sysconf(val)?; this.write_scalar(result, dest)?; } // File descriptors "read" => { - let [fd, buf, count] = this.check_shim(abi, Conv::C, link_name, args)?; + let [fd, buf, count] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32, this.machine.layouts.mut_raw_ptr.ty, this.tcx.types.usize], + this.tcx.types.isize, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_pointer(buf)?; let count = this.read_target_usize(count)?; this.read(fd, buf, count, None, dest)?; } "write" => { - let [fd, buf, n] = this.check_shim(abi, Conv::C, link_name, args)?; + let [fd, buf, n] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [ + this.tcx.types.i32, + this.machine.layouts.const_raw_ptr.ty, + this.tcx.types.usize, + ], + this.tcx.types.isize, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_pointer(buf)?; let count = this.read_target_usize(n)?; @@ -164,38 +235,88 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write(fd, buf, count, None, dest)?; } "pread" => { - let [fd, buf, count, offset] = this.check_shim(abi, Conv::C, link_name, args)?; + let off_t = this.libc_ty_layout("off_t"); + let [fd, buf, count, offset] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [ + this.tcx.types.i32, + this.machine.layouts.mut_raw_ptr.ty, + this.tcx.types.usize, + off_t.ty, + ], + this.tcx.types.isize, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_pointer(buf)?; let count = this.read_target_usize(count)?; - let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; + let offset = this.read_scalar(offset)?.to_int(off_t.size)?; this.read(fd, buf, count, Some(offset), dest)?; } "pwrite" => { - let [fd, buf, n, offset] = this.check_shim(abi, Conv::C, link_name, args)?; + let off_t = this.libc_ty_layout("off_t"); + let [fd, buf, n, offset] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [ + this.tcx.types.i32, + this.machine.layouts.const_raw_ptr.ty, + this.tcx.types.usize, + off_t.ty, + ], + this.tcx.types.isize, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_pointer(buf)?; let count = this.read_target_usize(n)?; - let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; + let offset = this.read_scalar(offset)?.to_int(off_t.size)?; trace!("Called pwrite({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset); this.write(fd, buf, count, Some(offset), dest)?; } "pread64" => { - let [fd, buf, count, offset] = this.check_shim(abi, Conv::C, link_name, args)?; + let off64_t = this.libc_ty_layout("off64_t"); + let [fd, buf, count, offset] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [ + this.tcx.types.i32, + this.machine.layouts.mut_raw_ptr.ty, + this.tcx.types.usize, + off64_t.ty, + ], + this.tcx.types.isize, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_pointer(buf)?; let count = this.read_target_usize(count)?; - let offset = - this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?; + let offset = this.read_scalar(offset)?.to_int(off64_t.size)?; this.read(fd, buf, count, Some(offset), dest)?; } "pwrite64" => { - let [fd, buf, n, offset] = this.check_shim(abi, Conv::C, link_name, args)?; + let off64_t = this.libc_ty_layout("off64_t"); + let [fd, buf, n, offset] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [ + this.tcx.types.i32, + this.machine.layouts.const_raw_ptr.ty, + this.tcx.types.usize, + off64_t.ty, + ], + this.tcx.types.isize, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_pointer(buf)?; let count = this.read_target_usize(n)?; - let offset = - this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?; + let offset = this.read_scalar(offset)?.to_int(off64_t.size)?; trace!("Called pwrite64({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset); this.write(fd, buf, count, Some(offset), dest)?; } @@ -218,13 +339,27 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } "dup" => { - let [old_fd] = this.check_shim(abi, Conv::C, link_name, args)?; + let [old_fd] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32], + this.tcx.types.i32, + args, + )?; let old_fd = this.read_scalar(old_fd)?.to_i32()?; let new_fd = this.dup(old_fd)?; this.write_scalar(new_fd, dest)?; } "dup2" => { - let [old_fd, new_fd] = this.check_shim(abi, Conv::C, link_name, args)?; + let [old_fd, new_fd] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32, this.tcx.types.i32], + this.tcx.types.i32, + args, + )?; let old_fd = this.read_scalar(old_fd)?.to_i32()?; let new_fd = this.read_scalar(new_fd)?.to_i32()?; let result = this.dup2(old_fd, new_fd)?; @@ -233,7 +368,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "flock" => { // Currently this function does not exist on all Unixes, e.g. on Solaris. this.check_target_os(&["linux", "freebsd", "macos", "illumos"], link_name)?; - let [fd, op] = this.check_shim(abi, Conv::C, link_name, args)?; + let [fd, op] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32, this.tcx.types.i32], + this.tcx.types.i32, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; let op = this.read_scalar(op)?.to_i32()?; let result = this.flock(fd, op)?; @@ -250,140 +392,311 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } "unlink" => { - let [path] = this.check_shim(abi, Conv::C, link_name, args)?; + let [path] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.unlink(path)?; this.write_scalar(result, dest)?; } "symlink" => { - let [target, linkpath] = this.check_shim(abi, Conv::C, link_name, args)?; + let [target, linkpath] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty, this.machine.layouts.const_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.symlink(target, linkpath)?; this.write_scalar(result, dest)?; } "rename" => { - let [oldpath, newpath] = this.check_shim(abi, Conv::C, link_name, args)?; + let [oldpath, newpath] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty, this.machine.layouts.const_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.rename(oldpath, newpath)?; this.write_scalar(result, dest)?; } "mkdir" => { - let [path, mode] = this.check_shim(abi, Conv::C, link_name, args)?; + let [path, mode] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty, this.libc_ty_layout("mode_t").ty], + this.tcx.types.i32, + args, + )?; let result = this.mkdir(path, mode)?; this.write_scalar(result, dest)?; } "rmdir" => { - let [path] = this.check_shim(abi, Conv::C, link_name, args)?; + let [path] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.rmdir(path)?; this.write_scalar(result, dest)?; } "opendir" => { - let [name] = this.check_shim(abi, Conv::C, link_name, args)?; + let [name] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty], + this.machine.layouts.mut_raw_ptr.ty, + args, + )?; let result = this.opendir(name)?; this.write_scalar(result, dest)?; } "closedir" => { - let [dirp] = this.check_shim(abi, Conv::C, link_name, args)?; + let [dirp] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.mut_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.closedir(dirp)?; this.write_scalar(result, dest)?; } "lseek64" => { - let [fd, offset, whence] = this.check_shim(abi, Conv::C, link_name, args)?; + let off64_t = this.libc_ty_layout("off64_t"); + let [fd, offset, whence] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32, off64_t.ty, this.tcx.types.i32], + off64_t.ty, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; - let offset = this.read_scalar(offset)?.to_i64()?; + let offset = this.read_scalar(offset)?.to_int(off64_t.size)?; let whence = this.read_scalar(whence)?.to_i32()?; - let result = this.lseek64(fd, offset.into(), whence)?; - this.write_scalar(result, dest)?; + this.lseek64(fd, offset, whence, dest)?; } "lseek" => { - let [fd, offset, whence] = this.check_shim(abi, Conv::C, link_name, args)?; + let off_t = this.libc_ty_layout("off_t"); + let [fd, offset, whence] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32, off_t.ty, this.tcx.types.i32], + off_t.ty, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; - let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; + let offset = this.read_scalar(offset)?.to_int(off_t.size)?; let whence = this.read_scalar(whence)?.to_i32()?; - let result = this.lseek64(fd, offset, whence)?; - this.write_scalar(result, dest)?; + this.lseek64(fd, offset, whence, dest)?; } "ftruncate64" => { - let [fd, length] = this.check_shim(abi, Conv::C, link_name, args)?; + let off64_t = this.libc_ty_layout("off64_t"); + let [fd, length] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32, off64_t.ty], + this.tcx.types.i32, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; - let length = this.read_scalar(length)?.to_i64()?; - let result = this.ftruncate64(fd, length.into())?; + let length = this.read_scalar(length)?.to_int(off64_t.size)?; + let result = this.ftruncate64(fd, length)?; this.write_scalar(result, dest)?; } "ftruncate" => { - let [fd, length] = this.check_shim(abi, Conv::C, link_name, args)?; + let off_t = this.libc_ty_layout("off_t"); + let [fd, length] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32, off_t.ty], + this.tcx.types.i32, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; - let length = this.read_scalar(length)?.to_int(this.libc_ty_layout("off_t").size)?; + let length = this.read_scalar(length)?.to_int(off_t.size)?; let result = this.ftruncate64(fd, length)?; this.write_scalar(result, dest)?; } "fsync" => { - let [fd] = this.check_shim(abi, Conv::C, link_name, args)?; + let [fd] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32], + this.tcx.types.i32, + args, + )?; let result = this.fsync(fd)?; this.write_scalar(result, dest)?; } "fdatasync" => { - let [fd] = this.check_shim(abi, Conv::C, link_name, args)?; + let [fd] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32], + this.tcx.types.i32, + args, + )?; let result = this.fdatasync(fd)?; this.write_scalar(result, dest)?; } "readlink" => { - let [pathname, buf, bufsize] = this.check_shim(abi, Conv::C, link_name, args)?; + let [pathname, buf, bufsize] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [ + this.machine.layouts.const_raw_ptr.ty, + this.machine.layouts.mut_raw_ptr.ty, + this.tcx.types.usize, + ], + this.tcx.types.isize, + args, + )?; let result = this.readlink(pathname, buf, bufsize)?; this.write_scalar(Scalar::from_target_isize(result, this), dest)?; } "posix_fadvise" => { - let [fd, offset, len, advice] = this.check_shim(abi, Conv::C, link_name, args)?; + let off_t = this.libc_ty_layout("off_t"); + let [fd, offset, len, advice] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32, off_t.ty, off_t.ty, this.tcx.types.i32], + this.tcx.types.i32, + args, + )?; this.read_scalar(fd)?.to_i32()?; - this.read_target_isize(offset)?; - this.read_target_isize(len)?; + this.read_scalar(offset)?.to_int(off_t.size)?; + this.read_scalar(len)?.to_int(off_t.size)?; this.read_scalar(advice)?.to_i32()?; // fadvise is only informational, we can ignore it. this.write_null(dest)?; } "realpath" => { - let [path, resolved_path] = this.check_shim(abi, Conv::C, link_name, args)?; + let [path, resolved_path] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty, this.machine.layouts.mut_raw_ptr.ty], + this.machine.layouts.mut_raw_ptr.ty, + args, + )?; let result = this.realpath(path, resolved_path)?; this.write_scalar(result, dest)?; } "mkstemp" => { - let [template] = this.check_shim(abi, Conv::C, link_name, args)?; + let [template] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.mut_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.mkstemp(template)?; this.write_scalar(result, dest)?; } // Unnamed sockets and pipes "socketpair" => { - let [domain, type_, protocol, sv] = - this.check_shim(abi, Conv::C, link_name, args)?; + let [domain, type_, protocol, sv] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [ + this.tcx.types.i32, + this.tcx.types.i32, + this.tcx.types.i32, + this.machine.layouts.mut_raw_ptr.ty, + ], + this.tcx.types.i32, + args, + )?; let result = this.socketpair(domain, type_, protocol, sv)?; this.write_scalar(result, dest)?; } "pipe" => { - let [pipefd] = this.check_shim(abi, Conv::C, link_name, args)?; + let [pipefd] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.mut_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.pipe2(pipefd, /*flags*/ None)?; this.write_scalar(result, dest)?; } "pipe2" => { // Currently this function does not exist on all Unixes, e.g. on macOS. this.check_target_os(&["linux", "freebsd", "solaris", "illumos"], link_name)?; - let [pipefd, flags] = this.check_shim(abi, Conv::C, link_name, args)?; + let [pipefd, flags] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.mut_raw_ptr.ty, this.tcx.types.i32], + this.tcx.types.i32, + args, + )?; let result = this.pipe2(pipefd, Some(flags))?; this.write_scalar(result, dest)?; } // Time "gettimeofday" => { - let [tv, tz] = this.check_shim(abi, Conv::C, link_name, args)?; + let [tv, tz] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.mut_raw_ptr.ty, this.machine.layouts.mut_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.gettimeofday(tv, tz)?; this.write_scalar(result, dest)?; } "localtime_r" => { - let [timep, result_op] = this.check_shim(abi, Conv::C, link_name, args)?; + let [timep, result_op] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty, this.machine.layouts.mut_raw_ptr.ty], + this.machine.layouts.mut_raw_ptr.ty, + args, + )?; let result = this.localtime_r(timep, result_op)?; this.write_pointer(result, dest)?; } "clock_gettime" => { - let [clk_id, tp] = this.check_shim(abi, Conv::C, link_name, args)?; - let result = this.clock_gettime(clk_id, tp)?; - this.write_scalar(result, dest)?; + let [clk_id, tp] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.libc_ty_layout("clockid_t").ty, this.machine.layouts.mut_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; + this.clock_gettime(clk_id, tp, dest)?; } // Allocation @@ -834,7 +1147,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // These shims are enabled only when the caller is in the standard library. "pthread_attr_getguardsize" if this.frame_in_std() => { let [_attr, guard_size] = this.check_shim(abi, Conv::C, link_name, args)?; - let guard_size_layout = this.libc_ty_layout("size_t"); + let guard_size_layout = this.machine.layouts.usize; let guard_size = this.deref_pointer_as(guard_size, guard_size_layout)?; this.write_scalar( Scalar::from_uint(this.machine.page_size, guard_size_layout.size), diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index fc0f57694a715..1f6acff0787a6 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -502,7 +502,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(Scalar::from_i32(this.try_unwrap_io_result(fd)?)) } - fn lseek64(&mut self, fd_num: i32, offset: i128, whence: i32) -> InterpResult<'tcx, Scalar> { + fn lseek64( + &mut self, + fd_num: i32, + offset: i128, + whence: i32, + dest: &MPlaceTy<'tcx>, + ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); // Isolation check is done via `FileDescription` trait. @@ -510,7 +516,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let seek_from = if whence == this.eval_libc_i32("SEEK_SET") { if offset < 0 { // Negative offsets return `EINVAL`. - return this.set_last_error_and_return_i64(LibcError("EINVAL")); + return this.set_last_error_and_return(LibcError("EINVAL"), dest); } else { SeekFrom::Start(u64::try_from(offset).unwrap()) } @@ -519,19 +525,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } else if whence == this.eval_libc_i32("SEEK_END") { SeekFrom::End(i64::try_from(offset).unwrap()) } else { - return this.set_last_error_and_return_i64(LibcError("EINVAL")); + return this.set_last_error_and_return(LibcError("EINVAL"), dest); }; let communicate = this.machine.communicate(); let Some(fd) = this.machine.fds.get(fd_num) else { - return this.set_last_error_and_return_i64(LibcError("EBADF")); + return this.set_last_error_and_return(LibcError("EBADF"), dest); }; let result = fd.seek(communicate, seek_from)?.map(|offset| i64::try_from(offset).unwrap()); drop(fd); let result = this.try_unwrap_io_result(result)?; - interp_ok(Scalar::from_i64(result)) + this.write_int(result, dest)?; + interp_ok(()) } fn unlink(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { diff --git a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs index 515e467fb54d3..ac6e221fcd8d3 100644 --- a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs +++ b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs @@ -9,6 +9,6 @@ extern "C" { fn main() { let mut fds = [-1, -1]; let res = unsafe { pipe(fds.as_mut_ptr()) }; - //~^ ERROR: calling a non-variadic function with a variadic caller-side signature + //~^ ERROR: ABI mismatch: calling a non-variadic function with a variadic caller-side signature assert_eq!(res, 0); } diff --git a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr index 2782f3b3269cf..0f642aca322af 100644 --- a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr +++ b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: calling a non-variadic function with a variadic caller-side signature +error: Undefined Behavior: ABI mismatch: calling a non-variadic function with a variadic caller-side signature --> tests/fail/shims/vararg_caller_signature_mismatch.rs:LL:CC | LL | let res = unsafe { pipe(fds.as_mut_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^ calling a non-variadic function with a variadic caller-side signature + | ^^^^^^^^^^^^^^^^^^^^^^ ABI mismatch: calling a non-variadic function with a variadic caller-side signature | = 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 From 9cd4757f5983c50bbd2191850c4fbc542c42a103 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 17 Apr 2025 16:11:37 +0200 Subject: [PATCH 05/24] ci.yml: always create sync PR when there's any difference --- src/tools/miri/.github/workflows/ci.yml | 72 +++++++++++++------------ 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index 59bae513a58f4..bd6d51530a9a9 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -89,41 +89,16 @@ jobs: # Check if all jobs that we depend on (in the needs array) were successful. jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' - cron-fail-notify: - name: cronjob failure notification + cron-rustc-pull: + name: automatic pull from rustc runs-on: ubuntu-latest permissions: # The cronjob needs to be able to push to the repo... contents: write # ... and create a PR. pull-requests: write - needs: [build, style, coverage] - if: ${{ github.event_name == 'schedule' && failure() }} + if: ${{ github.event_name == 'schedule' }} steps: - # Send a Zulip notification - - name: Install zulip-send - run: pip3 install zulip - - name: Send Zulip notification - env: - ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }} - ZULIP_API_TOKEN: ${{ secrets.ZULIP_API_TOKEN }} - run: | - ~/.local/bin/zulip-send --user $ZULIP_BOT_EMAIL --api-key $ZULIP_API_TOKEN --site https://rust-lang.zulipchat.com \ - --stream miri --subject "Miri Build Failure ($(date -u +%Y-%m))" \ - --message 'Dear @*T-miri*, - - It would appear that the [Miri cron job build]('"https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"') failed. - - This likely means that rustc changed the miri directory and - we now need to do a [`./miri rustc-pull`](https://github.com/rust-lang/miri/blob/master/CONTRIBUTING.md#importing-changes-from-the-rustc-repo). - - Would you mind investigating this issue? - - Thanks in advance! - Sincerely, - The Miri Cronjobs Bot' - - # Attempt to auto-sync with rustc - uses: actions/checkout@v4 with: fetch-depth: 256 # get a bit more of the history @@ -143,18 +118,45 @@ jobs: run: | ./miri toolchain ./miri fmt --check || (./miri fmt && git commit -am "fmt") - - name: Push changes to a branch + - name: Push changes to a branch and create PR run: | + # `git diff --exit-code` "succeeds" if the diff is empty. + if git diff --exit-code HEAD^; then exit 0; fi + # The diff is non-empty, create a PR. BRANCH="rustup-$(date -u +%Y-%m-%d)" git switch -c $BRANCH git push -u origin $BRANCH - - name: Create Pull Request - run: | - PR=$(gh pr create -B master --title 'Automatic Rustup' --body 'Please close and re-open this PR to trigger CI, then enable auto-merge.') - ~/.local/bin/zulip-send --user $ZULIP_BOT_EMAIL --api-key $ZULIP_API_TOKEN --site https://rust-lang.zulipchat.com \ - --stream miri --subject "Miri Build Failure ($(date -u +%Y-%m))" \ - --message "A PR doing a rustc-pull [has been automatically created]($PR) for your convenience." + gh pr create -B master --title 'Automatic Rustup' --body 'Please close and re-open this PR to trigger CI, then enable auto-merge.' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }} ZULIP_API_TOKEN: ${{ secrets.ZULIP_API_TOKEN }} + + cron-fail-notify: + name: cronjob failure notification + runs-on: ubuntu-latest + needs: [build, style, coverage] + if: ${{ github.event_name == 'schedule' && failure() }} + steps: + # Send a Zulip notification + - name: Install zulip-send + run: pip3 install zulip + - name: Send Zulip notification + env: + ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }} + ZULIP_API_TOKEN: ${{ secrets.ZULIP_API_TOKEN }} + run: | + ~/.local/bin/zulip-send --user $ZULIP_BOT_EMAIL --api-key $ZULIP_API_TOKEN --site https://rust-lang.zulipchat.com \ + --stream miri --subject "Miri Build Failure ($(date -u +%Y-%m))" \ + --message 'Dear @*T-miri*, + + It would appear that the [Miri cron job build]('"https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"') failed. + + This likely means that rustc changed the miri directory and + we now need to do a [`./miri rustc-pull`](https://github.com/rust-lang/miri/blob/master/CONTRIBUTING.md#importing-changes-from-the-rustc-repo). + + Would you mind investigating this issue? + + Thanks in advance! + Sincerely, + The Miri Cronjobs Bot' From 8c9a9a77164ae3621a4bc7710670a8a49b0a9e66 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 17 Apr 2025 16:12:42 +0200 Subject: [PATCH 06/24] for testing, run the CI job an extra time today --- src/tools/miri/.github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index bd6d51530a9a9..86815fc60fb88 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -6,7 +6,7 @@ on: branches: - 'master' schedule: - - cron: '44 4 * * *' # At 4:44 UTC every day. + - cron: '44 4,17 * * *' # At 4:44 UTC every day. defaults: run: From edb3aaf655f1a7a766c5d37eacbf7931c087130b Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Thu, 17 Apr 2025 17:50:48 +0000 Subject: [PATCH 07/24] 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 d1107e5150906..ed2e4474adda7 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -1bc56185ee257ed829a0aea7abdc3b03c5fed887 +883f9f72e87ccb6838d528d8158ea6323baacc65 From e3b01c774953b8174c556b8a96383fe3132db931 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 17 Apr 2025 20:16:53 +0200 Subject: [PATCH 08/24] remove test trigger fron cron job --- src/tools/miri/.github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index 86815fc60fb88..bd6d51530a9a9 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -6,7 +6,7 @@ on: branches: - 'master' schedule: - - cron: '44 4,17 * * *' # At 4:44 UTC every day. + - cron: '44 4 * * *' # At 4:44 UTC every day. defaults: run: From 378886f77239c4661945c877f50c17512bbbd6a2 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Fri, 18 Apr 2025 04:54:04 +0000 Subject: [PATCH 09/24] 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 ed2e4474adda7..45b3546a09b4b 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -883f9f72e87ccb6838d528d8158ea6323baacc65 +1f76d219c906f0112bb1872f33aa977164c53fa6 From 4b995e72b66e510f678484400c33f838cbf0361b Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sat, 19 Apr 2025 04:52:37 +0000 Subject: [PATCH 10/24] 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 45b3546a09b4b..2d7b6a650aef8 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -1f76d219c906f0112bb1872f33aa977164c53fa6 +2ef78586529b5f68cc42bcbe9b10b4afe56a942a From 32fe60bc57ccdc234eb51bd22f74f3b55f2941e8 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sun, 20 Apr 2025 04:52:36 +0000 Subject: [PATCH 11/24] 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 2d7b6a650aef8..ce1b8fabac707 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -2ef78586529b5f68cc42bcbe9b10b4afe56a942a +90fd16eb5be9255006c95e8af12a0d43854dc1a9 From 9d16f6666dd92990cf36e40f9043b7c962a9d627 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Tue, 22 Apr 2025 04:53:59 +0000 Subject: [PATCH 12/24] 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 ce1b8fabac707..b9d35019e1f92 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -90fd16eb5be9255006c95e8af12a0d43854dc1a9 +fae7785b60ea7fe1ad293352c057a5b7be73d245 From ae3adaec6d2c23d6e31078486f0ac29b534c4638 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 22 Apr 2025 11:19:57 +0200 Subject: [PATCH 13/24] TB: add missing interior_mutability test file --- .../pass/tree_borrows/interior_mutability.rs | 177 ++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 src/tools/miri/tests/pass/tree_borrows/interior_mutability.rs diff --git a/src/tools/miri/tests/pass/tree_borrows/interior_mutability.rs b/src/tools/miri/tests/pass/tree_borrows/interior_mutability.rs new file mode 100644 index 0000000000000..752ae4b20c5d3 --- /dev/null +++ b/src/tools/miri/tests/pass/tree_borrows/interior_mutability.rs @@ -0,0 +1,177 @@ +//@revisions: default uniq +//@compile-flags: -Zmiri-tree-borrows +//@[uniq]compile-flags: -Zmiri-unique-is-unique +use std::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell}; +use std::mem::{self, MaybeUninit}; + +fn main() { + aliasing_mut_and_shr(); + aliasing_frz_and_shr(); + into_interior_mutability(); + unsafe_cell_2phase(); + unsafe_cell_deallocate(); + unsafe_cell_invalidate(); + refcell_basic(); + ref_protector(); + ref_mut_protector(); + rust_issue_68303(); +} + +fn aliasing_mut_and_shr() { + fn inner(rc: &RefCell, aliasing: &mut i32) { + *aliasing += 4; + let _escape_to_raw = rc as *const _; + *aliasing += 4; + let _shr = &*rc; + *aliasing += 4; + // also turning this into a frozen ref now must work + let aliasing = &*aliasing; + let _val = *aliasing; + let _escape_to_raw = rc as *const _; // this must NOT unfreeze + let _val = *aliasing; + let _shr = &*rc; // this must NOT unfreeze + let _val = *aliasing; + } + + let rc = RefCell::new(23); + let mut bmut = rc.borrow_mut(); + inner(&rc, &mut *bmut); + drop(bmut); + assert_eq!(*rc.borrow(), 23 + 12); +} + +fn aliasing_frz_and_shr() { + fn inner(rc: &RefCell, aliasing: &i32) { + let _val = *aliasing; + let _escape_to_raw = rc as *const _; // this must NOT unfreeze + let _val = *aliasing; + let _shr = &*rc; // this must NOT unfreeze + let _val = *aliasing; + } + + let rc = RefCell::new(23); + let bshr = rc.borrow(); + inner(&rc, &*bshr); + assert_eq!(*rc.borrow(), 23); +} + +// Getting a pointer into a union with interior mutability used to be tricky +// business (https://github.com/rust-lang/miri/issues/615), but it should work +// now. +fn into_interior_mutability() { + let mut x: MaybeUninit<(Cell, u32)> = MaybeUninit::uninit(); + x.as_ptr(); + x.write((Cell::new(0), 1)); + let ptr = unsafe { x.assume_init_ref() }; + assert_eq!(ptr.1, 1); +} + +// Two-phase borrows of the pointer returned by UnsafeCell::get() should not +// invalidate aliases. +fn unsafe_cell_2phase() { + unsafe { + let x = &UnsafeCell::new(vec![]); + let x2 = &*x; + (*x.get()).push(0); + let _val = (*x2.get()).get(0); + } +} + +/// Make sure we can deallocate an UnsafeCell that was passed to an active fn call. +/// (This is the fix for https://github.com/rust-lang/rust/issues/55005.) +fn unsafe_cell_deallocate() { + fn f(x: &UnsafeCell) { + let b: Box = unsafe { Box::from_raw(x as *const _ as *mut i32) }; + drop(b) + } + + let b = Box::new(0i32); + f(unsafe { mem::transmute(Box::into_raw(b)) }); +} + +/// As a side-effect of the above, we also allow this -- at least for now. +fn unsafe_cell_invalidate() { + fn f(_x: &UnsafeCell, y: *mut i32) { + // Writing to y invalidates x, but that is okay. + unsafe { + *y += 1; + } + } + + let mut x = 0i32; + let raw1 = &mut x as *mut _; + let ref1 = unsafe { &mut *raw1 }; + let raw2 = ref1 as *mut _; + // Now the borrow stack is: raw1, ref2, raw2. + // So using raw1 invalidates raw2. + f(unsafe { mem::transmute(raw2) }, raw1); +} + +fn refcell_basic() { + let c = RefCell::new(42); + { + let s1 = c.borrow(); + let _x: i32 = *s1; + let s2 = c.borrow(); + let _x: i32 = *s1; + let _y: i32 = *s2; + let _x: i32 = *s1; + let _y: i32 = *s2; + } + { + let mut m = c.borrow_mut(); + let _z: i32 = *m; + { + let s: &i32 = &*m; + let _x = *s; + } + *m = 23; + let _z: i32 = *m; + } + { + let s1 = c.borrow(); + let _x: i32 = *s1; + let s2 = c.borrow(); + let _x: i32 = *s1; + let _y: i32 = *s2; + let _x: i32 = *s1; + let _y: i32 = *s2; + } +} + +// Adding a Stacked Borrows protector for `Ref` would break this +fn ref_protector() { + fn break_it(rc: &RefCell, r: Ref<'_, i32>) { + // `r` has a shared reference, it is passed in as argument and hence + // a protector is added that marks this memory as read-only for the entire + // duration of this function. + drop(r); + // *oops* here we can mutate that memory. + *rc.borrow_mut() = 2; + } + + let rc = RefCell::new(0); + break_it(&rc, rc.borrow()) +} + +fn ref_mut_protector() { + fn break_it(rc: &RefCell, r: RefMut<'_, i32>) { + // `r` has a shared reference, it is passed in as argument and hence + // a protector is added that marks this memory as inaccessible for the entire + // duration of this function + drop(r); + // *oops* here we can mutate that memory. + *rc.borrow_mut() = 2; + } + + let rc = RefCell::new(0); + break_it(&rc, rc.borrow_mut()) +} + +/// Make sure we do not have bad enum layout optimizations. +fn rust_issue_68303() { + let optional = Some(RefCell::new(false)); + let mut handle = optional.as_ref().unwrap().borrow_mut(); + assert!(optional.is_some()); + *handle = true; +} From 39ddb4262716c7f7a145b653bc637a8c8af45cc7 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Wed, 23 Apr 2025 04:54:12 +0000 Subject: [PATCH 14/24] 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 b9d35019e1f92..f6e6b1ca741d5 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -fae7785b60ea7fe1ad293352c057a5b7be73d245 +1a5bf12f6586d724ed5ff40e58e06c0233560c0e From 9b491c0b3be8c2cd90e1f05db744f9881fac87ff Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 24 Apr 2025 10:57:42 +0200 Subject: [PATCH 15/24] 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 f6e6b1ca741d5..5be53f4766835 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -1a5bf12f6586d724ed5ff40e58e06c0233560c0e +7f695232a80fa1833e2282f2577c5e1ff066bf39 From f1b6b85f0840a4c14a3d955ea0b5c0164289f94a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 24 Apr 2025 10:59:04 +0200 Subject: [PATCH 16/24] CI: print message when skipping PR --- src/tools/miri/.github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index bd6d51530a9a9..9dbf51e9796a7 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -121,7 +121,7 @@ jobs: - name: Push changes to a branch and create PR run: | # `git diff --exit-code` "succeeds" if the diff is empty. - if git diff --exit-code HEAD^; then exit 0; fi + if git diff --exit-code HEAD^; then echo "Nothing changed in rustc, skipping PR"; exit 0; fi # The diff is non-empty, create a PR. BRANCH="rustup-$(date -u +%Y-%m-%d)" git switch -c $BRANCH From f2bbc1bf06ef905cf2f5ea9a54f5b3390f534b49 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 24 Apr 2025 11:02:55 +0200 Subject: [PATCH 17/24] clippy --- .../src/borrow_tracker/tree_borrows/tree/tests.rs | 15 +++++++-------- src/tools/miri/src/concurrency/data_race.rs | 2 +- src/tools/miri/src/machine.rs | 5 ++--- src/tools/miri/src/shims/time.rs | 4 ++-- 4 files changed, 12 insertions(+), 14 deletions(-) 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 a429940748c86..dbfa9807e3b5a 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 @@ -61,8 +61,7 @@ fn all_read_accesses_commute() { // ... and produce the same final result. assert_eq!( loc12, loc21, - "Read accesses {:?} followed by {:?} do not commute !", - rel1, rel2 + "Read accesses {rel1:?} followed by {rel2:?} do not commute !" ); } } @@ -674,8 +673,8 @@ mod spurious_read { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let (x, y) = self.retag_permissions(); write!(f, "{}; ", self.xy_rel)?; - write!(f, "y: ({}); ", y,)?; - write!(f, "retag x ({}); ", x)?; + write!(f, "y: ({y}); ")?; + write!(f, "retag x ({x}); ")?; write!(f, "; ;")?; Ok(()) @@ -730,17 +729,17 @@ mod spurious_read { // protector. final_source .distinguishable::(&final_target) - .then_some(format!("{}", final_target)) + .then_some(format!("{final_target}")) } else { Some(format!("UB")) } }; if let Some(final_target) = distinguishable { eprintln!( - "For pattern '{}', inserting a spurious read through x makes the final state '{}' instead of '{}' which is observable", - pat, final_target, final_source + "For pattern '{pat}', inserting a spurious read through x makes the final state '{final_target}' \ + instead of '{final_source}' which is observable" ); - eprintln!(" (arbitrary code instanciated with '{}')", opaque); + eprintln!(" (arbitrary code instanciated with '{opaque}')"); err += 1; // We found an instanciation of the opaque code that makes this Pattern // fail, we don't really need to check the rest. diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index 923031dbbd1eb..847c682347592 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -381,7 +381,7 @@ impl AccessType { }); if let Some(ty) = ty { - msg.push_str(&format!(" of type `{}`", ty)); + msg.push_str(&format!(" of type `{ty}`")); } msg diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index ea59d327be846..c3d841353a8a7 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -721,9 +721,8 @@ impl<'tcx> MiriMachine<'tcx> { // Check if host target == the session target. if host_triple != target_triple { panic!( - "calling external C functions in linked .so file requires host and target to be the same: host={}, target={}", - host_triple, - target_triple, + "calling native C functions in linked .so file requires host and target to be the same: \ + host={host_triple}, target={target_triple}", ); } // Note: it is the user's responsibility to provide a correct SO file. diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index c98d6e2b408a2..28f4ca5bb1b76 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -191,10 +191,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { tm_zone.push('+'); } let offset_hour = offset_in_seconds.abs() / 3600; - write!(tm_zone, "{:02}", offset_hour).unwrap(); + write!(tm_zone, "{offset_hour:02}").unwrap(); let offset_min = (offset_in_seconds.abs() % 3600) / 60; if offset_min != 0 { - write!(tm_zone, "{:02}", offset_min).unwrap(); + write!(tm_zone, "{offset_min:02}").unwrap(); } // Add null terminator for C string compatibility. From 37049558e43e72fa3890aa3f7c23e5f00414444c Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Fri, 25 Apr 2025 04:54:29 +0000 Subject: [PATCH 18/24] 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 5be53f4766835..46e045ac76946 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -7f695232a80fa1833e2282f2577c5e1ff066bf39 +847e3ee6b0e614937eee4e6d8f61094411eadcc0 From 673c879abb7f3b05e25f0da5654e2a484abc17c0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 25 Apr 2025 12:18:27 +0200 Subject: [PATCH 19/24] avoid an unnecessary transmute --- src/tools/miri/bench-cargo-miri/mse/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/bench-cargo-miri/mse/src/main.rs b/src/tools/miri/bench-cargo-miri/mse/src/main.rs index 06d5487d1d4ea..69c7c39cdd7e2 100644 --- a/src/tools/miri/bench-cargo-miri/mse/src/main.rs +++ b/src/tools/miri/bench-cargo-miri/mse/src/main.rs @@ -13,7 +13,7 @@ fn read_i16(buffer: &[u8], index: usize) -> i16 { const SIZE: usize = size_of::(); let mut bytes: [u8; SIZE] = [0u8; SIZE]; bytes.copy_from_slice(&buffer[(index * SIZE)..(index * SIZE + SIZE)]); - unsafe { std::mem::transmute(bytes) } + i16::from_ne_bytes(bytes) } fn mse(samples: usize, frame_buf: &[i16], buf_ref: &[u8]) -> f64 { From 5980c8ca18aaa976af672825a8bf172abfd782a3 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sat, 26 Apr 2025 04:52:46 +0000 Subject: [PATCH 20/24] 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 46e045ac76946..1ecaf8675c20e 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -847e3ee6b0e614937eee4e6d8f61094411eadcc0 +555e1d0386f024a8359645c3217f4b3eae9be042 From 15c4e4092817ee38c8235f3189d2644e1ac511ee Mon Sep 17 00:00:00 2001 From: primoly <168267431+primoly@users.noreply.github.com> Date: Sun, 27 Apr 2025 13:49:51 +0200 Subject: [PATCH 21/24] `unsafe(no_mangle)` in `miri_start` examples --- src/tools/miri/README.md | 2 +- src/tools/miri/src/bin/miri.rs | 4 ++-- src/tools/miri/tests/fail/no_main.stderr | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index e8ea988558ce9..95e1770aa7bad 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -489,7 +489,7 @@ Miri knows where it is supposed to start execution: ```rust #[cfg(miri)] -#[no_mangle] +#[unsafe(no_mangle)] fn miri_start(argc: isize, argv: *const *const u8) -> isize { // Call the actual start function that your project implements, based on your target's conventions. } diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 4e8fe0ca8adf7..8ff1c9d6ff022 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -106,7 +106,7 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) { } else { tcx.dcx().fatal( "`miri_start` must have the following signature:\n\ - fn miri_start(argc: isize, argv: *const *const u8) -> isize", + fn miri_start(argc: isize, argv: *const *const u8) -> isize", ); } } else { @@ -115,7 +115,7 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) { Alternatively, you can export a `miri_start` function:\n\ \n\ #[cfg(miri)]\n\ - #[no_mangle]\n\ + #[unsafe(no_mangle)]\n\ fn miri_start(argc: isize, argv: *const *const u8) -> isize {\ \n // Call the actual start function that your project implements, based on your target's conventions.\n\ }" diff --git a/src/tools/miri/tests/fail/no_main.stderr b/src/tools/miri/tests/fail/no_main.stderr index e9b9e5d65b1d1..e7f63be794f42 100644 --- a/src/tools/miri/tests/fail/no_main.stderr +++ b/src/tools/miri/tests/fail/no_main.stderr @@ -2,7 +2,7 @@ error: Miri can only run programs that have a main function. Alternatively, you can export a `miri_start` function: #[cfg(miri)] - #[no_mangle] + #[unsafe(no_mangle)] fn miri_start(argc: isize, argv: *const *const u8) -> isize { // Call the actual start function that your project implements, based on your target's conventions. } From 7953c9dda43674121dfb253afc4aade280243f07 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Tue, 29 Apr 2025 06:16:28 +0000 Subject: [PATCH 22/24] 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 1ecaf8675c20e..59d53891217d0 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -555e1d0386f024a8359645c3217f4b3eae9be042 +1b8ab72680f36e783af84c1a3c4f8508572bd9f9 From c2973c949d52b6a577721b4626e3e005e2dbaabf Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Tue, 29 Apr 2025 06:25:01 +0000 Subject: [PATCH 23/24] fmt --- src/tools/miri/tests/pass/async-drop.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/tools/miri/tests/pass/async-drop.rs b/src/tools/miri/tests/pass/async-drop.rs index 2a95f644389d5..4fa84384d9bdd 100644 --- a/src/tools/miri/tests/pass/async-drop.rs +++ b/src/tools/miri/tests/pass/async-drop.rs @@ -10,10 +10,10 @@ #![allow(incomplete_features, dead_code)] // FIXME(zetanumbers): consider AsyncDestruct::async_drop cleanup tests -use core::future::{async_drop_in_place, AsyncDrop, Future}; +use core::future::{AsyncDrop, Future, async_drop_in_place}; use core::hint::black_box; use core::mem::{self, ManuallyDrop}; -use core::pin::{pin, Pin}; +use core::pin::{Pin, pin}; use core::task::{Context, Poll, Waker}; async fn test_async_drop(x: T) { @@ -200,11 +200,7 @@ union AsyncUnion { impl Drop for AsyncUnion { fn drop(&mut self) { - println!( - "AsyncUnion::drop: {}, {}", - unsafe { self.signed }, - unsafe { self.unsigned }, - ); + println!("AsyncUnion::drop: {}, {}", unsafe { self.signed }, unsafe { self.unsigned },); } } impl AsyncDrop for AsyncUnion { From 0917a072641fb50866fed781af4745321d9e0373 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 29 Apr 2025 08:53:22 +0200 Subject: [PATCH 24/24] suppress dangerous_implicit_autorefs in TB test --- src/tools/miri/tests/pass/tree_borrows/interior_mutability.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/miri/tests/pass/tree_borrows/interior_mutability.rs b/src/tools/miri/tests/pass/tree_borrows/interior_mutability.rs index 752ae4b20c5d3..6dde593d2cfc2 100644 --- a/src/tools/miri/tests/pass/tree_borrows/interior_mutability.rs +++ b/src/tools/miri/tests/pass/tree_borrows/interior_mutability.rs @@ -1,6 +1,7 @@ //@revisions: default uniq //@compile-flags: -Zmiri-tree-borrows //@[uniq]compile-flags: -Zmiri-unique-is-unique +#![allow(dangerous_implicit_autorefs)] use std::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell}; use std::mem::{self, MaybeUninit};