-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
What it does
Warn for any calls to MaybeUninit::uninit(). Alternatively, expand uninit_assumed_init to any uses of MaybeUninit::uninit() followed after some code by .assume_init().
Advantage
MaybeUninit::uninit() isn't unsound on its own, but it can be a bit of a footgun with libc types and other FFI. The issue is that a number of libc structs have padding that the system libc/kernel doesn't write, and occasionally there are new fields added. This means that fairly innocent looking code like this:
let mut s = MaybeUninit::<foo>::uninit();
libc::do_foo(s.as_mut_ptr());
return s.assume_init();Can turn into UB if libc adds a field that hasn't yet made it to the local glibc version. Using zeroed instead is safe against this, and should be negligible to no cost.
Drawbacks
No response
Example
let mut s = MaybeUninit::<foo>::uninit();
libc::do_foo(s.as_mut_ptr());
return s.assume_init();Could be written as:
let mut s = MaybeUninit::<foo>::zeroed();
libc::do_foo(s.as_mut_ptr());
return s.assume_init();Comparison with existing lints
This is similar to clippy::uninit_assumed_init, though that specifically looks for MaybeUninit::uninit().assume_init().
Additional Context
Technically this doesn't need to warn if assume_init is never called, but that adds more difficulty to the lint.