From c0e799db1a0acfd638a8a165eb703766b683ff37 Mon Sep 17 00:00:00 2001 From: tiif Date: Sun, 18 Aug 2024 01:57:24 +0800 Subject: [PATCH] Set EINVAL for epoll_wait maxevent value 0 --- src/tools/miri/src/shims/unix/linux/epoll.rs | 3 ++- src/tools/miri/tests/pass-dep/libc/libc-epoll.rs | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs index 127817d5bbe..c69a2ac216e 100644 --- a/src/tools/miri/src/shims/unix/linux/epoll.rs +++ b/src/tools/miri/src/shims/unix/linux/epoll.rs @@ -409,11 +409,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; let timeout = this.read_scalar(timeout)?.to_i32()?; - if epfd <= 0 { + if epfd <= 0 || maxevents <= 0 { let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; return Ok(Scalar::from_i32(-1)); } + // FIXME: Implement blocking support if timeout != 0 { throw_unsup_format!("epoll_wait: timeout value can only be 0"); 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 71f0e832afb..eb742f2ccfb 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs @@ -19,6 +19,7 @@ fn main() { test_epoll_ctl_del(); test_pointer(); test_two_same_fd_in_same_epoll_instance(); + test_epoll_wait_less_maxevent_zero(); } // Using `as` cast since `EPOLLET` wraps around @@ -528,3 +529,17 @@ fn test_no_notification_for_unregister_flag() { let expected_value = u64::try_from(fds[0]).unwrap(); check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); } + + +fn test_epoll_wait_less_maxevent_zero() { + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + // It is ok to use uninitialised pointer here because it will error out before the + // pointer actually get accessed. + let array_ptr = MaybeUninit::::uninit().as_mut_ptr(); + let res = unsafe { libc::epoll_wait(epfd, array_ptr, 0, 0) }; + let e = std::io::Error::last_os_error(); + assert_eq!(e.raw_os_error(), Some(libc::EINVAL)); + assert_eq!(res, -1); +}