Skip to content

Commit

Permalink
Unrolled build for rust-lang#131286
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#131286 - RalfJung:miri-sync, r=RalfJung

Miri subtree update

r? `@ghost`
  • Loading branch information
rust-timer authored Oct 5, 2024
2 parents 5a4ee43 + 3b418b1 commit 784fb5b
Show file tree
Hide file tree
Showing 40 changed files with 1,293 additions and 402 deletions.
1 change: 0 additions & 1 deletion src/tools/miri/cargo-miri/src/phases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,6 @@ pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: Runner
RunnerPhase::Rustdoc => {
cmd.stdin(std::process::Stdio::piped());
// the warning is wrong, we have a `wait` inside the `scope` closure.
#[expect(clippy::zombie_processes)]
let mut child = cmd.spawn().expect("failed to spawn process");
let child_stdin = child.stdin.take().unwrap();
// Write stdin in a background thread, as it may block.
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/rust-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
76ed7a1fa40c3f54d3fd3f834e12bf9c932d0146
7067e4aee45c18cfa1c6af3bf79bd097684fb294
5 changes: 3 additions & 2 deletions src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -859,14 +859,15 @@ impl Tree {
) -> Option<UniIndex> {
let node = self.nodes.get(idx).unwrap();

let [child_idx] = node.children[..] else { return None };

// We never want to replace the root node, as it is also kept in `root_ptr_tags`.
if node.children.len() != 1 || live.contains(&node.tag) || node.parent.is_none() {
if live.contains(&node.tag) || node.parent.is_none() {
return None;
}
// Since protected nodes are never GC'd (see `borrow_tracker::FrameExtra::visit_provenance`),
// we know that `node` is not protected because otherwise `live` would
// have contained `node.tag`.
let child_idx = node.children[0];
let child = self.nodes.get(child_idx).unwrap();
// Check that for that one child, `can_be_replaced_by_child` holds for the permission
// on all locations.
Expand Down
3 changes: 2 additions & 1 deletion src/tools/miri/src/concurrency/init_once.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|ecx| &mut ecx.machine.sync.init_onces,
|_| interp_ok(Default::default()),
)?
.ok_or_else(|| err_ub_format!("init_once has invalid ID")).into()
.ok_or_else(|| err_ub_format!("init_once has invalid ID"))
.into()
}

#[inline]
Expand Down
9 changes: 6 additions & 3 deletions src/tools/miri/src/concurrency/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|ecx| &mut ecx.machine.sync.mutexes,
|ecx| initialize_data(ecx).map(|data| Mutex { data, ..Default::default() }),
)?
.ok_or_else(|| err_ub_format!("mutex has invalid ID")).into()
.ok_or_else(|| err_ub_format!("mutex has invalid ID"))
.into()
}

/// Retrieve the additional data stored for a mutex.
Expand All @@ -334,7 +335,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|ecx| &mut ecx.machine.sync.rwlocks,
|ecx| initialize_data(ecx).map(|data| RwLock { data, ..Default::default() }),
)?
.ok_or_else(|| err_ub_format!("rwlock has invalid ID")).into()
.ok_or_else(|| err_ub_format!("rwlock has invalid ID"))
.into()
}

/// Retrieve the additional data stored for a rwlock.
Expand Down Expand Up @@ -375,7 +377,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|ecx| &mut ecx.machine.sync.condvars,
|ecx| initialize_data(ecx).map(|data| Condvar { data, ..Default::default() }),
)?
.ok_or_else(|| err_ub_format!("condvar has invalid ID")).into()
.ok_or_else(|| err_ub_format!("condvar has invalid ID"))
.into()
}

/// Retrieve the additional data stored for a condvar.
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/src/concurrency/vector_clock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ impl VClock {
/// Load the internal timestamp slice in the vector clock
#[inline]
pub(super) fn as_slice(&self) -> &[VTimestamp] {
debug_assert!(!self.0.last().is_some_and(|t| t.time() == 0));
debug_assert!(self.0.last().is_none_or(|t| t.time() != 0));
self.0.as_slice()
}

Expand Down
196 changes: 13 additions & 183 deletions src/tools/miri/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,65 +31,6 @@ pub enum AccessKind {
Write,
}

// This mapping should match `decode_error_kind` in
// <https://github.com/rust-lang/rust/blob/master/library/std/src/sys/pal/unix/mod.rs>.
const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
use std::io::ErrorKind::*;
&[
("E2BIG", ArgumentListTooLong),
("EADDRINUSE", AddrInUse),
("EADDRNOTAVAIL", AddrNotAvailable),
("EBUSY", ResourceBusy),
("ECONNABORTED", ConnectionAborted),
("ECONNREFUSED", ConnectionRefused),
("ECONNRESET", ConnectionReset),
("EDEADLK", Deadlock),
("EDQUOT", FilesystemQuotaExceeded),
("EEXIST", AlreadyExists),
("EFBIG", FileTooLarge),
("EHOSTUNREACH", HostUnreachable),
("EINTR", Interrupted),
("EINVAL", InvalidInput),
("EISDIR", IsADirectory),
("ELOOP", FilesystemLoop),
("ENOENT", NotFound),
("ENOMEM", OutOfMemory),
("ENOSPC", StorageFull),
("ENOSYS", Unsupported),
("EMLINK", TooManyLinks),
("ENAMETOOLONG", InvalidFilename),
("ENETDOWN", NetworkDown),
("ENETUNREACH", NetworkUnreachable),
("ENOTCONN", NotConnected),
("ENOTDIR", NotADirectory),
("ENOTEMPTY", DirectoryNotEmpty),
("EPIPE", BrokenPipe),
("EROFS", ReadOnlyFilesystem),
("ESPIPE", NotSeekable),
("ESTALE", StaleNetworkFileHandle),
("ETIMEDOUT", TimedOut),
("ETXTBSY", ExecutableFileBusy),
("EXDEV", CrossesDevices),
// The following have two valid options. We have both for the forwards mapping; only the
// first one will be used for the backwards mapping.
("EPERM", PermissionDenied),
("EACCES", PermissionDenied),
("EWOULDBLOCK", WouldBlock),
("EAGAIN", WouldBlock),
]
};
// This mapping should match `decode_error_kind` in
// <https://github.com/rust-lang/rust/blob/master/library/std/src/sys/pal/windows/mod.rs>.
const WINDOWS_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
use std::io::ErrorKind::*;
// FIXME: this is still incomplete.
&[
("ERROR_ACCESS_DENIED", PermissionDenied),
("ERROR_FILE_NOT_FOUND", NotFound),
("ERROR_INVALID_PARAMETER", InvalidInput),
]
};

/// Gets an instance for a path.
///
/// A `None` namespace indicates we are looking for a module.
Expand Down Expand Up @@ -745,119 +686,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
self.eval_context_ref().tcx.sess.target.families.iter().any(|f| f == "unix")
}

/// Get last error variable as a place, lazily allocating thread-local storage for it if
/// necessary.
fn last_error_place(&mut self) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
let this = self.eval_context_mut();
if let Some(errno_place) = this.active_thread_ref().last_error.as_ref() {
interp_ok(errno_place.clone())
} else {
// Allocate new place, set initial value to 0.
let errno_layout = this.machine.layouts.u32;
let errno_place = this.allocate(errno_layout, MiriMemoryKind::Machine.into())?;
this.write_scalar(Scalar::from_u32(0), &errno_place)?;
this.active_thread_mut().last_error = Some(errno_place.clone());
interp_ok(errno_place)
}
}

/// Sets the last error variable.
fn set_last_error(&mut self, scalar: Scalar) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
let errno_place = this.last_error_place()?;
this.write_scalar(scalar, &errno_place)
}

/// Gets the last error variable.
fn get_last_error(&mut self) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
let errno_place = this.last_error_place()?;
this.read_scalar(&errno_place)
}

/// This function tries to produce the most similar OS error from the `std::io::ErrorKind`
/// as a platform-specific errnum.
fn io_error_to_errnum(&self, err: std::io::Error) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_ref();
let target = &this.tcx.sess.target;
if target.families.iter().any(|f| f == "unix") {
for &(name, kind) in UNIX_IO_ERROR_TABLE {
if err.kind() == kind {
return interp_ok(this.eval_libc(name));
}
}
throw_unsup_format!("unsupported io error: {err}")
} else if target.families.iter().any(|f| f == "windows") {
for &(name, kind) in WINDOWS_IO_ERROR_TABLE {
if err.kind() == kind {
return interp_ok(this.eval_windows("c", name));
}
}
throw_unsup_format!("unsupported io error: {err}");
} else {
throw_unsup_format!(
"converting io::Error into errnum is unsupported for OS {}",
target.os
)
}
}

/// The inverse of `io_error_to_errnum`.
#[allow(clippy::needless_return)]
fn try_errnum_to_io_error(
&self,
errnum: Scalar,
) -> InterpResult<'tcx, Option<std::io::ErrorKind>> {
let this = self.eval_context_ref();
let target = &this.tcx.sess.target;
if target.families.iter().any(|f| f == "unix") {
let errnum = errnum.to_i32()?;
for &(name, kind) in UNIX_IO_ERROR_TABLE {
if errnum == this.eval_libc_i32(name) {
return interp_ok(Some(kind));
}
}
return interp_ok(None);
} else if target.families.iter().any(|f| f == "windows") {
let errnum = errnum.to_u32()?;
for &(name, kind) in WINDOWS_IO_ERROR_TABLE {
if errnum == this.eval_windows("c", name).to_u32()? {
return interp_ok(Some(kind));
}
}
return interp_ok(None);
} else {
throw_unsup_format!(
"converting errnum into io::Error is unsupported for OS {}",
target.os
)
}
}

/// Sets the last OS error using a `std::io::ErrorKind`.
fn set_last_error_from_io_error(&mut self, err: std::io::Error) -> InterpResult<'tcx> {
self.set_last_error(self.io_error_to_errnum(err)?)
}

/// Helper function that consumes a `std::io::Result<T>` and returns a
/// `InterpResult<'tcx, T>` instead. In case the result is an error, this function returns
/// `Ok(-1)` and sets the last OS error accordingly.
///
/// This function uses `T: From<i32>` instead of `i32` directly because some IO related
/// functions return different integer types (like `read`, that returns an `i64`).
fn try_unwrap_io_result<T: From<i32>>(
&mut self,
result: std::io::Result<T>,
) -> InterpResult<'tcx, T> {
match result {
Ok(ok) => interp_ok(ok),
Err(e) => {
self.eval_context_mut().set_last_error_from_io_error(e)?;
interp_ok((-1).into())
}
}
}

/// Dereference a pointer operand to a place using `layout` instead of the pointer's declared type
fn deref_pointer_as(
&self,
Expand Down Expand Up @@ -924,17 +752,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
let nanoseconds_scalar = this.read_scalar(&nanoseconds_place)?;
let nanoseconds = nanoseconds_scalar.to_target_isize(this)?;

interp_ok(try {
// tv_sec must be non-negative.
let seconds: u64 = seconds.try_into().ok()?;
// tv_nsec must be non-negative.
let nanoseconds: u32 = nanoseconds.try_into().ok()?;
if nanoseconds >= 1_000_000_000 {
// tv_nsec must not be greater than 999,999,999.
None?
}
Duration::new(seconds, nanoseconds)
})
interp_ok(
try {
// tv_sec must be non-negative.
let seconds: u64 = seconds.try_into().ok()?;
// tv_nsec must be non-negative.
let nanoseconds: u32 = nanoseconds.try_into().ok()?;
if nanoseconds >= 1_000_000_000 {
// tv_nsec must not be greater than 999,999,999.
None?
}
Duration::new(seconds, nanoseconds)
},
)
}

/// Read bytes from a byte slice.
Expand Down
1 change: 1 addition & 0 deletions src/tools/miri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ pub use crate::range_map::RangeMap;
pub use crate::shims::EmulateItemResult;
pub use crate::shims::env::{EnvVars, EvalContextExt as _};
pub use crate::shims::foreign_items::{DynSym, EvalContextExt as _};
pub use crate::shims::io_error::{EvalContextExt as _, LibcError};
pub use crate::shims::os_str::EvalContextExt as _;
pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _};
pub use crate::shims::time::EvalContextExt as _;
Expand Down
Loading

0 comments on commit 784fb5b

Please sign in to comment.