This is similar to what is reported in #2693, but more general.
|
let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit(); |
|
unsafe { |
|
let p = attr.as_mut_ptr(); |
|
(*p).mq_flags = mq_flags; |
|
(*p).mq_maxmsg = mq_maxmsg; |
|
(*p).mq_msgsize = mq_msgsize; |
|
(*p).mq_curmsgs = mq_curmsgs; |
|
MqAttr { |
|
mq_attr: attr.assume_init(), |
|
} |
|
} |
: mq_attr has a private field so the struct cannot possibly be initialized.
- https://github.com/nix-rust/nix/blob/ba63e90362e24dcebbf96783da668647ceace21c/src/sys/signalfd.rs#L115C51-L127:
signalfd_siginfo has padding fields
|
let mut attr = mem::MaybeUninit::uninit(); |
|
let res = unsafe { libc::posix_spawnattr_init(attr.as_mut_ptr()) }; |
|
|
|
Errno::result(res)?; |
|
|
|
let attr = unsafe { attr.assume_init() }; |
|
Ok(PosixSpawnAttr { attr }) |
and other places in that file: posix_spawnattr_t has padding fields
|
let mut fdset = mem::MaybeUninit::uninit(); |
: the contents of fdset are not public API and may contain padding fields
|
let mut dst = mem::MaybeUninit::uninit(); |
: stat contains padding
The first example is the most problematic, that UB caused a (fairly innocuous) issue in Fedora's CI rust-lang/libc#4892 (comment). This happened to be fixed in the latest libc, but that was due to a change in internal details that shouldn't be relied upon.
In general, it's really not ever robust to use MaybeUninit::uninit with libc types if .assume_init() will be called. For anything that has padding fields now or may add fields in the future, it's easy to wind up in a situation where a system libc/kernel is only partially initializing the type and assume_init creates UB. I doubt the cost of zeroing will be noticeable when there is usually a syscall overhead.
(It's fine to leave the type wrapped in MaybeUninit and only access useful fields via raw pointers, same as in C, but that's not ergonomic.)
This is similar to what is reported in #2693, but more general.
nix/src/mqueue.rs
Lines 111 to 121 in ba63e90
mq_attrhas a private field so the struct cannot possibly be initialized.signalfd_siginfohas padding fieldsnix/src/spawn.rs
Lines 25 to 31 in ba63e90
posix_spawnattr_thas padding fieldsnix/src/sys/select.rs
Line 33 in ba63e90
fdsetare not public API and may contain padding fieldsnix/src/sys/stat.rs
Line 215 in ba63e90
The first example is the most problematic, that UB caused a (fairly innocuous) issue in Fedora's CI rust-lang/libc#4892 (comment). This happened to be fixed in the latest libc, but that was due to a change in internal details that shouldn't be relied upon.
In general, it's really not ever robust to use
MaybeUninit::uninitwith libc types if.assume_init()will be called. For anything that has padding fields now or may add fields in the future, it's easy to wind up in a situation where a system libc/kernel is only partially initializing the type andassume_initcreates UB. I doubt the cost of zeroing will be noticeable when there is usually a syscall overhead.(It's fine to leave the type wrapped in
MaybeUninitand only access useful fields via raw pointers, same as in C, but that's not ergonomic.)