.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<Provenance>> {
+ /// Evaluates the scalar at the specified path.
+ fn eval_path_scalar(&self, path: &[&str]) -> Scalar<Provenance> {
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<Provenance>> {
+ fn eval_libc(&self, name: &str) -> Scalar<Provenance> {
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<Provenance>> {
+ fn eval_windows(&self, module: &str, name: &str) -> Scalar<Provenance> {
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).
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",
err_kind
),
},
- )
+ ))
} else {
throw_unsup_format!(
"converting io::Error into errnum is unsupported for OS {}",
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));
}
}
))
}
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
}
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)
}
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)?;
this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?;
}
this.update_environ()?;
- Ok(this.eval_windows("c", "TRUE")?)
+ Ok(this.eval_windows("c", "TRUE"))
}
}
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)
}
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())?,
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"))
}
}
}
// 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}"),
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));
};
// 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);
}
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;
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);
}
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
// 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 {
];
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;
None => format!("<unknown errnum in strerror_r: {errnum}>"),
};
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" => {
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`).
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)?;
}
}
/// types (like `read`, that returns an `i64`).
fn handle_not_found<T: From<i32>>(&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())
}
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
{
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) =>
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.
// 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`
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);
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);
}
}
// 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
}
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()?;
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));
};
// 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));
}
// 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));
}
// 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);
}
// 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 <https://github.com/rust-lang/rust/pull/79196> 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,
// 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!(
// 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);
// 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.
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)))?;
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)))?;
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)))?;
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);
}
// 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));
}
// 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));
}
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();
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
}
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));
}
// 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);
}
}
}
// 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))
}
// 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));
}
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)? {
// 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: <https://eklitzke.org/path-max-is-tricky>.
- 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));
}
// * The value of `TMP_MAX` is at least 25.
// * On XSI-conformant systems, the value of `TMP_MAX` is at least 10000.
// See <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdio.h.html>.
- 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).
// 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);
}
// 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);
}
}
// 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)
}
"S_IFLNK"
};
- let mode = ecx.eval_libc(mode_name)?;
+ let mode = ecx.eval_libc(mode_name);
let size = metadata.len();
// 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!(
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)?;
}
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.
};
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(());
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(());
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)?;
} 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)?;
}
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(());
"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)?,
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))
}
) -> 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)
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
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);
}
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)?
};
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 {
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 {
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");
}
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)
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)
// 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)
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));
}
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)?
};
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);
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(())
// 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);
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> {
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.
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)?;
}
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(
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`");
this.init_once_fail(id)?;
}
- this.eval_windows("c", "TRUE")
+ Ok(this.eval_windows("c", "TRUE"))
}
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());
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)?;
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());
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(())
}
}
);
}
- this.eval_windows("c", "TRUE")
+ Ok(this.eval_windows("c", "TRUE"))
}
fn WakeConditionVariable(&mut self, condvar_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
};
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.
_ => 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");
}