about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorThe 8472 <git@infinite-source.de>2024-04-21 17:19:15 +0200
committerThe 8472 <git@infinite-source.de>2024-04-28 01:44:25 +0200
commit1ba00d9cb2fcfef464b6a188fa3a7543c66eecaa (patch)
tree2626b8a704fa0f5eaaccda41cd9950da8ea3b6f4 /library/std/src
parent25babe9a79a2c5d35211e0d6bad348637ef2a246 (diff)
downloadrust-1ba00d9cb2fcfef464b6a188fa3a7543c66eecaa.tar.gz
rust-1ba00d9cb2fcfef464b6a188fa3a7543c66eecaa.zip
put FD validity behind late debug_asserts checking
uses the same machinery as assert_unsafe_precondition
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/os/fd/owned.rs14
-rw-r--r--library/std/src/sys/pal/unix/fs.rs47
2 files changed, 32 insertions, 29 deletions
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs
index 8c421540af4..8c7fc4cb2e4 100644
--- a/library/std/src/os/fd/owned.rs
+++ b/library/std/src/os/fd/owned.rs
@@ -177,17 +177,9 @@ impl Drop for OwnedFd {
             // opened after we closed ours.
             #[cfg(not(target_os = "hermit"))]
             {
-                use crate::sys::os::errno;
-                // ideally this would use assert_unsafe_precondition!, but that's only in core
-                if cfg!(debug_assertions) {
-                    // close() can bubble up error codes from FUSE which can send semantically
-                    // inappropriate error codes including EBADF.
-                    // So we check file flags instead which live on the file descriptor and not the underlying file.
-                    // The downside is that it costs an extra syscall, so we only do it for debug.
-                    if libc::fcntl(self.fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
-                        rtabort!("IO Safety violation: owned file descriptor already closed");
-                    }
-                }
+                #[cfg(unix)]
+                crate::sys::fs::debug_assert_fd_is_open(self.fd);
+
                 let _ = libc::close(self.fd);
             }
             #[cfg(target_os = "hermit")]
diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs
index 2d57a9d81c9..0a86d28c2e3 100644
--- a/library/std/src/sys/pal/unix/fs.rs
+++ b/library/std/src/sys/pal/unix/fs.rs
@@ -868,28 +868,39 @@ impl Iterator for ReadDir {
     }
 }
 
+/// Aborts the process if a file desceriptor is not open, if debug asserts are enabled
+///
+/// Many IO syscalls can't be fully trusted about EBADF error codes because those
+/// might get bubbled up from a remote FUSE server rather than the file descriptor
+/// in the current process being invalid.
+///
+/// So we check file flags instead which live on the file descriptor and not the underlying file.
+/// The downside is that it costs an extra syscall, so we only do it for debug.
+#[inline]
+pub(crate) fn debug_assert_fd_is_open(fd: RawFd) {
+    use crate::sys::os::errno;
+
+    // this is similar to assert_unsafe_precondition!() but it doesn't require const
+    if core::ub_checks::check_library_ub() {
+        if unsafe { libc::fcntl(fd, libc::F_GETFD) } == -1 && errno() == libc::EBADF {
+            rtabort!("IO Safety violation: owned file descriptor already closed");
+        }
+    }
+}
+
 impl Drop for Dir {
     fn drop(&mut self) {
-        // ideally this would use assert_unsafe_precondition!, but that's only in core
-        #[cfg(all(
-            debug_assertions,
-            not(any(
-                target_os = "redox",
-                target_os = "nto",
-                target_os = "vita",
-                target_os = "hurd",
-            ))
-        ))]
+        // dirfd isn't supported everywhere
+        #[cfg(not(any(
+            miri,
+            target_os = "redox",
+            target_os = "nto",
+            target_os = "vita",
+            target_os = "hurd",
+        )))]
         {
-            use crate::sys::os::errno;
-            // close() can bubble up error codes from FUSE which can send semantically
-            // inappropriate error codes including EBADF.
-            // So we check file flags instead which live on the file descriptor and not the underlying file.
-            // The downside is that it costs an extra syscall, so we only do it for debug.
             let fd = unsafe { libc::dirfd(self.0) };
-            if unsafe { libc::fcntl(fd, libc::F_GETFD) } == -1 && errno() == libc::EBADF {
-                rtabort!("IO Safety violation: DIR*'s owned file descriptor already closed");
-            }
+            debug_assert_fd_is_open(fd);
         }
         let r = unsafe { libc::closedir(self.0) };
         assert!(