Use Scalar consistently in foreign item emulation
This commit is contained in:
parent
cf63c16269
commit
6fc1b69993
10 changed files with 239 additions and 245 deletions
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<i128>,
|
||||
) -> 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<i128>,
|
||||
) -> 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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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::<c_ulong>()
|
||||
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::<c_ulong>()
|
||||
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" => {
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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] =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue