From 04e46e138bf00adeb1a9f2008ad19e7cda619329 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 30 Jul 2024 13:18:16 +0000 Subject: [PATCH] Use Scalar consistently in foreign item emulation --- src/shims/time.rs | 16 +-- src/shims/unix/env.rs | 40 ++++--- src/shims/unix/fd.rs | 47 +++++---- src/shims/unix/foreign_items.rs | 146 +++++++++++++------------- src/shims/unix/fs.rs | 101 +++++++++--------- src/shims/unix/linux/foreign_items.rs | 8 +- src/shims/unix/sync.rs | 94 ++++++++--------- src/shims/unix/thread.rs | 20 ++-- src/shims/windows/env.rs | 4 +- src/shims/windows/foreign_items.rs | 8 +- 10 files changed, 239 insertions(+), 245 deletions(-) diff --git a/src/shims/time.rs b/src/shims/time.rs index e8f906d37e..ebec1a70c5 100644 --- a/src/shims/time.rs +++ b/src/shims/time.rs @@ -93,7 +93,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(Scalar::from_i32(0)) } - fn gettimeofday(&mut self, tv_op: &OpTy<'tcx>, tz_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn gettimeofday( + &mut self, + tv_op: &OpTy<'tcx>, + tz_op: &OpTy<'tcx>, + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.assert_target_os_is_unix("gettimeofday"); @@ -106,7 +110,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if !this.ptr_is_null(tz)? { let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } let duration = system_time_to_duration(&SystemTime::now())?; @@ -115,7 +119,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_int_fields(&[tv_sec.into(), tv_usec.into()], &tv)?; - Ok(0) + Ok(Scalar::from_i32(0)) } // The localtime() function shall convert the time in seconds since the Epoch pointed to by @@ -308,7 +312,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &mut self, req_op: &OpTy<'tcx>, _rem: &OpTy<'tcx>, // Signal handlers are not supported, so rem will never be written to. - ) -> InterpResult<'tcx, i32> { + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.assert_target_os_is_unix("nanosleep"); @@ -320,7 +324,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { None => { let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } }; @@ -333,7 +337,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { @timeout = |_this| { Ok(()) } ), ); - Ok(0) + Ok(Scalar::from_i32(0)) } #[allow(non_snake_case)] diff --git a/src/shims/unix/env.rs b/src/shims/unix/env.rs index 3b8ad65195..ac9933ea70 100644 --- a/src/shims/unix/env.rs +++ b/src/shims/unix/env.rs @@ -148,7 +148,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(var_ptr.unwrap_or_else(Pointer::null)) } - fn setenv(&mut self, name_op: &OpTy<'tcx>, value_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn setenv( + &mut self, + name_op: &OpTy<'tcx>, + value_op: &OpTy<'tcx>, + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.assert_target_os_is_unix("setenv"); @@ -169,16 +173,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?; } this.update_environ()?; - Ok(0) // return zero on success + Ok(Scalar::from_i32(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"); this.set_last_error(einval)?; - Ok(-1) + Ok(Scalar::from_i32(-1)) } } - fn unsetenv(&mut self, name_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn unsetenv(&mut self, name_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.assert_target_os_is_unix("unsetenv"); @@ -195,12 +199,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?; } this.update_environ()?; - Ok(0) + Ok(Scalar::from_i32(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"); this.set_last_error(einval)?; - Ok(-1) + Ok(Scalar::from_i32(-1)) } } @@ -232,7 +236,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(Pointer::null()) } - fn chdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn chdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.assert_target_os_is_unix("chdir"); @@ -242,16 +246,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.reject_in_isolation("`chdir`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } - match env::set_current_dir(path) { - Ok(()) => Ok(0), - Err(e) => { - this.set_last_error_from_io_error(e)?; - Ok(-1) - } - } + let result = env::set_current_dir(path).map(|()| 0); + Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } /// Updates the `environ` static. @@ -270,18 +269,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(()) } - fn getpid(&mut self) -> InterpResult<'tcx, i32> { + fn getpid(&mut self) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.assert_target_os_is_unix("getpid"); // The reason we need to do this wacky of a conversion is because // `libc::getpid` returns an i32, however, `std::process::id()` return an u32. // So we un-do the conversion that stdlib does and turn it back into an i32. - #[allow(clippy::cast_possible_wrap)] - Ok(this.get_pid() as i32) + // In `Scalar` representation, these are the same, so we don't need to anything else. + Ok(Scalar::from_u32(this.get_pid())) } - fn linux_gettid(&mut self) -> InterpResult<'tcx, i32> { + fn linux_gettid(&mut self) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_ref(); this.assert_target_os("linux", "gettid"); @@ -290,7 +289,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Compute a TID for this thread, ensuring that the main thread has PID == TID. let tid = this.get_pid().strict_add(index); - #[allow(clippy::cast_possible_wrap)] - Ok(tid as i32) + Ok(Scalar::from_u32(tid)) } } diff --git a/src/shims/unix/fd.rs b/src/shims/unix/fd.rs index ada5592f61..74e690a5f1 100644 --- a/src/shims/unix/fd.rs +++ b/src/shims/unix/fd.rs @@ -310,20 +310,20 @@ impl FdTable { impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - fn dup(&mut self, old_fd: i32) -> InterpResult<'tcx, i32> { + fn dup(&mut self, old_fd: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let Some(dup_fd) = this.machine.fds.dup(old_fd) else { - return this.fd_not_found(); + return Ok(Scalar::from_i32(this.fd_not_found()?)); }; - Ok(this.machine.fds.insert_fd_with_min_fd(dup_fd, 0)) + Ok(Scalar::from_i32(this.machine.fds.insert_fd_with_min_fd(dup_fd, 0))) } - fn dup2(&mut self, old_fd: i32, new_fd: i32) -> InterpResult<'tcx, i32> { + fn dup2(&mut self, old_fd: i32, new_fd: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let Some(dup_fd) = this.machine.fds.dup(old_fd) else { - return this.fd_not_found(); + return Ok(Scalar::from_i32(this.fd_not_found()?)); }; if new_fd != old_fd { // Close new_fd if it is previously opened. @@ -333,7 +333,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { file_description.close(this.machine.communicate())?.ok(); } } - Ok(new_fd) + Ok(Scalar::from_i32(new_fd)) } fn flock(&mut self, fd: i32, op: i32) -> InterpResult<'tcx, Scalar> { @@ -370,7 +370,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } - fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, i32> { + fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); if args.len() < 2 { @@ -388,11 +388,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `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.fds.is_fd(fd) { - Ok(this.eval_libc_i32("FD_CLOEXEC")) + Ok(Scalar::from_i32(if this.machine.fds.is_fd(fd) { + this.eval_libc_i32("FD_CLOEXEC") } else { - this.fd_not_found() - } + this.fd_not_found()? + })) } else if cmd == this.eval_libc_i32("F_DUPFD") || cmd == this.eval_libc_i32("F_DUPFD_CLOEXEC") { @@ -409,15 +409,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let start = this.read_scalar(&args[2])?.to_i32()?; match this.machine.fds.dup(fd) { - Some(dup_fd) => Ok(this.machine.fds.insert_fd_with_min_fd(dup_fd, start)), - None => this.fd_not_found(), + Some(dup_fd) => + Ok(Scalar::from_i32(this.machine.fds.insert_fd_with_min_fd(dup_fd, start))), + None => Ok(Scalar::from_i32(this.fd_not_found()?)), } } else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC") { // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`fcntl`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } this.ffullsync_fd(fd) @@ -462,7 +463,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { buf: Pointer, count: u64, offset: Option, - ) -> InterpResult<'tcx, i64> { + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); // Isolation check is done via `FileDescriptor` trait. @@ -482,7 +483,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // We temporarily dup the FD to be able to retain mutable access to `this`. let Some(fd) = this.machine.fds.dup(fd) else { trace!("read: FD not found"); - return this.fd_not_found(); + return Ok(Scalar::from_target_isize(this.fd_not_found()?, this)); }; trace!("read: FD mapped to {fd:?}"); @@ -496,7 +497,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let Ok(offset) = u64::try_from(offset) else { let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; - return Ok(-1); + return Ok(Scalar::from_target_isize(-1, this)); }; fd.borrow_mut().pread(communicate, &mut bytes, offset, this) } @@ -513,11 +514,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { buf, bytes[..usize::try_from(read_bytes).unwrap()].iter().copied(), )?; - Ok(read_bytes) + Ok(Scalar::from_target_isize(read_bytes, this)) } Err(e) => { this.set_last_error_from_io_error(e)?; - Ok(-1) + Ok(Scalar::from_target_isize(-1, this)) } } } @@ -528,7 +529,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { buf: Pointer, count: u64, offset: Option, - ) -> InterpResult<'tcx, i64> { + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); // Isolation check is done via `FileDescriptor` trait. @@ -546,7 +547,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let bytes = this.read_bytes_ptr_strip_provenance(buf, Size::from_bytes(count))?.to_owned(); // We temporarily dup the FD to be able to retain mutable access to `this`. let Some(fd) = this.machine.fds.dup(fd) else { - return this.fd_not_found(); + return Ok(Scalar::from_target_isize(this.fd_not_found()?, this)); }; let result = match offset { @@ -555,7 +556,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let Ok(offset) = u64::try_from(offset) else { let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; - return Ok(-1); + return Ok(Scalar::from_target_isize(-1, this)); }; fd.borrow_mut().pwrite(communicate, &bytes, offset, this) } @@ -563,7 +564,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { drop(fd); let result = result?.map(|c| i64::try_from(c).unwrap()); - this.try_unwrap_io_result(result) + Ok(Scalar::from_target_isize(this.try_unwrap_io_result(result)?, this)) } } diff --git a/src/shims/unix/foreign_items.rs b/src/shims/unix/foreign_items.rs index 17851e1aec..57930f9807 100644 --- a/src/shims/unix/foreign_items.rs +++ b/src/shims/unix/foreign_items.rs @@ -62,13 +62,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "unsetenv" => { let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.unsetenv(name)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "setenv" => { let [name, value, overwrite] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.read_scalar(overwrite)?.to_i32()?; let result = this.setenv(name, value)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "getcwd" => { let [buf, size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -78,12 +78,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "chdir" => { let [path] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.chdir(path)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "getpid" => { let [] = this.check_shim(abi, Abi::C { unwind: false}, link_name, args)?; let result = this.getpid()?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } // File descriptors @@ -93,7 +93,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let buf = this.read_pointer(buf)?; let count = this.read_target_usize(count)?; let result = this.read(fd, buf, count, None)?; - this.write_scalar(Scalar::from_target_isize(result, this), dest)?; + this.write_scalar(result, dest)?; } "write" => { let [fd, buf, n] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -103,7 +103,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { trace!("Called write({:?}, {:?}, {:?})", fd, buf, count); let result = this.write(fd, buf, count, None)?; // Now, `result` is the value we return back to the program. - this.write_scalar(Scalar::from_target_isize(result, this), dest)?; + this.write_scalar(result, dest)?; } "pread" => { let [fd, buf, count, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -112,7 +112,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let count = this.read_target_usize(count)?; let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; let result = this.read(fd, buf, count, Some(offset))?; - this.write_scalar(Scalar::from_target_isize(result, this), dest)?; + this.write_scalar(result, dest)?; } "pwrite" => { let [fd, buf, n, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -123,7 +123,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { trace!("Called pwrite({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset); let result = this.write(fd, buf, count, Some(offset))?; // Now, `result` is the value we return back to the program. - this.write_scalar(Scalar::from_target_isize(result, this), dest)?; + this.write_scalar(result, dest)?; } "pread64" => { let [fd, buf, count, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -132,7 +132,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let count = this.read_target_usize(count)?; let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?; let result = this.read(fd, buf, count, Some(offset))?; - this.write_scalar(Scalar::from_target_isize(result, this), dest)?; + this.write_scalar(result, dest)?; } "pwrite64" => { let [fd, buf, n, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -143,7 +143,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { trace!("Called pwrite64({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset); let result = this.write(fd, buf, count, Some(offset))?; // Now, `result` is the value we return back to the program. - this.write_scalar(Scalar::from_target_isize(result, this), dest)?; + this.write_scalar(result, dest)?; } "close" => { let [fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -155,20 +155,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // in `this.fcntl()`, so we do not use `check_shim` here. this.check_abi_and_shim_symbol_clash(abi, Abi::C { unwind: false }, link_name)?; let result = this.fcntl(args)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "dup" => { let [old_fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let old_fd = this.read_scalar(old_fd)?.to_i32()?; let new_fd = this.dup(old_fd)?; - this.write_scalar(Scalar::from_i32(new_fd), dest)?; + this.write_scalar(new_fd, dest)?; } "dup2" => { let [old_fd, new_fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let old_fd = this.read_scalar(old_fd)?.to_i32()?; let new_fd = this.read_scalar(new_fd)?.to_i32()?; let result = this.dup2(old_fd, new_fd)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "flock" => { let [fd, op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -183,32 +183,32 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `open` is variadic, the third argument is only present when the second argument has O_CREAT (or on linux O_TMPFILE, but miri doesn't support that) set this.check_abi_and_shim_symbol_clash(abi, Abi::C { unwind: false }, link_name)?; let result = this.open(args)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "unlink" => { let [path] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.unlink(path)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "symlink" => { let [target, linkpath] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.symlink(target, linkpath)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "rename" => { let [oldpath, newpath] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.rename(oldpath, newpath)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "mkdir" => { let [path, mode] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.mkdir(path, mode)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "rmdir" => { let [path] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.rmdir(path)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "opendir" => { let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -218,7 +218,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "closedir" => { let [dirp] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.closedir(dirp)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "lseek64" => { let [fd, offset, whence] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -255,12 +255,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "fsync" => { let [fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.fsync(fd)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "fdatasync" => { let [fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.fdatasync(fd)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "readlink" => { let [pathname, buf, bufsize] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -285,7 +285,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "mkstemp" => { let [template] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.mkstemp(template)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } // Sockets @@ -301,7 +301,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "gettimeofday" => { let [tv, tz] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.gettimeofday(tv, tz)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "localtime_r" => { let [timep, result_op] = this.check_shim(abi, Abi::C {unwind: false}, link_name, args)?; @@ -473,23 +473,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Synchronization primitives "pthread_mutexattr_init" => { let [attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_mutexattr_init(attr)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_mutexattr_init(attr)?; + this.write_null(dest)?; } "pthread_mutexattr_settype" => { let [attr, kind] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.pthread_mutexattr_settype(attr, kind)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "pthread_mutexattr_destroy" => { let [attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_mutexattr_destroy(attr)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_mutexattr_destroy(attr)?; + this.write_null(dest)?; } "pthread_mutex_init" => { let [mutex, attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_mutex_init(mutex, attr)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_mutex_init(mutex, attr)?; + this.write_null(dest)?; } "pthread_mutex_lock" => { let [mutex] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -498,17 +498,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "pthread_mutex_trylock" => { let [mutex] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.pthread_mutex_trylock(mutex)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "pthread_mutex_unlock" => { let [mutex] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.pthread_mutex_unlock(mutex)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "pthread_mutex_destroy" => { let [mutex] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_mutex_destroy(mutex)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_mutex_destroy(mutex)?; + this.write_int(0, dest)?; } "pthread_rwlock_rdlock" => { let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -517,7 +517,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "pthread_rwlock_tryrdlock" => { let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.pthread_rwlock_tryrdlock(rwlock)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "pthread_rwlock_wrlock" => { let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -526,22 +526,22 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "pthread_rwlock_trywrlock" => { let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.pthread_rwlock_trywrlock(rwlock)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "pthread_rwlock_unlock" => { let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_rwlock_unlock(rwlock)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_rwlock_unlock(rwlock)?; + this.write_null(dest)?; } "pthread_rwlock_destroy" => { let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_rwlock_destroy(rwlock)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_rwlock_destroy(rwlock)?; + this.write_null(dest)?; } "pthread_condattr_init" => { let [attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_condattr_init(attr)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_condattr_init(attr)?; + this.write_null(dest)?; } "pthread_condattr_setclock" => { let [attr, clock_id] = @@ -552,28 +552,28 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "pthread_condattr_getclock" => { let [attr, clock_id] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_condattr_getclock(attr, clock_id)?; - this.write_scalar(result, dest)?; + this.pthread_condattr_getclock(attr, clock_id)?; + this.write_null(dest)?; } "pthread_condattr_destroy" => { let [attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_condattr_destroy(attr)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_condattr_destroy(attr)?; + this.write_null(dest)?; } "pthread_cond_init" => { let [cond, attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_cond_init(cond, attr)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_cond_init(cond, attr)?; + this.write_null(dest)?; } "pthread_cond_signal" => { let [cond] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_cond_signal(cond)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_cond_signal(cond)?; + this.write_null(dest)?; } "pthread_cond_broadcast" => { let [cond] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_cond_broadcast(cond)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_cond_broadcast(cond)?; + this.write_null(dest)?; } "pthread_cond_wait" => { let [cond, mutex] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -585,25 +585,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "pthread_cond_destroy" => { let [cond] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_cond_destroy(cond)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_cond_destroy(cond)?; + this.write_null(dest)?; } // Threading "pthread_create" => { let [thread, attr, start, arg] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_create(thread, attr, start, arg)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_create(thread, attr, start, arg)?; + this.write_null(dest)?; } "pthread_join" => { let [thread, retval] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_join(thread, retval)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_join(thread, retval)?; + this.write_null(dest)?; } "pthread_detach" => { let [thread] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_detach(thread)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_detach(thread)?; + this.write_null(dest)?; } "pthread_self" => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -612,13 +612,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "sched_yield" => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.sched_yield()?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.sched_yield()?; + this.write_null(dest)?; } "nanosleep" => { let [req, rem] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.nanosleep(req, rem)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "sched_getaffinity" => { // Currently this function does not exist on all Unixes, e.g. on macOS. @@ -647,23 +647,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if this.ptr_is_null(mask)? { let einval = this.eval_libc("EFAULT"); this.set_last_error(einval)?; - this.write_scalar(Scalar::from_i32(-1), dest)?; + this.write_int(-1, dest)?; } else if cpusetsize == 0 || cpusetsize.checked_rem(chunk_size).unwrap() != 0 { // we only copy whole chunks of size_of::() let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; - this.write_scalar(Scalar::from_i32(-1), dest)?; + this.write_int(-1, dest)?; } else if let Some(cpuset) = this.machine.thread_cpu_affinity.get(&thread_id) { let cpuset = cpuset.clone(); // we only copy whole chunks of size_of::() let byte_count = Ord::min(cpuset.as_slice().len(), cpusetsize.try_into().unwrap()); this.write_bytes_ptr(mask, cpuset.as_slice()[..byte_count].iter().copied())?; - this.write_scalar(Scalar::from_i32(0), dest)?; + this.write_null(dest)?; } else { // The thread whose ID is pid could not be found let einval = this.eval_libc("ESRCH"); this.set_last_error(einval)?; - this.write_scalar(Scalar::from_i32(-1), dest)?; + this.write_int(-1, dest)?; } } "sched_setaffinity" => { @@ -690,7 +690,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if this.ptr_is_null(mask)? { let einval = this.eval_libc("EFAULT"); this.set_last_error(einval)?; - this.write_scalar(Scalar::from_i32(-1), dest)?; + this.write_int(-1, dest)?; } else { // NOTE: cpusetsize might be smaller than `CpuAffinityMask::CPU_MASK_BYTES`. // Any unspecified bytes are treated as zero here (none of the CPUs are configured). @@ -702,13 +702,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match CpuAffinityMask::from_array(this, this.machine.num_cpus, bits_array) { Some(cpuset) => { this.machine.thread_cpu_affinity.insert(thread_id, cpuset); - this.write_scalar(Scalar::from_i32(0), dest)?; + this.write_null(dest)?; } None => { // The intersection between the mask and the available CPUs was empty. let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; - this.write_scalar(Scalar::from_i32(-1), dest)?; + this.write_int(-1, dest)?; } } } @@ -766,10 +766,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if bufsize > 256 { let err = this.eval_libc("EIO"); this.set_last_error(err)?; - this.write_scalar(Scalar::from_i32(-1), dest)?; + this.write_int(-1, dest)?; } else { this.gen_random(buf, bufsize)?; - this.write_scalar(Scalar::from_i32(0), dest)?; + this.write_null(dest)?; } } "getrandom" => { diff --git a/src/shims/unix/fs.rs b/src/shims/unix/fs.rs index 38ef3f13b4..7891b65a9d 100644 --- a/src/shims/unix/fs.rs +++ b/src/shims/unix/fs.rs @@ -395,7 +395,7 @@ fn maybe_sync_file( impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - fn open(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, i32> { + fn open(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> { if args.len() < 2 { throw_ub_format!( "incorrect number of arguments for `open`: got {}, expected at least 2", @@ -503,7 +503,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // if the flag contains `O_TMPFILE` then we return a graceful error let eopnotsupp = this.eval_libc("EOPNOTSUPP"); this.set_last_error(eopnotsupp)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } } @@ -524,7 +524,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if path.is_symlink() { let eloop = this.eval_libc("ELOOP"); this.set_last_error(eloop)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } } mirror |= o_nofollow; @@ -540,14 +540,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`open`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } let fd = options .open(path) .map(|file| this.machine.fds.insert_fd(FileHandle { file, writable })); - this.try_unwrap_io_result(fd) + Ok(Scalar::from_i32(this.try_unwrap_io_result(fd)?)) } fn lseek64(&mut self, fd: i32, offset: i128, whence: i32) -> InterpResult<'tcx, Scalar> { @@ -588,7 +588,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(Scalar::from_i64(result)) } - fn unlink(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn unlink(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?; @@ -597,18 +597,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`unlink`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } let result = remove_file(path).map(|_| 0); - this.try_unwrap_io_result(result) + Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } fn symlink( &mut self, target_op: &OpTy<'tcx>, linkpath_op: &OpTy<'tcx>, - ) -> InterpResult<'tcx, i32> { + ) -> InterpResult<'tcx, Scalar> { #[cfg(unix)] fn create_link(src: &Path, dst: &Path) -> std::io::Result<()> { std::os::unix::fs::symlink(src, dst) @@ -628,11 +628,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`symlink`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } let result = create_link(&target, &linkpath).map(|_| 0); - this.try_unwrap_io_result(result) + Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } fn macos_fbsd_stat( @@ -731,7 +731,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { flags_op: &OpTy<'tcx>, // Should be an `int` mask_op: &OpTy<'tcx>, // Should be an `unsigned int` statxbuf_op: &OpTy<'tcx>, // Should be a `struct statx *` - ) -> InterpResult<'tcx, i32> { + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.assert_target_os("linux", "statx"); @@ -746,7 +746,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if this.ptr_is_null(statxbuf_ptr)? || this.ptr_is_null(pathname_ptr)? { let efault = this.eval_libc("EFAULT"); this.set_last_error(efault)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } let statxbuf = this.deref_pointer_as(statxbuf_op, this.libc_ty_layout("statx"))?; @@ -788,7 +788,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.eval_libc("EBADF") }; this.set_last_error(ecode)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } // the `_mask_op` parameter specifies the file information that the caller requested. @@ -810,7 +810,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { }; let metadata = match metadata { Some(metadata) => metadata, - None => return Ok(-1), + None => return Ok(Scalar::from_i32(-1)), }; // The `mode` field specifies the type of the file and the permissions over the file for @@ -903,14 +903,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &this.project_field_named(&statxbuf, "stx_mtime")?, )?; - Ok(0) + Ok(Scalar::from_i32(0)) } fn rename( &mut self, oldpath_op: &OpTy<'tcx>, newpath_op: &OpTy<'tcx>, - ) -> InterpResult<'tcx, i32> { + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let oldpath_ptr = this.read_pointer(oldpath_op)?; @@ -919,7 +919,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if this.ptr_is_null(oldpath_ptr)? || this.ptr_is_null(newpath_ptr)? { let efault = this.eval_libc("EFAULT"); this.set_last_error(efault)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } let oldpath = this.read_path_from_c_str(oldpath_ptr)?; @@ -929,15 +929,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`rename`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } let result = rename(oldpath, newpath).map(|_| 0); - this.try_unwrap_io_result(result) + Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } - fn mkdir(&mut self, path_op: &OpTy<'tcx>, mode_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn mkdir(&mut self, path_op: &OpTy<'tcx>, mode_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); #[cfg_attr(not(unix), allow(unused_variables))] @@ -953,7 +953,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`mkdir`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } #[cfg_attr(not(unix), allow(unused_mut))] @@ -969,10 +969,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let result = builder.create(path).map(|_| 0i32); - this.try_unwrap_io_result(result) + Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } - fn rmdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn rmdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?; @@ -981,12 +981,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`rmdir`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } let result = remove_dir(path).map(|_| 0i32); - this.try_unwrap_io_result(result) + Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } fn opendir(&mut self, name_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { @@ -1236,27 +1236,24 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { })) } - fn closedir(&mut self, dirp_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn closedir(&mut self, dirp_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let dirp = this.read_target_usize(dirp_op)?; // Reject if isolation is enabled. - if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { + Ok(Scalar::from_i32(if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`closedir`", reject_with)?; - // Set error code as "EBADF" (bad fd) - return this.fd_not_found(); - } - - if let Some(open_dir) = this.machine.dirs.streams.remove(&dirp) { + this.fd_not_found()? + } else if let Some(open_dir) = this.machine.dirs.streams.remove(&dirp) { if let Some(entry) = open_dir.entry { this.deallocate_ptr(entry, None, MiriMemoryKind::Runtime.into())?; } drop(open_dir); - Ok(0) + 0 } else { - this.fd_not_found() - } + this.fd_not_found()? + })) } fn ftruncate64(&mut self, fd: i32, length: i128) -> InterpResult<'tcx, Scalar> { @@ -1300,7 +1297,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } - fn fsync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn fsync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { // On macOS, `fsync` (unlike `fcntl(F_FULLFSYNC)`) does not wait for the // underlying disk to finish writing. In the interest of host compatibility, // we conservatively implement this with `sync_all`, which @@ -1314,16 +1311,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`fsync`", reject_with)?; // Set error code as "EBADF" (bad fd) - return this.fd_not_found(); + return Ok(Scalar::from_i32(this.fd_not_found()?)); } - return self.ffullsync_fd(fd); + self.ffullsync_fd(fd) } - fn ffullsync_fd(&mut self, fd: i32) -> InterpResult<'tcx, i32> { + fn ffullsync_fd(&mut self, fd: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let Some(file_description) = this.machine.fds.get(fd) else { - return Ok(this.fd_not_found()?); + return Ok(Scalar::from_i32(this.fd_not_found()?)); }; // Only regular files support synchronization. let FileHandle { file, writable } = @@ -1332,10 +1329,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { })?; let io_result = maybe_sync_file(file, *writable, File::sync_all); drop(file_description); - this.try_unwrap_io_result(io_result) + Ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?)) } - fn fdatasync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn fdatasync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let fd = this.read_scalar(fd_op)?.to_i32()?; @@ -1344,11 +1341,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`fdatasync`", reject_with)?; // Set error code as "EBADF" (bad fd) - return this.fd_not_found(); + return Ok(Scalar::from_i32(this.fd_not_found()?)); } let Some(file_description) = this.machine.fds.get(fd) else { - return Ok(this.fd_not_found()?); + return Ok(Scalar::from_i32(this.fd_not_found()?)); }; // Only regular files support synchronization. let FileHandle { file, writable } = @@ -1357,7 +1354,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { })?; let io_result = maybe_sync_file(file, *writable, File::sync_data); drop(file_description); - this.try_unwrap_io_result(io_result) + Ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?)) } fn sync_file_range( @@ -1534,7 +1531,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } } - fn mkstemp(&mut self, template_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn mkstemp(&mut self, template_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { use rand::seq::SliceRandom; // POSIX defines the template string. @@ -1565,7 +1562,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.reject_in_isolation("`mkstemp`", reject_with)?; let eacc = this.eval_libc("EACCES"); this.set_last_error(eacc)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } // Get the bytes of the suffix we expect in _target_ encoding. @@ -1583,7 +1580,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if last_six_char_bytes != suffix_bytes { let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } // At this point we know we have 6 ASCII 'X' characters as a suffix. @@ -1638,7 +1635,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match file { Ok(f) => { let fd = this.machine.fds.insert_fd(FileHandle { file: f, writable: true }); - return Ok(fd); + return Ok(Scalar::from_i32(fd)); } Err(e) => match e.kind() { @@ -1649,7 +1646,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // "On error, -1 is returned, and errno is set to // indicate the error" this.set_last_error_from_io_error(e)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } }, } @@ -1658,7 +1655,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // We ran out of attempts to create the file, return an error. let eexist = this.eval_libc("EEXIST"); this.set_last_error(eexist)?; - Ok(-1) + Ok(Scalar::from_i32(-1)) } } diff --git a/src/shims/unix/linux/foreign_items.rs b/src/shims/unix/linux/foreign_items.rs index 20c6a23479..581f0db42e 100644 --- a/src/shims/unix/linux/foreign_items.rs +++ b/src/shims/unix/linux/foreign_items.rs @@ -44,7 +44,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let [dirfd, pathname, flags, mask, statxbuf] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.linux_statx(dirfd, pathname, flags, mask, statxbuf)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } // epoll, eventfd @@ -97,7 +97,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "gettid" => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.linux_gettid()?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } // Dynamically invoked syscalls @@ -176,12 +176,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "__libc_current_sigrtmin" => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - this.write_scalar(Scalar::from_i32(SIGRTMIN), dest)?; + this.write_int(SIGRTMIN, dest)?; } "__libc_current_sigrtmax" => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - this.write_scalar(Scalar::from_i32(SIGRTMAX), dest)?; + this.write_int(SIGRTMAX, dest)?; } // Incomplete shims that we "stub out" just to get pre-main initialization code to work. diff --git a/src/shims/unix/sync.rs b/src/shims/unix/sync.rs index e8653117ae..0b889b1182 100644 --- a/src/shims/unix/sync.rs +++ b/src/shims/unix/sync.rs @@ -363,20 +363,20 @@ fn cond_set_clock_id<'tcx>( impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - fn pthread_mutexattr_init(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_mutexattr_init(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let default_kind = this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"); mutexattr_set_kind(this, attr_op, default_kind)?; - Ok(0) + Ok(()) } fn pthread_mutexattr_settype( &mut self, attr_op: &OpTy<'tcx>, kind_op: &OpTy<'tcx>, - ) -> InterpResult<'tcx, i32> { + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let kind = this.read_scalar(kind_op)?.to_i32()?; @@ -407,13 +407,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { mutexattr_set_kind(this, attr_op, kind)?; } else { let einval = this.eval_libc_i32("EINVAL"); - return Ok(einval); + return Ok(Scalar::from_i32(einval)); } - Ok(0) + Ok(Scalar::from_i32(0)) } - fn pthread_mutexattr_destroy(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_mutexattr_destroy(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); // Destroying an uninit pthread_mutexattr is UB, so check to make sure it's not uninit. @@ -435,14 +435,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &this.deref_pointer_as(attr_op, this.libc_ty_layout("pthread_mutexattr_t"))?, )?; - Ok(0) + Ok(()) } fn pthread_mutex_init( &mut self, mutex_op: &OpTy<'tcx>, attr_op: &OpTy<'tcx>, - ) -> InterpResult<'tcx, i32> { + ) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let attr = this.read_pointer(attr_op)?; @@ -457,7 +457,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { mutex_set_kind(this, mutex_op, kind)?; - Ok(0) + Ok(()) } fn pthread_mutex_lock( @@ -501,25 +501,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(()) } - fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let kind = mutex_get_kind(this, mutex_op)?; let id = mutex_get_id(this, mutex_op)?; - if this.mutex_is_locked(id) { + Ok(Scalar::from_i32(if this.mutex_is_locked(id) { let owner_thread = this.mutex_get_owner(id); if owner_thread != this.active_thread() { - Ok(this.eval_libc_i32("EBUSY")) + 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") { - Ok(this.eval_libc_i32("EBUSY")) + this.eval_libc_i32("EBUSY") } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") { this.mutex_lock(id); - Ok(0) + 0 } else { throw_unsup_format!( "called pthread_mutex_trylock on an unsupported type of mutex" @@ -529,11 +529,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } else { // The mutex is unlocked. Let's lock it. this.mutex_lock(id); - Ok(0) - } + 0 + })) } - fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let kind = mutex_get_kind(this, mutex_op)?; @@ -541,7 +541,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let Some(_old_locked_count) = this.mutex_unlock(id)? { // The mutex was locked by the current thread. - Ok(0) + Ok(Scalar::from_i32(0)) } else { // The mutex was locked by another thread or not locked at all. See // the “Unlock When Not Owner” column in @@ -557,14 +557,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") { - Ok(this.eval_libc_i32("EPERM")) + Ok(Scalar::from_i32(this.eval_libc_i32("EPERM"))) } else { throw_unsup_format!("called pthread_mutex_unlock on an unsupported type of mutex"); } } } - fn pthread_mutex_destroy(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_mutex_destroy(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let id = mutex_get_id(this, mutex_op)?; @@ -583,7 +583,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; // FIXME: delete interpreter state associated with this mutex. - Ok(0) + Ok(()) } fn pthread_rwlock_rdlock( @@ -605,16 +605,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(()) } - fn pthread_rwlock_tryrdlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_rwlock_tryrdlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let id = rwlock_get_id(this, rwlock_op)?; if this.rwlock_is_write_locked(id) { - Ok(this.eval_libc_i32("EBUSY")) + Ok(Scalar::from_i32(this.eval_libc_i32("EBUSY"))) } else { this.rwlock_reader_lock(id); - Ok(0) + Ok(Scalar::from_i32(0)) } } @@ -649,35 +649,33 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(()) } - fn pthread_rwlock_trywrlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_rwlock_trywrlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let id = rwlock_get_id(this, rwlock_op)?; if this.rwlock_is_locked(id) { - Ok(this.eval_libc_i32("EBUSY")) + Ok(Scalar::from_i32(this.eval_libc_i32("EBUSY"))) } else { this.rwlock_writer_lock(id); - Ok(0) + Ok(Scalar::from_i32(0)) } } - fn pthread_rwlock_unlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_rwlock_unlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let id = rwlock_get_id(this, rwlock_op)?; #[allow(clippy::if_same_then_else)] - if this.rwlock_reader_unlock(id)? { - Ok(0) - } else if this.rwlock_writer_unlock(id)? { - Ok(0) + if this.rwlock_reader_unlock(id)? || this.rwlock_writer_unlock(id)? { + Ok(()) } else { throw_ub_format!("unlocked an rwlock that was not locked by the active thread"); } } - fn pthread_rwlock_destroy(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_rwlock_destroy(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let id = rwlock_get_id(this, rwlock_op)?; @@ -695,10 +693,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; // FIXME: delete interpreter state associated with this rwlock. - Ok(0) + Ok(()) } - fn pthread_condattr_init(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_condattr_init(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); // no clock attribute on macOS @@ -710,7 +708,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { condattr_set_clock_id(this, attr_op, default_clock_id)?; } - Ok(0) + Ok(()) } fn pthread_condattr_setclock( @@ -737,16 +735,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &mut self, attr_op: &OpTy<'tcx>, clk_id_op: &OpTy<'tcx>, - ) -> InterpResult<'tcx, Scalar> { + ) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let clock_id = condattr_get_clock_id(this, attr_op)?; this.write_scalar(Scalar::from_i32(clock_id), &this.deref_pointer(clk_id_op)?)?; - Ok(Scalar::from_i32(0)) + Ok(()) } - fn pthread_condattr_destroy(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_condattr_destroy(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); // Destroying an uninit pthread_condattr is UB, so check to make sure it's not uninit. @@ -761,14 +759,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &this.deref_pointer_as(attr_op, this.libc_ty_layout("pthread_condattr_t"))?, )?; - Ok(0) + Ok(()) } fn pthread_cond_init( &mut self, cond_op: &OpTy<'tcx>, attr_op: &OpTy<'tcx>, - ) -> InterpResult<'tcx, i32> { + ) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let attr = this.read_pointer(attr_op)?; @@ -784,21 +782,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { cond_set_clock_id(this, cond_op, clock_id)?; - Ok(0) + Ok(()) } - fn pthread_cond_signal(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_cond_signal(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let id = cond_get_id(this, cond_op)?; this.condvar_signal(id)?; - Ok(0) + Ok(()) } - fn pthread_cond_broadcast(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_cond_broadcast(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let id = cond_get_id(this, cond_op)?; while this.condvar_signal(id)? {} - Ok(0) + Ok(()) } fn pthread_cond_wait( @@ -869,7 +867,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(()) } - fn pthread_cond_destroy(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_cond_destroy(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let id = cond_get_id(this, cond_op)?; @@ -885,6 +883,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_uninit(&this.deref_pointer_as(cond_op, this.libc_ty_layout("pthread_cond_t"))?)?; // FIXME: delete interpreter state associated with this condvar. - Ok(0) + Ok(()) } } diff --git a/src/shims/unix/thread.rs b/src/shims/unix/thread.rs index 6fe331ba62..83bb95c797 100644 --- a/src/shims/unix/thread.rs +++ b/src/shims/unix/thread.rs @@ -10,7 +10,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { _attr: &OpTy<'tcx>, start_routine: &OpTy<'tcx>, arg: &OpTy<'tcx>, - ) -> InterpResult<'tcx, i32> { + ) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let thread_info_place = this.deref_pointer_as(thread, this.libc_ty_layout("pthread_t"))?; @@ -27,14 +27,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.layout_of(this.tcx.types.usize)?, )?; - Ok(0) + Ok(()) } - fn pthread_join( - &mut self, - thread: &OpTy<'tcx>, - retval: &OpTy<'tcx>, - ) -> InterpResult<'tcx, i32> { + fn pthread_join(&mut self, thread: &OpTy<'tcx>, retval: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); if !this.ptr_is_null(this.read_pointer(retval)?)? { @@ -45,10 +41,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let thread_id = this.read_scalar(thread)?.to_int(this.libc_ty_layout("pthread_t").size)?; this.join_thread_exclusive(thread_id.try_into().expect("thread ID should fit in u32"))?; - Ok(0) + Ok(()) } - fn pthread_detach(&mut self, thread: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_detach(&mut self, thread: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let thread_id = this.read_scalar(thread)?.to_int(this.libc_ty_layout("pthread_t").size)?; @@ -57,7 +53,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /*allow_terminated_joined*/ false, )?; - Ok(0) + Ok(()) } fn pthread_self(&mut self) -> InterpResult<'tcx, Scalar> { @@ -113,11 +109,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(if success { Scalar::from_u32(0) } else { this.eval_libc("ERANGE") }) } - fn sched_yield(&mut self) -> InterpResult<'tcx, i32> { + fn sched_yield(&mut self) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); this.yield_active_thread(); - Ok(0) + Ok(()) } } diff --git a/src/shims/windows/env.rs b/src/shims/windows/env.rs index 77ae06bd5c..495df18a6e 100644 --- a/src/shims/windows/env.rs +++ b/src/shims/windows/env.rs @@ -197,11 +197,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } #[allow(non_snake_case)] - fn GetCurrentProcessId(&mut self) -> InterpResult<'tcx, u32> { + fn GetCurrentProcessId(&mut self) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.assert_target_os("windows", "GetCurrentProcessId"); - Ok(this.get_pid()) + Ok(Scalar::from_u32(this.get_pid())) } #[allow(non_snake_case)] diff --git a/src/shims/windows/foreign_items.rs b/src/shims/windows/foreign_items.rs index 71f6a2bc03..f840ba1616 100644 --- a/src/shims/windows/foreign_items.rs +++ b/src/shims/windows/foreign_items.rs @@ -141,7 +141,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "GetCurrentProcessId" => { let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; let result = this.GetCurrentProcessId()?; - this.write_int(result, dest)?; + this.write_scalar(result, dest)?; } // File related shims @@ -372,7 +372,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.machine.tls.store_tls(key, active_thread, new_data, &*this.tcx)?; // Return success (`1`). - this.write_scalar(Scalar::from_i32(1), dest)?; + this.write_int(1, dest)?; } // Access to command-line arguments @@ -563,7 +563,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let ptr = this.read_pointer(ptr)?; let len = this.read_target_usize(len)?; this.gen_random(ptr, len)?; - this.write_scalar(Scalar::from_i32(1), dest)?; + this.write_int(1, dest)?; } "BCryptGenRandom" => { // used by getrandom 0.2 @@ -627,7 +627,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.CloseHandle(handle)?; - this.write_scalar(Scalar::from_u32(1), dest)?; + this.write_int(1, dest)?; } "GetModuleFileNameW" => { let [handle, filename, size] =