about summary refs log tree commit diff
diff options
context:
space:
mode:
authortiif <pekyuan@gmail.com>2024-08-23 21:23:09 +0800
committertiif <pekyuan@gmail.com>2024-08-24 18:13:49 +0800
commit14f22c6e66b75aab02fc2a50ce18f1af638050ec (patch)
tree986824715a09aa856a19789a0cd444c8174de4b1
parentb8c02eb11eaac24e56ef718040eb83c304125ac6 (diff)
downloadrust-14f22c6e66b75aab02fc2a50ce18f1af638050ec.tar.gz
rust-14f22c6e66b75aab02fc2a50ce18f1af638050ec.zip
epoll: Add EINVAL case
-rw-r--r--src/tools/miri/src/shims/unix/linux/epoll.rs7
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-epoll.rs14
2 files changed, 21 insertions, 0 deletions
diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs
index fb1e0afdf9e..ea430fec593 100644
--- a/src/tools/miri/src/shims/unix/linux/epoll.rs
+++ b/src/tools/miri/src/shims/unix/linux/epoll.rs
@@ -251,6 +251,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             throw_unsup_format!("epoll_ctl: encountered unknown unsupported operation {:#x}", op);
         }
 
+        // Throw EINVAL if epfd and fd have the same value.
+        if epfd_value == fd {
+            let einval = this.eval_libc("EINVAL");
+            this.set_last_error(einval)?;
+            return Ok(Scalar::from_i32(-1));
+        }
+
         // Check if epfd is a valid epoll file descriptor.
         let Some(epfd) = this.machine.fds.get(epfd_value) else {
             return Ok(Scalar::from_i32(this.fd_not_found()?));
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs
index 052ce73de23..7b8acbd1200 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs
@@ -21,6 +21,7 @@ fn main() {
     test_socketpair_epollerr();
     test_epoll_lost_events();
     test_ready_list_fetching_logic();
+    test_epoll_ctl_epfd_equal_fd();
 }
 
 // Using `as` cast since `EPOLLET` wraps around
@@ -630,3 +631,16 @@ fn test_ready_list_fetching_logic() {
     let expected_value1 = fd1 as u64;
     check_epoll_wait::<1>(epfd, &[(expected_event1, expected_value1)]);
 }
+
+// In epoll_ctl, if the value of epfd equals to fd, EINVAL should be returned.
+fn test_epoll_ctl_epfd_equal_fd() {
+    // Create an epoll instance.
+    let epfd = unsafe { libc::epoll_create1(0) };
+    assert_ne!(epfd, -1);
+
+    let array_ptr = std::ptr::without_provenance_mut::<libc::epoll_event>(0x100);
+    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, epfd, array_ptr) };
+    let e = std::io::Error::last_os_error();
+    assert_eq!(e.raw_os_error(), Some(libc::EINVAL));
+    assert_eq!(res, -1);
+}