Skip to content

Commit

Permalink
Return Errno::INVAL when converting a Timespec to i32.
Browse files Browse the repository at this point in the history
  • Loading branch information
sunfishcode committed Jan 23, 2025
1 parent 6206487 commit 80fbb61
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/backend/libc/event/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: Option<&Timespec>) -> io::Re
millis.checked_add((i64::from(timeout.tv_nsec) + 999_999) / 1_000_000)
})
.and_then(|millis| c::c_int::try_from(millis).ok())
.ok_or(io::Errno::OVERFLOW)?
.ok_or(io::Errno::INVAL)?
}
};
ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) })
Expand Down
21 changes: 19 additions & 2 deletions src/backend/libc/event/windows_syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,32 @@
use crate::backend::c;
use crate::backend::conv::ret_c_int;
use crate::event::{FdSetElement, PollFd};
use crate::event::{FdSetElement, PollFd, Timespec};
use crate::io;

pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result<usize> {
pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: Option<&Timespec>) -> io::Result<usize> {
let nfds = fds
.len()
.try_into()
.map_err(|_convert_err| io::Errno::INVAL)?;

let timeout = match timeout {
None => -1,
Some(timeout) => {
// Convert from `Timespec` to `c_int` milliseconds.
let secs = timeout.tv_sec;
if secs < 0 {
return Err(io::Errno::INVAL);
}
secs.checked_mul(1000)
.and_then(|millis| {
millis.checked_add((i64::from(timeout.tv_nsec) + 999_999) / 1_000_000)
})
.and_then(|millis| c::c_int::try_from(millis).ok())
.ok_or(io::Errno::INVAL)?
}
};

ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) })
.map(|nready| nready as usize)
}
Expand Down
6 changes: 2 additions & 4 deletions src/event/poll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ pub use backend::event::poll_fd::{PollFd, PollFlags};
/// `poll(self.fds, timeout)`—Wait for events on lists of file descriptors.
///
/// Some platforms (those that don't support `ppoll`) don't support timeouts
/// greater than `c_int::MAX` milliseconds, and some (those that aren't fully
/// y2038-ready) don't support timeouts with a seconds value greater than
/// `i32::MAX`; if an unsupported timeout is passed, this function fails with
/// [`io::Errno::OVERFLOW`].
/// greater than `c_int::MAX` milliseconds; if an unsupported timeout is
/// passed, this function fails with [`io::Errno::INVAL`].
///
/// On macOS, `poll` doesn't work on fds for /dev/tty or /dev/null, however
/// [`select`] is available and does work on these fds.
Expand Down

0 comments on commit 80fbb61

Please sign in to comment.