From 0ea71218b03b87aefa39f224219f7782286149ab Mon Sep 17 00:00:00 2001 From: geetanshjuneja Date: Thu, 9 Jan 2025 21:37:20 +0530 Subject: [PATCH 01/11] Supported fioclex for ioctl on macos --- src/shims/unix/fd.rs | 21 +++++++++++++++++++++ src/shims/unix/macos/foreign_items.rs | 7 +++++++ 2 files changed, 28 insertions(+) diff --git a/src/shims/unix/fd.rs b/src/shims/unix/fd.rs index 0b59490308..e7a944b4b1 100644 --- a/src/shims/unix/fd.rs +++ b/src/shims/unix/fd.rs @@ -189,6 +189,27 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } + fn ioctl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let [fd_num, cmd] = check_min_arg_count("fcntl", args)?; + let fioclex = this.eval_libc_i32("FIOCLEX"); + + let fd_num = this.read_scalar(fd_num)?.to_i32()?; + let cmd = this.read_scalar(cmd)?.to_i32()?; + + if cmd == fioclex { + 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")) + } + // interp_ok(Scalar::from_i32(0)) + } else { + throw_unsup_format!("ioctl: unsupported command {cmd:#x}"); + } + } + fn close(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); diff --git a/src/shims/unix/macos/foreign_items.rs b/src/shims/unix/macos/foreign_items.rs index aa291639a6..7006e7b961 100644 --- a/src/shims/unix/macos/foreign_items.rs +++ b/src/shims/unix/macos/foreign_items.rs @@ -67,6 +67,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" => { From 1cbc0fdaa746e83fa8d1c2594703e962660d6f31 Mon Sep 17 00:00:00 2001 From: geetanshjuneja Date: Thu, 9 Jan 2025 21:39:37 +0530 Subject: [PATCH 02/11] cleanup --- src/shims/unix/fd.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/shims/unix/fd.rs b/src/shims/unix/fd.rs index e7a944b4b1..ffcdd6ba8c 100644 --- a/src/shims/unix/fd.rs +++ b/src/shims/unix/fd.rs @@ -204,7 +204,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } else { this.set_last_error_and_return_i32(LibcError("EBADF")) } - // interp_ok(Scalar::from_i32(0)) } else { throw_unsup_format!("ioctl: unsupported command {cmd:#x}"); } From ac360edf3b1691c2792cb859cba1baeaa4008c44 Mon Sep 17 00:00:00 2001 From: geetanshjuneja Date: Thu, 9 Jan 2025 21:40:45 +0530 Subject: [PATCH 03/11] nits --- src/shims/unix/fd.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shims/unix/fd.rs b/src/shims/unix/fd.rs index ffcdd6ba8c..518b182385 100644 --- a/src/shims/unix/fd.rs +++ b/src/shims/unix/fd.rs @@ -192,7 +192,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn ioctl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let [fd_num, cmd] = check_min_arg_count("fcntl", args)?; + let [fd_num, cmd] = check_min_arg_count("ioctl", args)?; let fioclex = this.eval_libc_i32("FIOCLEX"); let fd_num = this.read_scalar(fd_num)?.to_i32()?; From 77d40396ef129325eae9896f543bc070fa729712 Mon Sep 17 00:00:00 2001 From: geetanshjuneja Date: Fri, 10 Jan 2025 00:27:28 +0530 Subject: [PATCH 04/11] Added ioctl test --- tests/pass-dep/libc/libc-fs.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/pass-dep/libc/libc-fs.rs b/tests/pass-dep/libc/libc-fs.rs index f85abe2cc4..5dc2abc5e2 100644 --- a/tests/pass-dep/libc/libc-fs.rs +++ b/tests/pass-dep/libc/libc-fs.rs @@ -17,6 +17,8 @@ mod utils; fn main() { test_dup(); test_dup_stdout_stderr(); + #[cfg(target_os = "macos")] + test_ioctl(); test_canonicalize_too_long(); test_rename(); test_ftruncate::(libc::ftruncate); @@ -77,6 +79,20 @@ fn test_dup_stdout_stderr() { } } +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::(); + unsafe { + assert_eq!(libc::ioctl(1, libc::FIOCLEX), -1); + + let fd = libc::open(name_ptr, libc::O_RDONLY); + assert_eq!(libc::ioctl(fd, libc::FIOCLEX), 0); + } +} + fn test_dup() { let bytes = b"dup and dup2"; let path = utils::prepare_with_content("miri_test_libc_dup.txt", bytes); From a99984ca1357710292ec006a91f594d1486e0307 Mon Sep 17 00:00:00 2001 From: geetanshjuneja Date: Fri, 10 Jan 2025 00:32:45 +0530 Subject: [PATCH 05/11] fmt --- tests/pass-dep/libc/libc-fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/pass-dep/libc/libc-fs.rs b/tests/pass-dep/libc/libc-fs.rs index 5dc2abc5e2..cea1a54e3a 100644 --- a/tests/pass-dep/libc/libc-fs.rs +++ b/tests/pass-dep/libc/libc-fs.rs @@ -81,13 +81,13 @@ fn test_dup_stdout_stderr() { 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::(); unsafe { assert_eq!(libc::ioctl(1, libc::FIOCLEX), -1); - + let fd = libc::open(name_ptr, libc::O_RDONLY); assert_eq!(libc::ioctl(fd, libc::FIOCLEX), 0); } From 18d5dcc5796dadf08024e71b3d7905435aebef09 Mon Sep 17 00:00:00 2001 From: geetanshjuneja Date: Fri, 10 Jan 2025 00:46:59 +0530 Subject: [PATCH 06/11] nits --- tests/pass-dep/libc/libc-fs.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/pass-dep/libc/libc-fs.rs b/tests/pass-dep/libc/libc-fs.rs index cea1a54e3a..c1792ba4f7 100644 --- a/tests/pass-dep/libc/libc-fs.rs +++ b/tests/pass-dep/libc/libc-fs.rs @@ -79,6 +79,7 @@ fn test_dup_stdout_stderr() { } } +#[cfg(target_os = "macos")] fn test_ioctl() { let path = utils::prepare_with_content("miri_test_libc_ioctl.txt", &[]); From add00c1a4ee5e75ec43a4b57fb8f7b9f6595964a Mon Sep 17 00:00:00 2001 From: geetanshjuneja Date: Fri, 10 Jan 2025 18:39:28 +0530 Subject: [PATCH 07/11] Fixed ioctl and added pipe test --- src/helpers.rs | 8 ++++++++ src/shims/unix/fd.rs | 4 ++-- tests/pass-dep/libc/libc-fs.rs | 2 +- tests/pass/shims/pipe.rs | 10 ++++++++++ 4 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 tests/pass/shims/pipe.rs diff --git a/src/helpers.rs b/src/helpers.rs index adfec33bea..bae4144d71 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -254,6 +254,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 `i64`): {name}") + }) + } + /// Helper function to get a `libc` constant as an `u32`. fn eval_libc_u32(&self, name: &str) -> u32 { // TODO: Cache the result. diff --git a/src/shims/unix/fd.rs b/src/shims/unix/fd.rs index 518b182385..90713c32b4 100644 --- a/src/shims/unix/fd.rs +++ b/src/shims/unix/fd.rs @@ -193,10 +193,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let [fd_num, cmd] = check_min_arg_count("ioctl", args)?; - let fioclex = this.eval_libc_i32("FIOCLEX"); + let fioclex = this.eval_libc_u64("FIOCLEX"); let fd_num = this.read_scalar(fd_num)?.to_i32()?; - let cmd = this.read_scalar(cmd)?.to_i32()?; + let cmd = this.read_scalar(cmd)?.to_u64()?; if cmd == fioclex { if this.machine.fds.is_fd_num(fd_num) { diff --git a/tests/pass-dep/libc/libc-fs.rs b/tests/pass-dep/libc/libc-fs.rs index c1792ba4f7..221c39daaa 100644 --- a/tests/pass-dep/libc/libc-fs.rs +++ b/tests/pass-dep/libc/libc-fs.rs @@ -87,7 +87,7 @@ fn test_ioctl() { name.push("\0"); let name_ptr = name.as_bytes().as_ptr().cast::(); unsafe { - assert_eq!(libc::ioctl(1, libc::FIOCLEX), -1); + assert_eq!(libc::ioctl(10, libc::FIOCLEX), -1); let fd = libc::open(name_ptr, libc::O_RDONLY); assert_eq!(libc::ioctl(fd, libc::FIOCLEX), 0); diff --git a/tests/pass/shims/pipe.rs b/tests/pass/shims/pipe.rs new file mode 100644 index 0000000000..ccc5afd7d7 --- /dev/null +++ b/tests/pass/shims/pipe.rs @@ -0,0 +1,10 @@ +#![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()); +} From 37f7c2f8468f68d0d02979183e926f35f8b630de Mon Sep 17 00:00:00 2001 From: geetanshjuneja Date: Fri, 10 Jan 2025 18:43:51 +0530 Subject: [PATCH 08/11] nits --- src/helpers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers.rs b/src/helpers.rs index bae4144d71..0a782862c4 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -258,7 +258,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { 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 `i64`): {name}") + panic!("required libc item has unexpected type (not `u64`): {name}") }) } From 1bcf34efa38ba77f0d7ec0fa9a87742429c583fa Mon Sep 17 00:00:00 2001 From: geetanshjuneja Date: Fri, 10 Jan 2025 18:55:34 +0530 Subject: [PATCH 09/11] ignore pipe test for window --- tests/pass/shims/pipe.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/pass/shims/pipe.rs b/tests/pass/shims/pipe.rs index ccc5afd7d7..d547b2b1cc 100644 --- a/tests/pass/shims/pipe.rs +++ b/tests/pass/shims/pipe.rs @@ -1,3 +1,5 @@ +//@ignore-target: windows + #![feature(anonymous_pipe)] use std::io::{Read, Write}; From 2f1755148d118ca7792e468cca33733a465a9811 Mon Sep 17 00:00:00 2001 From: geetanshjuneja Date: Sat, 11 Jan 2025 21:49:41 +0530 Subject: [PATCH 10/11] minor changes --- src/helpers.rs | 16 ++++++------ src/shims/unix/fd.rs | 20 --------------- src/shims/unix/macos/foreign_items.rs | 23 +++++++++++++++++ tests/pass-dep/libc/libc-fs.rs | 37 +++++++++++++++------------ 4 files changed, 51 insertions(+), 45 deletions(-) diff --git a/src/helpers.rs b/src/helpers.rs index 0a782862c4..ca8dbdac12 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -254,14 +254,6 @@ 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 `libc` constant as an `u32`. fn eval_libc_u32(&self, name: &str) -> u32 { // TODO: Cache the result. @@ -270,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]) diff --git a/src/shims/unix/fd.rs b/src/shims/unix/fd.rs index 90713c32b4..0b59490308 100644 --- a/src/shims/unix/fd.rs +++ b/src/shims/unix/fd.rs @@ -189,26 +189,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } - fn ioctl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> { - let this = self.eval_context_mut(); - - let [fd_num, cmd] = check_min_arg_count("ioctl", args)?; - let fioclex = this.eval_libc_u64("FIOCLEX"); - - let fd_num = this.read_scalar(fd_num)?.to_i32()?; - let cmd = this.read_scalar(cmd)?.to_u64()?; - - if cmd == fioclex { - 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}"); - } - } - fn close(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); diff --git a/src/shims/unix/macos/foreign_items.rs b/src/shims/unix/macos/foreign_items.rs index 7006e7b961..2afe0b5cd3 100644 --- a/src/shims/unix/macos/foreign_items.rs +++ b/src/shims/unix/macos/foreign_items.rs @@ -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::*; @@ -241,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}"); + } + } } diff --git a/tests/pass-dep/libc/libc-fs.rs b/tests/pass-dep/libc/libc-fs.rs index 221c39daaa..129b18d8e5 100644 --- a/tests/pass-dep/libc/libc-fs.rs +++ b/tests/pass-dep/libc/libc-fs.rs @@ -17,8 +17,6 @@ mod utils; fn main() { test_dup(); test_dup_stdout_stderr(); - #[cfg(target_os = "macos")] - test_ioctl(); test_canonicalize_too_long(); test_rename(); test_ftruncate::(libc::ftruncate); @@ -40,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() { @@ -79,21 +79,6 @@ fn test_dup_stdout_stderr() { } } -#[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::(); - unsafe { - assert_eq!(libc::ioctl(10, libc::FIOCLEX), -1); - - let fd = libc::open(name_ptr, libc::O_RDONLY); - assert_eq!(libc::ioctl(fd, libc::FIOCLEX), 0); - } -} - fn test_dup() { let bytes = b"dup and dup2"; let path = utils::prepare_with_content("miri_test_libc_dup.txt", bytes); @@ -448,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::(); + 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); + } +} From d1e52eea9b190047d6fbe13bc234053762e8f61f Mon Sep 17 00:00:00 2001 From: geetanshjuneja Date: Sat, 11 Jan 2025 22:07:13 +0530 Subject: [PATCH 11/11] Supported fioclex for ioctl on macos --- src/helpers.rs | 8 +++++++ src/shims/unix/macos/foreign_items.rs | 30 +++++++++++++++++++++++++++ tests/pass-dep/libc/libc-fs.rs | 20 ++++++++++++++++++ tests/pass/shims/pipe.rs | 12 +++++++++++ 4 files changed, 70 insertions(+) create mode 100644 tests/pass/shims/pipe.rs diff --git a/src/helpers.rs b/src/helpers.rs index adfec33bea..ca8dbdac12 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -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]) diff --git a/src/shims/unix/macos/foreign_items.rs b/src/shims/unix/macos/foreign_items.rs index aa291639a6..2afe0b5cd3 100644 --- a/src/shims/unix/macos/foreign_items.rs +++ b/src/shims/unix/macos/foreign_items.rs @@ -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}"); + } + } } diff --git a/tests/pass-dep/libc/libc-fs.rs b/tests/pass-dep/libc/libc-fs.rs index f85abe2cc4..129b18d8e5 100644 --- a/tests/pass-dep/libc/libc-fs.rs +++ b/tests/pass-dep/libc/libc-fs.rs @@ -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::(); + 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); + } +} diff --git a/tests/pass/shims/pipe.rs b/tests/pass/shims/pipe.rs new file mode 100644 index 0000000000..d547b2b1cc --- /dev/null +++ b/tests/pass/shims/pipe.rs @@ -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()); +}