Skip to content

Commit 1ad8f0a

Browse files
authored
Don't allocate FdSetElement arrays smaller than FD_SET. (#1364)
On platforms where `FD_SET` is an fd array, ensure that our `FdSetElement` arrays are always at least as long as the platform `FD_SET` size.
1 parent a8fcbb5 commit 1ad8f0a

File tree

1 file changed

+25
-1
lines changed

1 file changed

+25
-1
lines changed

src/event/select.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,22 @@ pub fn fd_set_num_elements(set_count: usize, nfds: RawFd) -> usize {
232232
#[cfg(any(windows, target_os = "wasi"))]
233233
#[inline]
234234
pub(crate) fn fd_set_num_elements_for_fd_array(set_count: usize) -> usize {
235+
// Ensure that we always have a big enough set to derefence an `FD_SET`.
236+
core::cmp::max(
237+
fd_set_num_elements_for_fd_array_raw(set_count),
238+
div_ceil(size_of::<FD_SET>(), size_of::<FdSetElement>()),
239+
)
240+
}
241+
242+
/// Compute the raw `fd_set_num_elements` value, before ensuring the value is
243+
/// big enough to dereference an `FD_SET`.
244+
#[cfg(any(windows, target_os = "wasi"))]
245+
#[inline]
246+
fn fd_set_num_elements_for_fd_array_raw(set_count: usize) -> usize {
235247
// Allocate space for an `fd_count` field, plus `set_count` elements
236248
// for the `fd_array` field.
237249
div_ceil(
238-
align_of::<FD_SET>() + set_count * size_of::<RawFd>(),
250+
core::cmp::max(align_of::<FD_SET>(), align_of::<RawFd>()) + set_count * size_of::<RawFd>(),
239251
size_of::<FdSetElement>(),
240252
)
241253
}
@@ -346,12 +358,24 @@ mod test {
346358

347359
// The layout of `FD_SET` should match our layout of a set of the same
348360
// size.
361+
assert_eq!(
362+
fd_set_num_elements_for_fd_array_raw(
363+
memoffset::span_of!(FD_SET, fd_array).len() / size_of::<RawFd>()
364+
) * size_of::<FdSetElement>(),
365+
size_of::<FD_SET>()
366+
);
349367
assert_eq!(
350368
fd_set_num_elements_for_fd_array(
351369
memoffset::span_of!(FD_SET, fd_array).len() / size_of::<RawFd>()
352370
) * size_of::<FdSetElement>(),
353371
size_of::<FD_SET>()
354372
);
373+
374+
// Don't create fd sets smaller than `FD_SET`.
375+
assert_eq!(
376+
fd_set_num_elements_for_fd_array(0) * size_of::<FdSetElement>(),
377+
size_of::<FD_SET>()
378+
);
355379
}
356380

357381
#[test]

0 commit comments

Comments
 (0)