From f0bb7c726412b3187a9ba94b97240474a096ee4a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 12 Dec 2022 08:14:22 +0100 Subject: [PATCH] make eval_libc functions ICE on any problem --- src/tools/miri/src/helpers.rs | 58 +++++--- src/tools/miri/src/shims/env.rs | 18 +-- src/tools/miri/src/shims/time.rs | 26 ++-- src/tools/miri/src/shims/tls.rs | 4 +- .../miri/src/shims/unix/foreign_items.rs | 10 +- src/tools/miri/src/shims/unix/fs.rs | 129 +++++++++--------- .../src/shims/unix/linux/foreign_items.rs | 8 +- src/tools/miri/src/shims/unix/linux/sync.rs | 22 +-- .../src/shims/unix/macos/foreign_items.rs | 2 +- src/tools/miri/src/shims/unix/sync.rs | 66 ++++----- src/tools/miri/src/shims/unix/thread.rs | 4 +- src/tools/miri/src/shims/windows/sync.rs | 28 ++-- src/tools/miri/src/shims/windows/thread.rs | 4 +- 13 files changed, 200 insertions(+), 179 deletions(-) diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 7fb2539ca5a..c11c6104c28 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -138,55 +138,77 @@ fn resolve_path(&self, path: &[&str], namespace: Namespace) -> ty::Instance<'tcx .unwrap_or_else(|| panic!("failed to find required Rust item: {path:?}")) } - /// Evaluates the scalar at the specified path. Returns Some(val) - /// if the path could be resolved, and None otherwise - fn eval_path_scalar(&self, path: &[&str]) -> InterpResult<'tcx, Scalar> { + /// Evaluates the scalar at the specified path. + fn eval_path_scalar(&self, path: &[&str]) -> Scalar { let this = self.eval_context_ref(); let instance = this.resolve_path(path, Namespace::ValueNS); let cid = GlobalId { instance, promoted: None }; // We don't give a span -- this isn't actually used directly by the program anyway. - let const_val = this.eval_global(cid, None)?; + let const_val = this + .eval_global(cid, None) + .unwrap_or_else(|err| panic!("failed to evaluate required Rust item: {path:?}\n{err}")); this.read_scalar(&const_val.into()) + .unwrap_or_else(|err| panic!("failed to read required Rust item: {path:?}\n{err}")) } /// Helper function to get a `libc` constant as a `Scalar`. - fn eval_libc(&self, name: &str) -> InterpResult<'tcx, Scalar> { + fn eval_libc(&self, name: &str) -> Scalar { self.eval_path_scalar(&["libc", name]) } /// Helper function to get a `libc` constant as an `i32`. - fn eval_libc_i32(&self, name: &str) -> InterpResult<'tcx, i32> { + fn eval_libc_i32(&self, name: &str) -> i32 { // TODO: Cache the result. - self.eval_libc(name)?.to_i32() + self.eval_libc(name).to_i32().unwrap_or_else(|_err| { + panic!("required libc item has unexpected type (not `i32`): {name}") + }) + } + + /// Helper function to get a `libc` constant as an `u32`. + fn eval_libc_u32(&self, name: &str) -> u32 { + // TODO: Cache the result. + self.eval_libc(name).to_u32().unwrap_or_else(|_err| { + panic!("required libc item has unexpected type (not `u32`): {name}") + }) } /// Helper function to get a `windows` constant as a `Scalar`. - fn eval_windows(&self, module: &str, name: &str) -> InterpResult<'tcx, Scalar> { + fn eval_windows(&self, module: &str, name: &str) -> Scalar { self.eval_context_ref().eval_path_scalar(&["std", "sys", "windows", module, name]) } + /// Helper function to get a `windows` constant as a `u32`. + fn eval_windows_u32(&self, module: &str, name: &str) -> u32 { + // TODO: Cache the result. + self.eval_windows(module, name).to_u32().unwrap_or_else(|_err| { + panic!("required Windows item has unexpected type (not `u32`): {module}::{name}") + }) + } + /// Helper function to get a `windows` constant as a `u64`. - fn eval_windows_u64(&self, module: &str, name: &str) -> InterpResult<'tcx, u64> { + fn eval_windows_u64(&self, module: &str, name: &str) -> u64 { // TODO: Cache the result. - self.eval_windows(module, name)?.to_u64() + self.eval_windows(module, name).to_u64().unwrap_or_else(|_err| { + panic!("required Windows item has unexpected type (not `u64`): {module}::{name}") + }) } /// Helper function to get the `TyAndLayout` of a `libc` type - fn libc_ty_layout(&self, name: &str) -> InterpResult<'tcx, TyAndLayout<'tcx>> { + fn libc_ty_layout(&self, name: &str) -> TyAndLayout<'tcx> { let this = self.eval_context_ref(); let ty = this .resolve_path(&["libc", name], Namespace::TypeNS) .ty(*this.tcx, ty::ParamEnv::reveal_all()); - this.layout_of(ty) + this.layout_of(ty).unwrap() } /// Helper function to get the `TyAndLayout` of a `windows` type - fn windows_ty_layout(&self, name: &str) -> InterpResult<'tcx, TyAndLayout<'tcx>> { + fn windows_ty_layout(&self, name: &str) -> TyAndLayout<'tcx> { let this = self.eval_context_ref(); let ty = this .resolve_path(&["std", "sys", "windows", "c", name], Namespace::TypeNS) .ty(*this.tcx, ty::ParamEnv::reveal_all()); - this.layout_of(ty) + this.layout_of(ty).unwrap() } /// Project to the given *named* field of the mplace (which must be a struct or union type). @@ -609,14 +631,14 @@ fn io_error_to_errnum( if target.families.iter().any(|f| f == "unix") { for &(name, kind) in UNIX_IO_ERROR_TABLE { if err_kind == kind { - return this.eval_libc(name); + return Ok(this.eval_libc(name)); } } throw_unsup_format!("io error {:?} cannot be translated into a raw os error", err_kind) } else if target.families.iter().any(|f| f == "windows") { // FIXME: we have to finish implementing the Windows equivalent of this. use std::io::ErrorKind::*; - this.eval_windows( + Ok(this.eval_windows( "c", match err_kind { NotFound => "ERROR_FILE_NOT_FOUND", @@ -627,7 +649,7 @@ fn io_error_to_errnum( err_kind ), }, - ) + )) } else { throw_unsup_format!( "converting io::Error into errnum is unsupported for OS {}", @@ -647,7 +669,7 @@ fn try_errnum_to_io_error( 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)? { + if errnum == this.eval_libc_i32(name) { return Ok(Some(kind)); } } diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs index 80fb4ff2fe9..054162a4ea9 100644 --- a/src/tools/miri/src/shims/env.rs +++ b/src/tools/miri/src/shims/env.rs @@ -170,7 +170,7 @@ fn GetEnvironmentVariableW( )) } None => { - let envvar_not_found = this.eval_windows("c", "ERROR_ENVVAR_NOT_FOUND")?; + let envvar_not_found = this.eval_windows("c", "ERROR_ENVVAR_NOT_FOUND"); this.set_last_error(envvar_not_found)?; Scalar::from_u32(0) // return zero upon failure } @@ -240,7 +240,7 @@ fn setenv( Ok(0) // return zero on success } else { // name argument is a null pointer, points to an empty string, or points to a string containing an '=' character. - let einval = this.eval_libc("EINVAL")?; + let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; Ok(-1) } @@ -274,7 +274,7 @@ fn SetEnvironmentVariableW( this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?; this.update_environ()?; } - Ok(this.eval_windows("c", "TRUE")?) + Ok(this.eval_windows("c", "TRUE")) } else { let value = this.read_os_str_from_wide_str(value_ptr)?; let var_ptr = alloc_env_var_as_wide_str(&name, &value, this)?; @@ -282,7 +282,7 @@ fn SetEnvironmentVariableW( this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?; } this.update_environ()?; - Ok(this.eval_windows("c", "TRUE")?) + Ok(this.eval_windows("c", "TRUE")) } } @@ -306,7 +306,7 @@ fn unsetenv(&mut self, name_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i Ok(0) } else { // name argument is a null pointer, points to an empty string, or points to a string containing an '=' character. - let einval = this.eval_libc("EINVAL")?; + let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; Ok(-1) } @@ -335,7 +335,7 @@ fn getcwd( if this.write_path_to_c_str(&cwd, buf, size)?.0 { return Ok(buf); } - let erange = this.eval_libc("ERANGE")?; + let erange = this.eval_libc("ERANGE"); this.set_last_error(erange)?; } Err(e) => this.set_last_error_from_io_error(e.kind())?, @@ -411,14 +411,14 @@ fn SetCurrentDirectoryW( this.reject_in_isolation("`SetCurrentDirectoryW`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?; - return this.eval_windows("c", "FALSE"); + return Ok(this.eval_windows("c", "FALSE")); } match env::set_current_dir(path) { - Ok(()) => this.eval_windows("c", "TRUE"), + Ok(()) => Ok(this.eval_windows("c", "TRUE")), Err(e) => { this.set_last_error_from_io_error(e.kind())?; - this.eval_windows("c", "FALSE") + Ok(this.eval_windows("c", "FALSE")) } } } diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index d263aab351b..ef411eb8aa7 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -36,26 +36,26 @@ fn clock_gettime( // 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_i32("CLOCK_REALTIME"), + this.eval_libc_i32("CLOCK_REALTIME_COARSE"), ]; // 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 additonal 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_i32("CLOCK_MONOTONIC"), + this.eval_libc_i32("CLOCK_MONOTONIC_COARSE"), ]; } "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_i32("CLOCK_REALTIME")]; + relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")]; // Some clocks only seem to exist in the aarch64 version of the target. if this.tcx.sess.target.arch == "aarch64" { // `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_i32("CLOCK_UPTIME_RAW")); } } target => throw_unsup_format!("`clock_gettime` is not supported on target OS {target}"), @@ -68,7 +68,7 @@ fn clock_gettime( this.machine.clock.now().duration_since(this.machine.clock.anchor()) } else { // Unsupported clock. - let einval = this.eval_libc("EINVAL")?; + let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; return Ok(Scalar::from_i32(-1)); }; @@ -94,7 +94,7 @@ fn gettimeofday( // Using tz is obsolete and should always be null let tz = this.read_pointer(tz_op)?; if !this.ptr_is_null(tz)? { - let einval = this.eval_libc("EINVAL")?; + let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; return Ok(-1); } @@ -118,9 +118,9 @@ fn GetSystemTimeAsFileTime( this.assert_target_os("windows", "GetSystemTimeAsFileTime"); this.check_no_isolation("`GetSystemTimeAsFileTime`")?; - let NANOS_PER_SEC = this.eval_windows_u64("time", "NANOS_PER_SEC")?; - let INTERVALS_PER_SEC = this.eval_windows_u64("time", "INTERVALS_PER_SEC")?; - let INTERVALS_TO_UNIX_EPOCH = this.eval_windows_u64("time", "INTERVALS_TO_UNIX_EPOCH")?; + let NANOS_PER_SEC = this.eval_windows_u64("time", "NANOS_PER_SEC"); + let INTERVALS_PER_SEC = this.eval_windows_u64("time", "INTERVALS_PER_SEC"); + let INTERVALS_TO_UNIX_EPOCH = this.eval_windows_u64("time", "INTERVALS_TO_UNIX_EPOCH"); let NANOS_PER_INTERVAL = NANOS_PER_SEC / INTERVALS_PER_SEC; let SECONDS_TO_UNIX_EPOCH = INTERVALS_TO_UNIX_EPOCH / INTERVALS_PER_SEC; @@ -226,7 +226,7 @@ fn nanosleep( let duration = match this.read_timespec(&this.deref_operand(req_op)?)? { Some(duration) => duration, None => { - let einval = this.eval_libc("EINVAL")?; + let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; return Ok(-1); } diff --git a/src/tools/miri/src/shims/tls.rs b/src/tools/miri/src/shims/tls.rs index 54fdf2872ab..7768772338a 100644 --- a/src/tools/miri/src/shims/tls.rs +++ b/src/tools/miri/src/shims/tls.rs @@ -303,12 +303,12 @@ fn schedule_windows_tls_dtors(&mut self) -> InterpResult<'tcx> { return Ok(()); } let thread_callback = - this.eval_windows("thread_local_key", "p_thread_callback")?.to_pointer(this)?; + this.eval_windows("thread_local_key", "p_thread_callback").to_pointer(this)?; let thread_callback = this.get_ptr_fn(thread_callback)?.as_instance()?; // FIXME: Technically, the reason should be `DLL_PROCESS_DETACH` when the main thread exits // but std treats both the same. - let reason = this.eval_windows("c", "DLL_THREAD_DETACH")?; + let reason = this.eval_windows("c", "DLL_THREAD_DETACH"); // The signature of this function is `unsafe extern "system" fn(h: c::LPVOID, dwReason: c::DWORD, pv: c::LPVOID)`. // FIXME: `h` should be a handle to the current module and what `pv` should be is unknown diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index e851d6d5139..f155e11241b 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -196,7 +196,7 @@ fn emulate_foreign_item_by_name( // Align must be power of 2, and also at least ptr-sized (POSIX rules). // But failure to adhere to this is not UB, it's an error condition. if !align.is_power_of_two() || align < this.pointer_size().bytes() { - let einval = this.eval_libc_i32("EINVAL")?; + let einval = this.eval_libc_i32("EINVAL"); this.write_int(einval, dest)?; } else { if size == 0 { @@ -243,7 +243,7 @@ fn emulate_foreign_item_by_name( ]; let mut result = None; for &(sysconf_name, value) in sysconfs { - let sysconf_name = this.eval_libc_i32(sysconf_name)?; + let sysconf_name = this.eval_libc_i32(sysconf_name); if sysconf_name == name { result = Some(value(this)); break; @@ -480,7 +480,7 @@ fn emulate_foreign_item_by_name( None => format!(""), }; let (complete, _) = this.write_os_str_to_c_str(OsStr::new(&formatted), buf, buflen)?; - let ret = if complete { 0 } else { this.eval_libc_i32("ERANGE")? }; + let ret = if complete { 0 } else { this.eval_libc_i32("ERANGE") }; this.write_int(ret, dest)?; } "getpid" => { @@ -495,7 +495,7 @@ fn emulate_foreign_item_by_name( if this.frame_in_std() => { let [_attr, guard_size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let guard_size = this.deref_operand(guard_size)?; - let guard_size_layout = this.libc_ty_layout("size_t")?; + let guard_size_layout = this.libc_ty_layout("size_t"); this.write_scalar(Scalar::from_uint(this.machine.page_size, guard_size_layout.size), &guard_size.into())?; // Return success (`0`). @@ -589,7 +589,7 @@ fn emulate_foreign_item_by_name( this.write_null(dest)?; } else { this.write_null(&result.into())?; - this.write_scalar(this.eval_libc("ERANGE")?, dest)?; + this.write_scalar(this.eval_libc("ERANGE"), dest)?; } } diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 0a26657f57c..22fbd940e71 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -382,7 +382,7 @@ fn macos_stat_write_buf( /// types (like `read`, that returns an `i64`). fn handle_not_found>(&mut self) -> InterpResult<'tcx, T> { let this = self.eval_context_mut(); - let ebadf = this.eval_libc("EBADF")?; + let ebadf = this.eval_libc("EBADF"); this.set_last_error(ebadf)?; Ok((-1).into()) } @@ -395,11 +395,11 @@ fn file_type_to_d_type( match file_type { Ok(file_type) => { if file_type.is_dir() { - Ok(this.eval_libc("DT_DIR")?.to_u8()?.into()) + Ok(this.eval_libc("DT_DIR").to_u8()?.into()) } else if file_type.is_file() { - Ok(this.eval_libc("DT_REG")?.to_u8()?.into()) + Ok(this.eval_libc("DT_REG").to_u8()?.into()) } else if file_type.is_symlink() { - Ok(this.eval_libc("DT_LNK")?.to_u8()?.into()) + Ok(this.eval_libc("DT_LNK").to_u8()?.into()) } else { // Certain file types are only supported when the host is a Unix system. // (i.e. devices and sockets) If it is, check those cases, if not, fall back to @@ -409,19 +409,19 @@ fn file_type_to_d_type( { use std::os::unix::fs::FileTypeExt; if file_type.is_block_device() { - Ok(this.eval_libc("DT_BLK")?.to_u8()?.into()) + Ok(this.eval_libc("DT_BLK").to_u8()?.into()) } else if file_type.is_char_device() { - Ok(this.eval_libc("DT_CHR")?.to_u8()?.into()) + Ok(this.eval_libc("DT_CHR").to_u8()?.into()) } else if file_type.is_fifo() { - Ok(this.eval_libc("DT_FIFO")?.to_u8()?.into()) + Ok(this.eval_libc("DT_FIFO").to_u8()?.into()) } else if file_type.is_socket() { - Ok(this.eval_libc("DT_SOCK")?.to_u8()?.into()) + Ok(this.eval_libc("DT_SOCK").to_u8()?.into()) } else { - Ok(this.eval_libc("DT_UNKNOWN")?.to_u8()?.into()) + Ok(this.eval_libc("DT_UNKNOWN").to_u8()?.into()) } } #[cfg(not(unix))] - Ok(this.eval_libc("DT_UNKNOWN")?.to_u8()?.into()) + Ok(this.eval_libc("DT_UNKNOWN").to_u8()?.into()) } } Err(e) => @@ -532,9 +532,9 @@ fn open(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> { let mut options = OpenOptions::new(); - let o_rdonly = this.eval_libc_i32("O_RDONLY")?; - let o_wronly = this.eval_libc_i32("O_WRONLY")?; - let o_rdwr = this.eval_libc_i32("O_RDWR")?; + let o_rdonly = this.eval_libc_i32("O_RDONLY"); + let o_wronly = this.eval_libc_i32("O_WRONLY"); + let o_rdwr = this.eval_libc_i32("O_RDWR"); // The first two bits of the flag correspond to the access mode in linux, macOS and // windows. We need to check that in fact the access mode flags for the current target // only use these two bits, otherwise we are in an unsupported target and should error. @@ -561,17 +561,17 @@ fn open(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> { // options. let mut mirror = access_mode; - let o_append = this.eval_libc_i32("O_APPEND")?; + let o_append = this.eval_libc_i32("O_APPEND"); if flag & o_append == o_append { options.append(true); mirror |= o_append; } - let o_trunc = this.eval_libc_i32("O_TRUNC")?; + let o_trunc = this.eval_libc_i32("O_TRUNC"); if flag & o_trunc == o_trunc { options.truncate(true); mirror |= o_trunc; } - let o_creat = this.eval_libc_i32("O_CREAT")?; + let o_creat = this.eval_libc_i32("O_CREAT"); if flag & o_creat == o_creat { // Get the mode. On macOS, the argument type `mode_t` is actually `u16`, but // C integer promotion rules mean that on the ABI level, it gets passed as `u32` @@ -591,7 +591,7 @@ fn open(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> { mirror |= o_creat; - let o_excl = this.eval_libc_i32("O_EXCL")?; + let o_excl = this.eval_libc_i32("O_EXCL"); if flag & o_excl == o_excl { mirror |= o_excl; options.create_new(true); @@ -599,17 +599,17 @@ fn open(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> { options.create(true); } } - let o_cloexec = this.eval_libc_i32("O_CLOEXEC")?; + let o_cloexec = this.eval_libc_i32("O_CLOEXEC"); if flag & o_cloexec == o_cloexec { // We do not need to do anything for this flag because `std` already sets it. // (Technically we do not support *not* setting this flag, but we ignore that.) mirror |= o_cloexec; } if this.tcx.sess.target.os == "linux" { - let o_tmpfile = this.eval_libc_i32("O_TMPFILE")?; + let o_tmpfile = this.eval_libc_i32("O_TMPFILE"); if flag & o_tmpfile == o_tmpfile { // if the flag contains `O_TMPFILE` then we return a graceful error - let eopnotsupp = this.eval_libc("EOPNOTSUPP")?; + let eopnotsupp = this.eval_libc("EOPNOTSUPP"); this.set_last_error(eopnotsupp)?; return Ok(-1); } @@ -657,18 +657,18 @@ fn fcntl(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> } // We only support getting the flags for a descriptor. - if cmd == this.eval_libc_i32("F_GETFD")? { + if cmd == this.eval_libc_i32("F_GETFD") { // Currently this is the only flag that `F_GETFD` returns. It is OK to just return the // `FD_CLOEXEC` value without checking if the flag is set for the file because `std` // always sets this flag when opening a file. However we still need to check that the // file itself is open. if this.machine.file_handler.handles.contains_key(&fd) { - Ok(this.eval_libc_i32("FD_CLOEXEC")?) + Ok(this.eval_libc_i32("FD_CLOEXEC")) } else { this.handle_not_found() } - } else if cmd == this.eval_libc_i32("F_DUPFD")? - || cmd == this.eval_libc_i32("F_DUPFD_CLOEXEC")? + } else if cmd == this.eval_libc_i32("F_DUPFD") + || cmd == this.eval_libc_i32("F_DUPFD_CLOEXEC") { // Note that we always assume the FD_CLOEXEC flag is set for every open file, in part // because exec() isn't supported. The F_DUPFD and F_DUPFD_CLOEXEC commands only @@ -697,7 +697,7 @@ fn fcntl(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> } None => this.handle_not_found(), } - } else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC")? { + } else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC") { if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) { // FIXME: Support fullfsync for all FDs let FileHandle { file, writable } = file_descriptor.as_file_handle()?; @@ -830,14 +830,14 @@ fn lseek64( let offset = this.read_scalar(offset_op)?.to_i64()?; let whence = this.read_scalar(whence_op)?.to_i32()?; - let seek_from = if whence == this.eval_libc_i32("SEEK_SET")? { + let seek_from = if whence == this.eval_libc_i32("SEEK_SET") { SeekFrom::Start(u64::try_from(offset).unwrap()) - } else if whence == this.eval_libc_i32("SEEK_CUR")? { + } else if whence == this.eval_libc_i32("SEEK_CUR") { SeekFrom::Current(offset) - } else if whence == this.eval_libc_i32("SEEK_END")? { + } else if whence == this.eval_libc_i32("SEEK_END") { SeekFrom::End(offset) } else { - let einval = this.eval_libc("EINVAL")?; + let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; return Ok(Scalar::from_i64(-1)); }; @@ -916,7 +916,7 @@ fn macos_stat( // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`stat`", reject_with)?; - let eacc = this.eval_libc("EACCES")?; + let eacc = this.eval_libc("EACCES"); this.set_last_error(eacc)?; return Ok(Scalar::from_i32(-1)); } @@ -945,7 +945,7 @@ fn macos_lstat( // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`lstat`", reject_with)?; - let eacc = this.eval_libc("EACCES")?; + let eacc = this.eval_libc("EACCES"); this.set_last_error(eacc)?; return Ok(Scalar::from_i32(-1)); } @@ -1003,7 +1003,7 @@ fn linux_statx( // If the statxbuf or pathname pointers are null, the function fails with `EFAULT`. if this.ptr_is_null(statxbuf_ptr)? || this.ptr_is_null(pathname_ptr)? { - let efault = this.eval_libc("EFAULT")?; + let efault = this.eval_libc("EFAULT"); this.set_last_error(efault)?; return Ok(-1); } @@ -1014,13 +1014,13 @@ fn linux_statx( // as `isize`s instead of having the proper types. Thus, we have to recover the layout of // `statxbuf_op` by using the `libc::statx` struct type. let statxbuf = { - let statx_layout = this.libc_ty_layout("statx")?; + let statx_layout = this.libc_ty_layout("statx"); MPlaceTy::from_aligned_ptr(statxbuf_ptr, statx_layout) }; let path = this.read_path_from_c_str(pathname_ptr)?.into_owned(); // See for a discussion of argument sizes. - let at_ampty_path = this.eval_libc_i32("AT_EMPTY_PATH")?; + let at_ampty_path = this.eval_libc_i32("AT_EMPTY_PATH"); let empty_path_flag = flags & at_ampty_path == at_ampty_path; // We only support: // * interpreting `path` as an absolute directory, @@ -1030,7 +1030,7 @@ fn linux_statx( // Other behaviors cannot be tested from `libstd` and thus are not implemented. If you // found this error, please open an issue reporting it. if !(path.is_absolute() - || dirfd == this.eval_libc_i32("AT_FDCWD")? + || dirfd == this.eval_libc_i32("AT_FDCWD") || (path.as_os_str().is_empty() && empty_path_flag)) { throw_unsup_format!( @@ -1043,16 +1043,16 @@ fn linux_statx( // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`statx`", reject_with)?; - let ecode = if path.is_absolute() || dirfd == this.eval_libc_i32("AT_FDCWD")? { + let ecode = if path.is_absolute() || dirfd == this.eval_libc_i32("AT_FDCWD") { // since `path` is provided, either absolute or // relative to CWD, `EACCES` is the most relevant. - this.eval_libc("EACCES")? + this.eval_libc("EACCES") } else { // `dirfd` is set to target file, and `path` is empty // (or we would have hit the `throw_unsup_format` // above). `EACCES` would violate the spec. assert!(empty_path_flag); - this.eval_libc("EBADF")? + this.eval_libc("EBADF") }; this.set_last_error(ecode)?; return Ok(-1); @@ -1062,12 +1062,11 @@ fn linux_statx( // However `statx` is allowed to return information that was not requested or to not // return information that was requested. This `mask` represents the information we can // actually provide for any target. - let mut mask = - this.eval_libc("STATX_TYPE")?.to_u32()? | this.eval_libc("STATX_SIZE")?.to_u32()?; + let mut mask = this.eval_libc_u32("STATX_TYPE") | this.eval_libc_u32("STATX_SIZE"); // If the `AT_SYMLINK_NOFOLLOW` flag is set, we query the file's metadata without following // symbolic links. - let follow_symlink = flags & this.eval_libc("AT_SYMLINK_NOFOLLOW")?.to_i32()? == 0; + let follow_symlink = flags & this.eval_libc_i32("AT_SYMLINK_NOFOLLOW") == 0; // If the path is empty, and the AT_EMPTY_PATH flag is set, we query the open file // represented by dirfd, whether it's a directory or otherwise. @@ -1096,7 +1095,7 @@ fn linux_statx( let (access_sec, access_nsec) = metadata .accessed .map(|tup| { - mask |= this.eval_libc("STATX_ATIME")?.to_u32()?; + mask |= this.eval_libc_u32("STATX_ATIME"); InterpResult::Ok(tup) }) .unwrap_or_else(|| Ok((0, 0)))?; @@ -1104,7 +1103,7 @@ fn linux_statx( let (created_sec, created_nsec) = metadata .created .map(|tup| { - mask |= this.eval_libc("STATX_BTIME")?.to_u32()?; + mask |= this.eval_libc_u32("STATX_BTIME"); InterpResult::Ok(tup) }) .unwrap_or_else(|| Ok((0, 0)))?; @@ -1112,7 +1111,7 @@ fn linux_statx( let (modified_sec, modified_nsec) = metadata .modified .map(|tup| { - mask |= this.eval_libc("STATX_MTIME")?.to_u32()?; + mask |= this.eval_libc_u32("STATX_MTIME"); InterpResult::Ok(tup) }) .unwrap_or_else(|| Ok((0, 0)))?; @@ -1185,7 +1184,7 @@ fn rename( let newpath_ptr = this.read_pointer(newpath_op)?; if this.ptr_is_null(oldpath_ptr)? || this.ptr_is_null(newpath_ptr)? { - let efault = this.eval_libc("EFAULT")?; + let efault = this.eval_libc("EFAULT"); this.set_last_error(efault)?; return Ok(-1); } @@ -1272,7 +1271,7 @@ fn opendir( // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`opendir`", reject_with)?; - let eacc = this.eval_libc("EACCES")?; + let eacc = this.eval_libc("EACCES"); this.set_last_error(eacc)?; return Ok(Scalar::null_ptr(this)); } @@ -1308,7 +1307,7 @@ fn linux_readdir64( // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`readdir`", reject_with)?; - let eacc = this.eval_libc("EBADF")?; + let eacc = this.eval_libc("EBADF"); this.set_last_error(eacc)?; return Ok(Scalar::null_ptr(this)); } @@ -1337,7 +1336,7 @@ fn linux_readdir64( let name_bytes = os_str_to_bytes(&name)?; let name_len = u64::try_from(name_bytes.len()).unwrap(); - let dirent64_layout = this.libc_ty_layout("dirent64")?; + let dirent64_layout = this.libc_ty_layout("dirent64"); let d_name_offset = dirent64_layout.fields.offset(4 /* d_name */).bytes(); let size = d_name_offset.checked_add(name_len).unwrap(); @@ -1532,13 +1531,13 @@ fn ftruncate64( let result = file.set_len(length); this.try_unwrap_io_result(result.map(|_| 0i32))? } else { - let einval = this.eval_libc("EINVAL")?; + let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; -1 } } else { // The file is not writable - let einval = this.eval_libc("EINVAL")?; + let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; -1 } @@ -1612,15 +1611,15 @@ fn sync_file_range( let flags = this.read_scalar(flags_op)?.to_i32()?; if offset < 0 || nbytes < 0 { - let einval = this.eval_libc("EINVAL")?; + let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; return Ok(Scalar::from_i32(-1)); } - let allowed_flags = this.eval_libc_i32("SYNC_FILE_RANGE_WAIT_BEFORE")? - | this.eval_libc_i32("SYNC_FILE_RANGE_WRITE")? - | this.eval_libc_i32("SYNC_FILE_RANGE_WAIT_AFTER")?; + let allowed_flags = this.eval_libc_i32("SYNC_FILE_RANGE_WAIT_BEFORE") + | this.eval_libc_i32("SYNC_FILE_RANGE_WRITE") + | this.eval_libc_i32("SYNC_FILE_RANGE_WAIT_AFTER"); if flags & allowed_flags != flags { - let einval = this.eval_libc("EINVAL")?; + let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; return Ok(Scalar::from_i32(-1)); } @@ -1657,7 +1656,7 @@ fn readlink( // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`readlink`", reject_with)?; - let eacc = this.eval_libc("EACCES")?; + let eacc = this.eval_libc("EACCES"); this.set_last_error(eacc)?; return Ok(-1); } @@ -1702,7 +1701,7 @@ fn isatty( } } // Fallback when the FD was not found or isolation is enabled. - let enotty = this.eval_libc("ENOTTY")?; + let enotty = this.eval_libc("ENOTTY"); this.set_last_error(enotty)?; Ok(Scalar::from_i32(0)) } @@ -1721,7 +1720,7 @@ fn realpath( // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`realpath`", reject_with)?; - let eacc = this.eval_libc("EACCES")?; + let eacc = this.eval_libc("EACCES"); this.set_last_error(eacc)?; return Ok(Scalar::from_machine_usize(0, this)); } @@ -1730,7 +1729,7 @@ fn realpath( match result { Ok(resolved) => { let path_max = this - .eval_libc_i32("PATH_MAX")? + .eval_libc_i32("PATH_MAX") .try_into() .expect("PATH_MAX does not fit in u64"); let dest = if this.ptr_is_null(processed_ptr)? { @@ -1752,7 +1751,7 @@ fn realpath( // Note that we do not explicitly handle `FILENAME_MAX` // (different from `PATH_MAX` above) as it is Linux-specific and // seems like a bit of a mess anyway: . - let enametoolong = this.eval_libc("ENAMETOOLONG")?; + let enametoolong = this.eval_libc("ENAMETOOLONG"); this.set_last_error(enametoolong)?; return Ok(Scalar::from_machine_usize(0, this)); } @@ -1785,7 +1784,7 @@ fn mkstemp(&mut self, template_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx // * The value of `TMP_MAX` is at least 25. // * On XSI-conformant systems, the value of `TMP_MAX` is at least 10000. // See . - let max_attempts = this.eval_libc("TMP_MAX")?.to_u32()?; + let max_attempts = this.eval_libc_u32("TMP_MAX"); // Get the raw bytes from the template -- as a byte slice, this is a string in the target // (and the target is unix, so a byte slice is the right representation). @@ -1796,7 +1795,7 @@ fn mkstemp(&mut self, template_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`mkstemp`", reject_with)?; - let eacc = this.eval_libc("EACCES")?; + let eacc = this.eval_libc("EACCES"); this.set_last_error(eacc)?; return Ok(-1); } @@ -1814,7 +1813,7 @@ fn mkstemp(&mut self, template_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx // If we don't find the suffix, it is an error. if last_six_char_bytes != suffix_bytes { - let einval = this.eval_libc("EINVAL")?; + let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; return Ok(-1); } @@ -1890,7 +1889,7 @@ fn mkstemp(&mut self, template_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx } // We ran out of attempts to create the file, return an error. - let eexist = this.eval_libc("EEXIST")?; + let eexist = this.eval_libc("EEXIST"); this.set_last_error(eexist)?; Ok(-1) } @@ -1968,7 +1967,7 @@ fn from_meta<'tcx>( "S_IFLNK" }; - let mode = ecx.eval_libc(mode_name)?; + let mode = ecx.eval_libc(mode_name); let size = metadata.len(); diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 34076e842d5..ff7b2b352f2 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -88,11 +88,11 @@ fn emulate_foreign_item_by_name( // argument, we have to also check all arguments *before* it to ensure that they // have the right type. - let sys_getrandom = this.eval_libc("SYS_getrandom")?.to_machine_usize(this)?; + let sys_getrandom = this.eval_libc("SYS_getrandom").to_machine_usize(this)?; - let sys_statx = this.eval_libc("SYS_statx")?.to_machine_usize(this)?; + let sys_statx = this.eval_libc("SYS_statx").to_machine_usize(this)?; - let sys_futex = this.eval_libc("SYS_futex")?.to_machine_usize(this)?; + let sys_futex = this.eval_libc("SYS_futex").to_machine_usize(this)?; if args.is_empty() { throw_ub_format!( @@ -150,7 +150,7 @@ fn emulate_foreign_item_by_name( this.read_scalar(cpusetsize)?.to_machine_usize(this)?; this.deref_operand(mask)?; // FIXME: we just return an error; `num_cpus` then falls back to `sysconf`. - let einval = this.eval_libc("EINVAL")?; + let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; this.write_scalar(Scalar::from_i32(-1), dest)?; } diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs index 31461e4c9fd..ef43c9b0ff4 100644 --- a/src/tools/miri/src/shims/unix/linux/sync.rs +++ b/src/tools/miri/src/shims/unix/linux/sync.rs @@ -37,12 +37,12 @@ pub fn futex<'tcx>( let addr = MPlaceTy::from_aligned_ptr(addr, this.machine.layouts.i32); let addr_usize = addr.ptr.addr().bytes(); - let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG")?; - let futex_wait = this.eval_libc_i32("FUTEX_WAIT")?; - let futex_wait_bitset = this.eval_libc_i32("FUTEX_WAIT_BITSET")?; - let futex_wake = this.eval_libc_i32("FUTEX_WAKE")?; - let futex_wake_bitset = this.eval_libc_i32("FUTEX_WAKE_BITSET")?; - let futex_realtime = this.eval_libc_i32("FUTEX_CLOCK_REALTIME")?; + let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG"); + let futex_wait = this.eval_libc_i32("FUTEX_WAIT"); + let futex_wait_bitset = this.eval_libc_i32("FUTEX_WAIT_BITSET"); + let futex_wake = this.eval_libc_i32("FUTEX_WAKE"); + let futex_wake_bitset = this.eval_libc_i32("FUTEX_WAKE_BITSET"); + let futex_realtime = this.eval_libc_i32("FUTEX_CLOCK_REALTIME"); // FUTEX_PRIVATE enables an optimization that stops it from working across processes. // Miri doesn't support that anyway, so we ignore that flag. @@ -79,7 +79,7 @@ pub fn futex<'tcx>( }; if bitset == 0 { - let einval = this.eval_libc("EINVAL")?; + let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?; return Ok(()); @@ -99,7 +99,7 @@ pub fn futex<'tcx>( let duration = match this.read_timespec(&timeout)? { Some(duration) => duration, None => { - let einval = this.eval_libc("EINVAL")?; + let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?; return Ok(()); @@ -194,7 +194,7 @@ impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for Callback<'tcx> { fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { this.unblock_thread(self.thread); this.futex_remove_waiter(self.addr_usize, self.thread); - let etimedout = this.eval_libc("ETIMEDOUT")?; + let etimedout = this.eval_libc("ETIMEDOUT"); this.set_last_error(etimedout)?; this.write_scalar(Scalar::from_machine_isize(-1, this), &self.dest)?; @@ -211,7 +211,7 @@ fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { } else { // The futex value doesn't match the expected value, so we return failure // right away without sleeping: -1 and errno set to EAGAIN. - let eagain = this.eval_libc("EAGAIN")?; + let eagain = this.eval_libc("EAGAIN"); this.set_last_error(eagain)?; this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?; } @@ -237,7 +237,7 @@ fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { u32::MAX }; if bitset == 0 { - let einval = this.eval_libc("EINVAL")?; + let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?; return Ok(()); diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 282bfc8024f..d616126cb2a 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -176,7 +176,7 @@ fn emulate_foreign_item_by_name( "pthread_setname_np" => { let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let thread = this.pthread_self()?; - let max_len = this.eval_libc("MAXTHREADNAMESIZE")?.to_machine_usize(this)?; + let max_len = this.eval_libc("MAXTHREADNAMESIZE").to_machine_usize(this)?; let res = this.pthread_setname_np( thread, this.read_scalar(name)?, diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index f9b5774f009..b3c474dd3c9 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -21,14 +21,14 @@ fn is_mutex_kind_default<'mir, 'tcx: 'mir>( ecx: &mut MiriInterpCx<'mir, 'tcx>, kind: i32, ) -> InterpResult<'tcx, bool> { - Ok(kind == ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?) + Ok(kind == ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")) } fn is_mutex_kind_normal<'mir, 'tcx: 'mir>( ecx: &mut MiriInterpCx<'mir, 'tcx>, kind: i32, ) -> InterpResult<'tcx, bool> { - let mutex_normal_kind = ecx.eval_libc_i32("PTHREAD_MUTEX_NORMAL")?; + let mutex_normal_kind = ecx.eval_libc_i32("PTHREAD_MUTEX_NORMAL"); Ok(kind == (mutex_normal_kind | PTHREAD_MUTEX_NORMAL_FLAG)) } @@ -217,7 +217,7 @@ fn pthread_mutexattr_init( ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); - let default_kind = this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?; + let default_kind = this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"); mutexattr_set_kind(this, attr_op, default_kind)?; Ok(0) @@ -231,7 +231,7 @@ fn pthread_mutexattr_settype( let this = self.eval_context_mut(); let kind = this.read_scalar(kind_op)?.to_i32()?; - if kind == this.eval_libc_i32("PTHREAD_MUTEX_NORMAL")? { + if kind == this.eval_libc_i32("PTHREAD_MUTEX_NORMAL") { // In `glibc` implementation, the numeric values of // `PTHREAD_MUTEX_NORMAL` and `PTHREAD_MUTEX_DEFAULT` are equal. // However, a mutex created by explicitly passing @@ -247,17 +247,17 @@ fn pthread_mutexattr_settype( let normal_kind = kind | PTHREAD_MUTEX_NORMAL_FLAG; // Check that after setting the flag, the kind is distinguishable // from all other kinds. - assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?); - assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")?); - assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")?); + assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")); + assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")); + assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")); mutexattr_set_kind(this, attr_op, normal_kind)?; - } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")? - || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")? - || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")? + } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT") + || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") + || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") { mutexattr_set_kind(this, attr_op, kind)?; } else { - let einval = this.eval_libc_i32("EINVAL")?; + let einval = this.eval_libc_i32("EINVAL"); return Ok(einval); } @@ -299,7 +299,7 @@ fn pthread_mutex_init( let attr = this.read_pointer(attr_op)?; let kind = if this.ptr_is_null(attr)? { - this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")? + this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT") } else { mutexattr_get_kind(this, attr_op)? }; @@ -331,9 +331,9 @@ fn pthread_mutex_lock(&mut self, mutex_op: &OpTy<'tcx, Provenance>) -> InterpRes throw_ub_format!("trying to acquire already locked default mutex"); } else if is_mutex_kind_normal(this, kind)? { throw_machine_stop!(TerminationInfo::Deadlock); - } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")? { - this.eval_libc_i32("EDEADLK") - } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")? { + } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") { + Ok(this.eval_libc_i32("EDEADLK")) + } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") { this.mutex_lock(id, active_thread); Ok(0) } else { @@ -362,14 +362,14 @@ fn pthread_mutex_trylock( if this.mutex_is_locked(id) { let owner_thread = this.mutex_get_owner(id); if owner_thread != active_thread { - this.eval_libc_i32("EBUSY") + Ok(this.eval_libc_i32("EBUSY")) } else { if is_mutex_kind_default(this, kind)? || is_mutex_kind_normal(this, kind)? - || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")? + || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") { - this.eval_libc_i32("EBUSY") - } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")? { + Ok(this.eval_libc_i32("EBUSY")) + } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") { this.mutex_lock(id, active_thread); Ok(0) } else { @@ -410,10 +410,10 @@ fn pthread_mutex_unlock( throw_ub_format!( "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread" ); - } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")? - || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")? + } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") + || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") { - this.eval_libc_i32("EPERM") + Ok(this.eval_libc_i32("EPERM")) } else { throw_unsup_format!("called pthread_mutex_unlock on an unsupported type of mutex"); } @@ -471,7 +471,7 @@ fn pthread_rwlock_tryrdlock( let active_thread = this.get_active_thread(); if this.rwlock_is_write_locked(id) { - this.eval_libc_i32("EBUSY") + Ok(this.eval_libc_i32("EBUSY")) } else { this.rwlock_reader_lock(id, active_thread); Ok(0) @@ -518,7 +518,7 @@ fn pthread_rwlock_trywrlock( let active_thread = this.get_active_thread(); if this.rwlock_is_locked(id) { - this.eval_libc_i32("EBUSY") + Ok(this.eval_libc_i32("EBUSY")) } else { this.rwlock_writer_lock(id, active_thread); Ok(0) @@ -575,7 +575,7 @@ fn pthread_condattr_init( // The default value of the clock attribute shall refer to the system // clock. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_condattr_setclock.html - let default_clock_id = this.eval_libc_i32("CLOCK_REALTIME")?; + let default_clock_id = this.eval_libc_i32("CLOCK_REALTIME"); condattr_set_clock_id(this, attr_op, default_clock_id)?; Ok(0) @@ -589,12 +589,12 @@ fn pthread_condattr_setclock( let this = self.eval_context_mut(); let clock_id = this.read_scalar(clock_id_op)?.to_i32()?; - if clock_id == this.eval_libc_i32("CLOCK_REALTIME")? - || clock_id == this.eval_libc_i32("CLOCK_MONOTONIC")? + if clock_id == this.eval_libc_i32("CLOCK_REALTIME") + || clock_id == this.eval_libc_i32("CLOCK_MONOTONIC") { condattr_set_clock_id(this, attr_op, clock_id)?; } else { - let einval = this.eval_libc_i32("EINVAL")?; + let einval = this.eval_libc_i32("EINVAL"); return Ok(Scalar::from_i32(einval)); } @@ -638,7 +638,7 @@ fn pthread_cond_init( let attr = this.read_pointer(attr_op)?; let clock_id = if this.ptr_is_null(attr)? { - this.eval_libc_i32("CLOCK_REALTIME")? + this.eval_libc_i32("CLOCK_REALTIME") } else { condattr_get_clock_id(this, attr_op)? }; @@ -718,16 +718,16 @@ fn pthread_cond_timedwait( let duration = match this.read_timespec(&this.deref_operand(abstime_op)?)? { Some(duration) => duration, None => { - let einval = this.eval_libc("EINVAL")?; + let einval = this.eval_libc("EINVAL"); this.write_scalar(einval, dest)?; return Ok(()); } }; - let timeout_time = if clock_id == this.eval_libc_i32("CLOCK_REALTIME")? { + let timeout_time = if clock_id == this.eval_libc_i32("CLOCK_REALTIME") { this.check_no_isolation("`pthread_cond_timedwait` with `CLOCK_REALTIME`")?; Time::RealTime(SystemTime::UNIX_EPOCH.checked_add(duration).unwrap()) - } else if clock_id == this.eval_libc_i32("CLOCK_MONOTONIC")? { + } else if clock_id == this.eval_libc_i32("CLOCK_MONOTONIC") { Time::Monotonic(this.machine.clock.anchor().checked_add(duration).unwrap()) } else { throw_unsup_format!("unsupported clock id: {}", clock_id); @@ -763,7 +763,7 @@ fn call(&self, ecx: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { ecx.condvar_remove_waiter(self.id, self.active_thread); // Set the return value: we timed out. - let etimedout = ecx.eval_libc("ETIMEDOUT")?; + let etimedout = ecx.eval_libc("ETIMEDOUT"); ecx.write_scalar(etimedout, &self.dest)?; Ok(()) diff --git a/src/tools/miri/src/shims/unix/thread.rs b/src/tools/miri/src/shims/unix/thread.rs index 5b9dc90f0f0..4f7b028d35d 100644 --- a/src/tools/miri/src/shims/unix/thread.rs +++ b/src/tools/miri/src/shims/unix/thread.rs @@ -84,7 +84,7 @@ fn pthread_setname_np( // Comparing with `>=` to account for null terminator. if name.len() >= max_name_len { - return this.eval_libc("ERANGE"); + return Ok(this.eval_libc("ERANGE")); } this.set_thread_name(thread, name); @@ -107,7 +107,7 @@ fn pthread_getname_np( let name = this.get_thread_name(thread).to_owned(); let (success, _written) = this.write_c_str(&name, name_out, len)?; - if success { Ok(Scalar::from_u32(0)) } else { this.eval_libc("ERANGE") } + Ok(if success { Scalar::from_u32(0) } else { this.eval_libc("ERANGE") }) } fn sched_yield(&mut self) -> InterpResult<'tcx, i32> { diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs index 6b043c6d2c9..61cb3b382b3 100644 --- a/src/tools/miri/src/shims/windows/sync.rs +++ b/src/tools/miri/src/shims/windows/sync.rs @@ -170,7 +170,7 @@ fn InitOnceBeginInitialize( match this.init_once_status(id) { InitOnceStatus::Uninitialized => { this.init_once_begin(id); - this.write_scalar(this.eval_windows("c", "TRUE")?, &pending_place)?; + this.write_scalar(this.eval_windows("c", "TRUE"), &pending_place)?; } InitOnceStatus::Begun => { // Someone else is already on it. @@ -195,8 +195,8 @@ fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { unreachable!( "status should have either been set to begun or complete" ), - InitOnceStatus::Begun => this.eval_windows("c", "TRUE")?, - InitOnceStatus::Complete => this.eval_windows("c", "FALSE")?, + InitOnceStatus::Begun => this.eval_windows("c", "TRUE"), + InitOnceStatus::Complete => this.eval_windows("c", "FALSE"), }; this.write_scalar(pending, &self.pending_place)?; @@ -213,12 +213,12 @@ fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { } InitOnceStatus::Complete => { this.init_once_observe_completed(id); - this.write_scalar(this.eval_windows("c", "FALSE")?, &pending_place)?; + this.write_scalar(this.eval_windows("c", "FALSE"), &pending_place)?; } } // This always succeeds (even if the thread is blocked, we will succeed if we ever unblock). - this.eval_windows("c", "TRUE") + Ok(this.eval_windows("c", "TRUE")) } fn InitOnceComplete( @@ -235,7 +235,7 @@ fn InitOnceComplete( let success = if flags == 0 { true - } else if flags == this.eval_windows("c", "INIT_ONCE_INIT_FAILED")?.to_u32()? { + } else if flags == this.eval_windows_u32("c", "INIT_ONCE_INIT_FAILED") { false } else { throw_unsup_format!("unsupported `dwFlags` {flags} in `InitOnceBeginInitialize`"); @@ -258,7 +258,7 @@ fn InitOnceComplete( this.init_once_fail(id)?; } - this.eval_windows("c", "TRUE") + Ok(this.eval_windows("c", "TRUE")) } fn WaitOnAddress( @@ -280,14 +280,14 @@ fn WaitOnAddress( let addr = ptr.addr().bytes(); if size > 8 || !size.is_power_of_two() { - let invalid_param = this.eval_windows("c", "ERROR_INVALID_PARAMETER")?; + let invalid_param = this.eval_windows("c", "ERROR_INVALID_PARAMETER"); this.set_last_error(invalid_param)?; this.write_scalar(Scalar::from_i32(0), dest)?; return Ok(()); }; let size = Size::from_bytes(size); - let timeout_time = if timeout_ms == this.eval_windows("c", "INFINITE")?.to_u32()? { + let timeout_time = if timeout_ms == this.eval_windows_u32("c", "INFINITE") { None } else { let duration = Duration::from_millis(timeout_ms.into()); @@ -325,7 +325,7 @@ impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for Callback<'tcx> { fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { this.unblock_thread(self.thread); this.futex_remove_waiter(self.addr, self.thread); - let error_timeout = this.eval_windows("c", "ERROR_TIMEOUT")?; + let error_timeout = this.eval_windows("c", "ERROR_TIMEOUT"); this.set_last_error(error_timeout)?; this.write_scalar(Scalar::from_i32(0), &self.dest)?; @@ -377,7 +377,7 @@ fn SleepConditionVariableSRW( let timeout_ms = this.read_scalar(timeout_op)?.to_u32()?; let flags = this.read_scalar(flags_op)?.to_u32()?; - let timeout_time = if timeout_ms == this.eval_windows("c", "INFINITE")?.to_u32()? { + let timeout_time = if timeout_ms == this.eval_windows_u32("c", "INFINITE") { None } else { let duration = Duration::from_millis(timeout_ms.into()); @@ -431,9 +431,9 @@ fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { this.condvar_remove_waiter(self.condvar_id, self.thread); - let error_timeout = this.eval_windows("c", "ERROR_TIMEOUT")?; + let error_timeout = this.eval_windows("c", "ERROR_TIMEOUT"); this.set_last_error(error_timeout)?; - this.write_scalar(this.eval_windows("c", "FALSE")?, &self.dest)?; + this.write_scalar(this.eval_windows("c", "FALSE"), &self.dest)?; Ok(()) } } @@ -451,7 +451,7 @@ fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { ); } - this.eval_windows("c", "TRUE") + Ok(this.eval_windows("c", "TRUE")) } fn WakeConditionVariable(&mut self, condvar_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> { diff --git a/src/tools/miri/src/shims/windows/thread.rs b/src/tools/miri/src/shims/windows/thread.rs index 25a5194caa0..c3a450db48d 100644 --- a/src/tools/miri/src/shims/windows/thread.rs +++ b/src/tools/miri/src/shims/windows/thread.rs @@ -34,7 +34,7 @@ fn CreateThread( }; let stack_size_param_is_a_reservation = - this.eval_windows("c", "STACK_SIZE_PARAM_IS_A_RESERVATION")?.to_u32()?; + this.eval_windows_u32("c", "STACK_SIZE_PARAM_IS_A_RESERVATION"); // We ignore the stack size, so we also ignore the // `STACK_SIZE_PARAM_IS_A_RESERVATION` flag. @@ -73,7 +73,7 @@ fn WaitForSingleObject( _ => this.invalid_handle("WaitForSingleObject")?, }; - if timeout != this.eval_windows("c", "INFINITE")?.to_u32()? { + if timeout != this.eval_windows_u32("c", "INFINITE") { throw_unsup_format!("`WaitForSingleObject` with non-infinite timeout"); } -- 2.44.0