Merge pull request #4133 from geetanshjuneja/ioctl2
Supported fioclex for ioctl on macos
This commit is contained in:
commit
fcb64d3af0
4 changed files with 70 additions and 0 deletions
|
|
@ -262,6 +262,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Helper function to get a `libc` constant as an `u64`.
|
||||
fn eval_libc_u64(&self, name: &str) -> u64 {
|
||||
// TODO: Cache the result.
|
||||
self.eval_libc(name).to_u64().unwrap_or_else(|_err| {
|
||||
panic!("required libc item has unexpected type (not `u64`): {name}")
|
||||
})
|
||||
}
|
||||
|
||||
/// Helper function to get a `windows` constant as a `Scalar`.
|
||||
fn eval_windows(&self, module: &str, name: &str) -> Scalar {
|
||||
self.eval_context_ref().eval_path_scalar(&["std", "sys", "pal", "windows", module, name])
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use rustc_span::Symbol;
|
|||
use rustc_target::callconv::{Conv, FnAbi};
|
||||
|
||||
use super::sync::EvalContextExt as _;
|
||||
use crate::helpers::check_min_arg_count;
|
||||
use crate::shims::unix::*;
|
||||
use crate::*;
|
||||
|
||||
|
|
@ -67,6 +68,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
let result = this.realpath(path, resolved_path)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"ioctl" => {
|
||||
// `ioctl` is variadic. The argument count is checked based on the first argument
|
||||
// in `this.ioctl()`, so we do not use `check_shim` here.
|
||||
this.check_abi_and_shim_symbol_clash(abi, Conv::C, link_name)?;
|
||||
let result = this.ioctl(args)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
|
||||
// Environment related shims
|
||||
"_NSGetEnviron" => {
|
||||
|
|
@ -234,4 +242,26 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
interp_ok(EmulateItemResult::NeedsReturn)
|
||||
}
|
||||
|
||||
fn ioctl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let fioclex = this.eval_libc_u64("FIOCLEX");
|
||||
|
||||
let [fd_num, cmd] = check_min_arg_count("ioctl", args)?;
|
||||
let fd_num = this.read_scalar(fd_num)?.to_i32()?;
|
||||
let cmd = this.read_scalar(cmd)?.to_u64()?;
|
||||
|
||||
if cmd == fioclex {
|
||||
// Since we don't support `exec`, this is a NOP. However, we want to
|
||||
// return EBADF if the FD is invalid.
|
||||
if this.machine.fds.is_fd_num(fd_num) {
|
||||
interp_ok(Scalar::from_i32(0))
|
||||
} else {
|
||||
this.set_last_error_and_return_i32(LibcError("EBADF"))
|
||||
}
|
||||
} else {
|
||||
throw_unsup_format!("ioctl: unsupported command {cmd:#x}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ fn main() {
|
|||
test_isatty();
|
||||
test_read_and_uninit();
|
||||
test_nofollow_not_symlink();
|
||||
#[cfg(target_os = "macos")]
|
||||
test_ioctl();
|
||||
}
|
||||
|
||||
fn test_file_open_unix_allow_two_args() {
|
||||
|
|
@ -431,3 +433,21 @@ fn test_nofollow_not_symlink() {
|
|||
let ret = unsafe { libc::open(cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) };
|
||||
assert!(ret >= 0);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn test_ioctl() {
|
||||
let path = utils::prepare_with_content("miri_test_libc_ioctl.txt", &[]);
|
||||
|
||||
let mut name = path.into_os_string();
|
||||
name.push("\0");
|
||||
let name_ptr = name.as_bytes().as_ptr().cast::<libc::c_char>();
|
||||
unsafe {
|
||||
// 100 surely is an invalid FD.
|
||||
assert_eq!(libc::ioctl(100, libc::FIOCLEX), -1);
|
||||
let errno = std::io::Error::last_os_error().raw_os_error().unwrap();
|
||||
assert_eq!(errno, libc::EBADF);
|
||||
|
||||
let fd = libc::open(name_ptr, libc::O_RDONLY);
|
||||
assert_eq!(libc::ioctl(fd, libc::FIOCLEX), 0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
12
src/tools/miri/tests/pass/shims/pipe.rs
Normal file
12
src/tools/miri/tests/pass/shims/pipe.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
//@ignore-target: windows
|
||||
|
||||
#![feature(anonymous_pipe)]
|
||||
use std::io::{Read, Write};
|
||||
|
||||
fn main() {
|
||||
let (mut ping_rx, mut ping_tx) = std::pipe::pipe().unwrap();
|
||||
ping_tx.write(b"hello").unwrap();
|
||||
let mut buf: [u8; 5] = [0; 5];
|
||||
ping_rx.read(&mut buf).unwrap();
|
||||
assert_eq!(&buf, "hello".as_bytes());
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue