diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh index 7808c9acf931..378d7744cf21 100755 --- a/src/tools/miri/ci.sh +++ b/src/tools/miri/ci.sh @@ -108,7 +108,7 @@ case $HOST_TARGET in MIRI_TEST_TARGET=aarch64-unknown-linux-gnu run_tests MIRI_TEST_TARGET=aarch64-apple-darwin run_tests MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests - MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc atomic env align + MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings wasm MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std integer strings wasm diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index 4918698c6b27..611b8bc8ccc6 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -31,8 +31,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let mut relative_clocks; match this.tcx.sess.target.os.as_ref() { - "linux" => { - // Linux has two main kinds of clocks. REALTIME clocks return the actual time since the + "linux" | "freebsd" => { + // Linux and FreeBSD have two main kinds of clocks. REALTIME clocks return the actual time since the // Unix epoch, including effects which may cause time to move backwards such as NTP. // Linux further distinguishes regular and "coarse" clocks, but the "coarse" version // is just specified to be "faster and less precise", so we implement both the same way. diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index d155623eb7b6..7bc26788b267 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -163,6 +163,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "ftruncate64" => { let [fd, length] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let fd = this.read_scalar(fd)?.to_i32()?; + let length = this.read_scalar(length)?.to_i64()?; + let result = this.ftruncate64(fd, length)?; + this.write_scalar(result, dest)?; + } + "ftruncate" => { + let [fd, length] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let fd = this.read_scalar(fd)?.to_i32()?; + let length = this.read_target_isize(length)?; let result = this.ftruncate64(fd, length)?; this.write_scalar(result, dest)?; } diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 062623a7f6a6..721fa161232e 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -1504,16 +1504,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - fn ftruncate64( - &mut self, - fd_op: &OpTy<'tcx, Provenance>, - length_op: &OpTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, Scalar> { + fn ftruncate64(&mut self, fd: i32, length: i64) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let fd = this.read_scalar(fd_op)?.to_i32()?; - let length = this.read_scalar(length_op)?.to_i64()?; - // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`ftruncate64`", reject_with)?; diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index e8f35e7ba578..07e19cadd6e3 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -72,13 +72,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let result = this.lseek64(fd, offset, whence)?; this.write_scalar(result, dest)?; } - "ftruncate" => { - let [fd, length] = - this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - // macOS is 64bit-only, so this is ftruncate64 - let result = this.ftruncate64(fd, length)?; - this.write_scalar(result, dest)?; - } "realpath$DARWIN_EXTSN" => { let [path, resolved_path] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs index 5185db0b0e29..adfece586611 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs @@ -1,4 +1,5 @@ //@ignore-target-windows: no libc on Windows +//@ignore-target-freebsd: FIXME needs foreign function `stat@FBSD_1.0` //@compile-flags: -Zmiri-isolation-error=warn-nobacktrace //@normalize-stderr-test: "(stat(x)?)" -> "$$STAT" diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs index 767a4fdbede3..697970a0885d 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs @@ -23,6 +23,7 @@ fn main() { test_file_open_unix_extra_third_arg(); #[cfg(target_os = "linux")] test_o_tmpfile_flag(); + test_posix_mkstemp(); } /// Prepare: compute filename and make sure the file does not exist. @@ -151,3 +152,45 @@ fn test_o_tmpfile_flag() { .raw_os_error(), ); } + +fn test_posix_mkstemp() { + use std::ffi::OsStr; + use std::os::unix::io::FromRawFd; + use std::path::Path; + + let valid_template = "fooXXXXXX"; + // C needs to own this as `mkstemp(3)` says: + // "Since it will be modified, `template` must not be a string constant, but + // should be declared as a character array." + // There seems to be no `as_mut_ptr` on `CString` so we need to use `into_raw`. + let ptr = CString::new(valid_template).unwrap().into_raw(); + let fd = unsafe { libc::mkstemp(ptr) }; + // Take ownership back in Rust to not leak memory. + let slice = unsafe { CString::from_raw(ptr) }; + assert!(fd > 0); + let osstr = OsStr::from_bytes(slice.to_bytes()); + let path: &Path = osstr.as_ref(); + let name = path.file_name().unwrap().to_string_lossy(); + assert!(name.ne("fooXXXXXX")); + assert!(name.starts_with("foo")); + assert_eq!(name.len(), 9); + assert_eq!( + name.chars().skip(3).filter(char::is_ascii_alphanumeric).collect::>().len(), + 6 + ); + let file = unsafe { File::from_raw_fd(fd) }; + assert!(file.set_len(0).is_ok()); + + let invalid_templates = vec!["foo", "barXX", "XXXXXXbaz", "whatXXXXXXever", "X"]; + for t in invalid_templates { + let ptr = CString::new(t).unwrap().into_raw(); + let fd = unsafe { libc::mkstemp(ptr) }; + let _ = unsafe { CString::from_raw(ptr) }; + // "On error, -1 is returned, and errno is set to + // indicate the error" + assert_eq!(fd, -1); + let e = std::io::Error::last_os_error(); + assert_eq!(e.raw_os_error(), Some(libc::EINVAL)); + assert_eq!(e.kind(), std::io::ErrorKind::InvalidInput); + } +} diff --git a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs index de1acb13cbeb..abb384b0a857 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs @@ -172,14 +172,13 @@ fn test_thread_local_errno() { } /// Tests whether clock support exists at all -#[cfg(not(target_os = "freebsd"))] fn test_clocks() { let mut tp = std::mem::MaybeUninit::::uninit(); let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, tp.as_mut_ptr()) }; assert_eq!(is_error, 0); let is_error = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, tp.as_mut_ptr()) }; assert_eq!(is_error, 0); - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "freebsd"))] { let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME_COARSE, tp.as_mut_ptr()) }; assert_eq!(is_error, 0); @@ -238,51 +237,6 @@ fn test_isatty() { } } -#[cfg(not(target_os = "freebsd"))] -fn test_posix_mkstemp() { - use std::ffi::CString; - use std::ffi::OsStr; - use std::os::unix::ffi::OsStrExt; - use std::os::unix::io::FromRawFd; - use std::path::Path; - - let valid_template = "fooXXXXXX"; - // C needs to own this as `mkstemp(3)` says: - // "Since it will be modified, `template` must not be a string constant, but - // should be declared as a character array." - // There seems to be no `as_mut_ptr` on `CString` so we need to use `into_raw`. - let ptr = CString::new(valid_template).unwrap().into_raw(); - let fd = unsafe { libc::mkstemp(ptr) }; - // Take ownership back in Rust to not leak memory. - let slice = unsafe { CString::from_raw(ptr) }; - assert!(fd > 0); - let osstr = OsStr::from_bytes(slice.to_bytes()); - let path: &Path = osstr.as_ref(); - let name = path.file_name().unwrap().to_string_lossy(); - assert!(name.ne("fooXXXXXX")); - assert!(name.starts_with("foo")); - assert_eq!(name.len(), 9); - assert_eq!( - name.chars().skip(3).filter(char::is_ascii_alphanumeric).collect::>().len(), - 6 - ); - let file = unsafe { File::from_raw_fd(fd) }; - assert!(file.set_len(0).is_ok()); - - let invalid_templates = vec!["foo", "barXX", "XXXXXXbaz", "whatXXXXXXever", "X"]; - for t in invalid_templates { - let ptr = CString::new(t).unwrap().into_raw(); - let fd = unsafe { libc::mkstemp(ptr) }; - let _ = unsafe { CString::from_raw(ptr) }; - // "On error, -1 is returned, and errno is set to - // indicate the error" - assert_eq!(fd, -1); - let e = std::io::Error::last_os_error(); - assert_eq!(e.raw_os_error(), Some(libc::EINVAL)); - assert_eq!(e.kind(), std::io::ErrorKind::InvalidInput); - } -} - fn test_memcpy() { unsafe { let src = [1i8, 2, 3]; @@ -406,9 +360,6 @@ fn test_reallocarray() { fn main() { test_posix_gettimeofday(); - #[cfg(not(target_os = "freebsd"))] // FIXME we should support this on FreeBSD as well - test_posix_mkstemp(); - test_posix_realpath_alloc(); test_posix_realpath_noalloc(); test_posix_realpath_errors(); @@ -417,7 +368,6 @@ fn main() { test_isatty(); - #[cfg(not(target_os = "freebsd"))] // FIXME we should support this on FreeBSD as well test_clocks(); test_dlsym();