From 469032433d68841ad098f03aa2b28e81235b8be8 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Fri, 30 Aug 2019 23:10:22 -0600 Subject: [PATCH] Replace most instances of mem::uninitialized with mem::MaybeUninit Only two instances remain: * For the deprecated sys::socket::CmsgSpace::new. We should probably just remove that method. * For sys::termios::Termios::default_uninit. This will require some more thought. Fixes #1096 --- CONVENTIONS.md | 9 ++-- src/dir.rs | 11 +++-- src/ifaddrs.rs | 16 +++--- src/mqueue.rs | 32 +++++++----- src/pty.rs | 44 +++++++++-------- src/sys/ptrace/linux.rs | 7 ++- src/sys/quota.rs | 9 ++-- src/sys/select.rs | 11 +++-- src/sys/signal.rs | 107 ++++++++++++++++++++++------------------ src/sys/signalfd.rs | 11 +++-- src/sys/socket/addr.rs | 4 +- src/sys/socket/mod.rs | 60 +++++++++++----------- src/sys/stat.rs | 24 ++++----- src/sys/statfs.rs | 12 +++-- src/sys/statvfs.rs | 14 +++--- src/sys/sysinfo.rs | 7 +-- src/sys/termios.rs | 6 +-- src/sys/utsname.rs | 8 +-- src/ucontext.rs | 10 ++-- src/unistd.rs | 24 +++++---- test/sys/test_ptrace.rs | 2 +- 21 files changed, 234 insertions(+), 194 deletions(-) diff --git a/CONVENTIONS.md b/CONVENTIONS.md index 48daa93..2461085 100644 --- a/CONVENTIONS.md +++ b/CONVENTIONS.md @@ -76,12 +76,11 @@ to parameters of functions by [enumerations][enum]. Whenever we need to use a [libc][libc] function to properly initialize a variable and said function allows us to use uninitialized memory, we use -[`std::mem::uninitialized`][std_uninitialized] (or [`core::mem::uninitialized`][core_uninitialized]) -when defining the variable. This allows us to avoid the overhead incurred by -zeroing or otherwise initializing the variable. +[`std::mem::MaybeUninit`][std_MaybeUninit] when defining the variable. This +allows us to avoid the overhead incurred by zeroing or otherwise initializing +the variable. [bitflags]: https://crates.io/crates/bitflags/ -[core_uninitialized]: https://doc.rust-lang.org/core/mem/fn.uninitialized.html [enum]: https://doc.rust-lang.org/reference.html#enumerations [libc]: https://crates.io/crates/libc/ -[std_uninitialized]: https://doc.rust-lang.org/std/mem/fn.uninitialized.html +[std_MaybeUninit]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html diff --git a/src/dir.rs b/src/dir.rs index 5dfc51c..d8c05e9 100644 --- a/src/dir.rs +++ b/src/dir.rs @@ -102,16 +102,18 @@ impl<'d> Iterator for Iter<'d> { // for the NUL byte. It doesn't look like the std library does this; it just uses // fixed-sized buffers (and libc's dirent seems to be sized so this is appropriate). // Probably fine here too then. - let mut ent: Entry = Entry(::std::mem::uninitialized()); + let mut ent = std::mem::MaybeUninit::::uninit(); let mut result = ptr::null_mut(); - if let Err(e) = Errno::result(readdir_r((self.0).0.as_ptr(), &mut ent.0, &mut result)) { + if let Err(e) = Errno::result( + readdir_r((self.0).0.as_ptr(), ent.as_mut_ptr(), &mut result)) + { return Some(Err(e)); } if result.is_null() { return None; } - assert_eq!(result, &mut ent.0 as *mut dirent); - Some(Ok(ent)) + assert_eq!(result, ent.as_mut_ptr()); + Some(Ok(Entry(ent.assume_init()))) } } } @@ -126,6 +128,7 @@ impl<'d> Drop for Iter<'d> { /// /// Note that unlike the std version, this may represent the `.` or `..` entries. #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] +#[repr(transparent)] pub struct Entry(dirent); #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] diff --git a/src/ifaddrs.rs b/src/ifaddrs.rs index 0485b1b..2c226cb 100644 --- a/src/ifaddrs.rs +++ b/src/ifaddrs.rs @@ -125,13 +125,15 @@ impl Iterator for InterfaceAddressIterator { /// } /// ``` pub fn getifaddrs() -> Result { - let mut addrs: *mut libc::ifaddrs = unsafe { mem::uninitialized() }; - Errno::result(unsafe { libc::getifaddrs(&mut addrs) }).map(|_| { - InterfaceAddressIterator { - base: addrs, - next: addrs, - } - }) + let mut addrs = mem::MaybeUninit::<*mut libc::ifaddrs>::uninit(); + unsafe { + Errno::result(libc::getifaddrs(addrs.as_mut_ptr())).map(|_| { + InterfaceAddressIterator { + base: addrs.assume_init(), + next: addrs.assume_init(), + } + }) + } } #[cfg(test)] diff --git a/src/mqueue.rs b/src/mqueue.rs index a35f895..62ba808 100644 --- a/src/mqueue.rs +++ b/src/mqueue.rs @@ -39,13 +39,17 @@ impl MqAttr { mq_maxmsg: c_long, mq_msgsize: c_long, mq_curmsgs: c_long) - -> MqAttr { - let mut attr = unsafe { mem::uninitialized::() }; - attr.mq_flags = mq_flags; - attr.mq_maxmsg = mq_maxmsg; - attr.mq_msgsize = mq_msgsize; - attr.mq_curmsgs = mq_curmsgs; - MqAttr { mq_attr: attr } + -> MqAttr + { + let mut attr = mem::MaybeUninit::::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() } + } } pub fn flags(&self) -> c_long { @@ -123,9 +127,9 @@ pub fn mq_send(mqdes: mqd_t, message: &[u8], msq_prio: u32) -> Result<()> { /// /// See also [`mq_getattr(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_getattr.html) pub fn mq_getattr(mqd: mqd_t) -> Result { - let mut attr = unsafe { mem::uninitialized::() }; - let res = unsafe { libc::mq_getattr(mqd, &mut attr) }; - Errno::result(res).map(|_| MqAttr { mq_attr: attr }) + let mut attr = mem::MaybeUninit::::uninit(); + let res = unsafe { libc::mq_getattr(mqd, attr.as_mut_ptr()) }; + Errno::result(res).map(|_| unsafe{MqAttr { mq_attr: attr.assume_init() }}) } /// Set the attributes of the message queue. Only `O_NONBLOCK` can be set, everything else will be ignored @@ -134,9 +138,11 @@ pub fn mq_getattr(mqd: mqd_t) -> Result { /// /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_setattr.html) pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result { - let mut attr = unsafe { mem::uninitialized::() }; - let res = unsafe { libc::mq_setattr(mqd, &newattr.mq_attr as *const libc::mq_attr, &mut attr) }; - Errno::result(res).map(|_| MqAttr { mq_attr: attr }) + let mut attr = mem::MaybeUninit::::uninit(); + let res = unsafe { + libc::mq_setattr(mqd, &newattr.mq_attr as *const libc::mq_attr, attr.as_mut_ptr()) + }; + Errno::result(res).map(|_| unsafe{ MqAttr { mq_attr: attr.assume_init() }}) } /// Convenience function. diff --git a/src/pty.rs b/src/pty.rs index 51b269e..b281d75 100644 --- a/src/pty.rs +++ b/src/pty.rs @@ -218,16 +218,16 @@ pub fn unlockpt(fd: &PtyMaster) -> Result<()> { pub fn openpty<'a, 'b, T: Into>, U: Into>>(winsize: T, termios: U) -> Result { use std::ptr; - let mut slave: libc::c_int = unsafe { mem::uninitialized() }; - let mut master: libc::c_int = unsafe { mem::uninitialized() }; + let mut slave = mem::MaybeUninit::::uninit(); + let mut master = mem::MaybeUninit::::uninit(); let ret = { match (termios.into(), winsize.into()) { (Some(termios), Some(winsize)) => { let inner_termios = termios.get_libc_termios(); unsafe { libc::openpty( - &mut master, - &mut slave, + master.as_mut_ptr(), + slave.as_mut_ptr(), ptr::null_mut(), &*inner_termios as *const libc::termios as *mut _, winsize as *const Winsize as *mut _, @@ -237,8 +237,8 @@ pub fn openpty<'a, 'b, T: Into>, U: Into (None, Some(winsize)) => { unsafe { libc::openpty( - &mut master, - &mut slave, + master.as_mut_ptr(), + slave.as_mut_ptr(), ptr::null_mut(), ptr::null_mut(), winsize as *const Winsize as *mut _, @@ -249,8 +249,8 @@ pub fn openpty<'a, 'b, T: Into>, U: Into let inner_termios = termios.get_libc_termios(); unsafe { libc::openpty( - &mut master, - &mut slave, + master.as_mut_ptr(), + slave.as_mut_ptr(), ptr::null_mut(), &*inner_termios as *const libc::termios as *mut _, ptr::null_mut(), @@ -260,8 +260,8 @@ pub fn openpty<'a, 'b, T: Into>, U: Into (None, None) => { unsafe { libc::openpty( - &mut master, - &mut slave, + master.as_mut_ptr(), + slave.as_mut_ptr(), ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), @@ -273,10 +273,12 @@ pub fn openpty<'a, 'b, T: Into>, U: Into Errno::result(ret)?; - Ok(OpenptyResult { - master, - slave, - }) + unsafe { + Ok(OpenptyResult { + master: master.assume_init(), + slave: slave.assume_init(), + }) + } } /// Create a new pseudoterminal, returning the master file descriptor and forked pid. @@ -294,7 +296,7 @@ pub fn forkpty<'a, 'b, T: Into>, U: Into use unistd::Pid; use unistd::ForkResult::*; - let mut master: libc::c_int = unsafe { mem::uninitialized() }; + let mut master = mem::MaybeUninit::::uninit(); let term = match termios.into() { Some(termios) => { @@ -310,7 +312,7 @@ pub fn forkpty<'a, 'b, T: Into>, U: Into .unwrap_or(ptr::null_mut()); let res = unsafe { - libc::forkpty(&mut master, ptr::null_mut(), term, win) + libc::forkpty(master.as_mut_ptr(), ptr::null_mut(), term, win) }; let fork_result = Errno::result(res).map(|res| match res { @@ -318,9 +320,11 @@ pub fn forkpty<'a, 'b, T: Into>, U: Into res => Parent { child: Pid::from_raw(res) }, })?; - Ok(ForkptyResult { - master, - fork_result, - }) + unsafe { + Ok(ForkptyResult { + master: master.assume_init(), + fork_result, + }) + } } diff --git a/src/sys/ptrace/linux.rs b/src/sys/ptrace/linux.rs index df15e66..b2b984c 100644 --- a/src/sys/ptrace/linux.rs +++ b/src/sys/ptrace/linux.rs @@ -221,16 +221,15 @@ pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> { /// and therefore use the data field to return values. This function handles these /// requests. fn ptrace_get_data(request: Request, pid: Pid) -> Result { - // Creates an uninitialized pointer to store result in - let data: T = unsafe { mem::uninitialized() }; + let mut data = mem::MaybeUninit::uninit(); let res = unsafe { libc::ptrace(request as RequestType, libc::pid_t::from(pid), ptr::null_mut::(), - &data as *const _ as *const c_void) + data.as_mut_ptr() as *const _ as *const c_void) }; Errno::result(res)?; - Ok(data) + Ok(unsafe{ data.assume_init() }) } unsafe fn ptrace_other(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result { diff --git a/src/sys/quota.rs b/src/sys/quota.rs index 8946fca..b056c84 100644 --- a/src/sys/quota.rs +++ b/src/sys/quota.rs @@ -94,8 +94,7 @@ libc_bitflags!( ); /// Wrapper type for `if_dqblk` -// FIXME: Change to repr(transparent) -#[repr(C)] +#[repr(transparent)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct Dqblk(libc::dqblk); @@ -260,9 +259,9 @@ pub fn quotactl_sync(which: QuotaType, special: Option<&P>) /// Get disk quota limits and current usage for the given user/group id. pub fn quotactl_get(which: QuotaType, special: &P, id: c_int) -> Result { - let mut dqblk = unsafe { mem::uninitialized() }; - quotactl(QuotaCmd(QuotaSubCmd::Q_GETQUOTA, which), Some(special), id, &mut dqblk as *mut _ as *mut c_char)?; - dqblk + let mut dqblk = mem::MaybeUninit::uninit(); + quotactl(QuotaCmd(QuotaSubCmd::Q_GETQUOTA, which), Some(special), id, dqblk.as_mut_ptr() as *mut c_char)?; + Ok(unsafe{ Dqblk(dqblk.assume_init())}) } /// Configure quota values for the specified fields for a given user/group id. diff --git a/src/sys/select.rs b/src/sys/select.rs index 9d60ffa..32569ac 100644 --- a/src/sys/select.rs +++ b/src/sys/select.rs @@ -9,16 +9,17 @@ use sys::time::{TimeSpec, TimeVal}; pub use libc::FD_SETSIZE; -// FIXME: Change to repr(transparent) once it's stable -#[repr(C)] +#[repr(transparent)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct FdSet(libc::fd_set); impl FdSet { pub fn new() -> FdSet { - let mut fdset = unsafe { mem::uninitialized() }; - unsafe { libc::FD_ZERO(&mut fdset) }; - FdSet(fdset) + let mut fdset = mem::MaybeUninit::uninit(); + unsafe { + libc::FD_ZERO(fdset.as_mut_ptr()); + FdSet(fdset.assume_init()) + } } pub fn insert(&mut self, fd: RawFd) { diff --git a/src/sys/signal.rs b/src/sys/signal.rs index 51df7b1..41a62e6 100644 --- a/src/sys/signal.rs +++ b/src/sys/signal.rs @@ -335,17 +335,17 @@ pub struct SigSet { impl SigSet { pub fn all() -> SigSet { - let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() }; - let _ = unsafe { libc::sigfillset(&mut sigset as *mut libc::sigset_t) }; + let mut sigset = mem::MaybeUninit::uninit(); + let _ = unsafe { libc::sigfillset(sigset.as_mut_ptr()) }; - SigSet { sigset } + unsafe{ SigSet { sigset: sigset.assume_init() } } } pub fn empty() -> SigSet { - let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() }; - let _ = unsafe { libc::sigemptyset(&mut sigset as *mut libc::sigset_t) }; + let mut sigset = mem::MaybeUninit::uninit(); + let _ = unsafe { libc::sigemptyset(sigset.as_mut_ptr()) }; - SigSet { sigset } + unsafe{ SigSet { sigset: sigset.assume_init() } } } pub fn add(&mut self, signal: Signal) { @@ -380,9 +380,9 @@ impl SigSet { /// Gets the currently blocked (masked) set of signals for the calling thread. pub fn thread_get_mask() -> Result { - let mut oldmask: SigSet = unsafe { mem::uninitialized() }; - pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(&mut oldmask))?; - Ok(oldmask) + let mut oldmask = mem::MaybeUninit::uninit(); + do_pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(oldmask.as_mut_ptr()))?; + Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}}) } /// Sets the set of signals as the signal mask for the calling thread. @@ -402,18 +402,20 @@ impl SigSet { /// Sets the set of signals as the signal mask, and returns the old mask. pub fn thread_swap_mask(&self, how: SigmaskHow) -> Result { - let mut oldmask: SigSet = unsafe { mem::uninitialized() }; - pthread_sigmask(how, Some(self), Some(&mut oldmask))?; - Ok(oldmask) + let mut oldmask = mem::MaybeUninit::uninit(); + do_pthread_sigmask(how, Some(self), Some(oldmask.as_mut_ptr()))?; + Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}}) } /// Suspends execution of the calling thread until one of the signals in the /// signal mask becomes pending, and returns the accepted signal. pub fn wait(&self) -> Result { - let mut signum: libc::c_int = unsafe { mem::uninitialized() }; - let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, &mut signum) }; + let mut signum = mem::MaybeUninit::uninit(); + let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, signum.as_mut_ptr()) }; - Errno::result(res).map(|_| Signal::from_c_int(signum).unwrap()) + Errno::result(res).map(|_| unsafe { + Signal::from_c_int(signum.assume_init()).unwrap() + }) } } @@ -451,20 +453,23 @@ impl SigAction { /// is the `SigAction` variant). `mask` specifies other signals to block during execution of /// the signal-catching function. pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction { - let mut s = unsafe { mem::uninitialized::() }; - s.sa_sigaction = match handler { - SigHandler::SigDfl => libc::SIG_DFL, - SigHandler::SigIgn => libc::SIG_IGN, - SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize, - SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize, - }; - s.sa_flags = match handler { - SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(), - _ => (flags - SaFlags::SA_SIGINFO).bits(), - }; - s.sa_mask = mask.sigset; + let mut s = mem::MaybeUninit::::uninit(); + unsafe { + let p = s.as_mut_ptr(); + (*p).sa_sigaction = match handler { + SigHandler::SigDfl => libc::SIG_DFL, + SigHandler::SigIgn => libc::SIG_IGN, + SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize, + SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize, + }; + (*p).sa_flags = match handler { + SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(), + _ => (flags - SaFlags::SA_SIGINFO).bits(), + }; + (*p).sa_mask = mask.sigset; - SigAction { sigaction: s } + SigAction { sigaction: s.assume_init() } + } } /// Returns the flags set on the action. @@ -501,12 +506,13 @@ impl SigAction { /// the body of the signal-catching function. Be certain to only make syscalls that are explicitly /// marked safe for signal handlers and only share global data using atomics. pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result { - let mut oldact = mem::uninitialized::(); + let mut oldact = mem::MaybeUninit::::uninit(); - let res = - libc::sigaction(signal as libc::c_int, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction); + let res = libc::sigaction(signal as libc::c_int, + &sigaction.sigaction as *const libc::sigaction, + oldact.as_mut_ptr()); - Errno::result(res).map(|_| SigAction { sigaction: oldact }) + Errno::result(res).map(|_| SigAction { sigaction: oldact.assume_init() }) } /// Signal management (see [signal(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html)) @@ -582,6 +588,25 @@ pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result }) } +fn do_pthread_sigmask(how: SigmaskHow, + set: Option<&SigSet>, + oldset: Option<*mut libc::sigset_t>) -> Result<()> { + if set.is_none() && oldset.is_none() { + return Ok(()) + } + + let res = unsafe { + // if set or oldset is None, pass in null pointers instead + libc::pthread_sigmask(how as libc::c_int, + set.map_or_else(ptr::null::, + |s| &s.sigset as *const libc::sigset_t), + oldset.unwrap_or(ptr::null_mut()) + ) + }; + + Errno::result(res).map(drop) +} + /// Manages the signal mask (set of blocked signals) for the calling thread. /// /// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set. @@ -599,21 +624,9 @@ pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result /// or [`sigprocmask`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html) man pages. pub fn pthread_sigmask(how: SigmaskHow, set: Option<&SigSet>, - oldset: Option<&mut SigSet>) -> Result<()> { - if set.is_none() && oldset.is_none() { - return Ok(()) - } - - let res = unsafe { - // if set or oldset is None, pass in null pointers instead - libc::pthread_sigmask(how as libc::c_int, - set.map_or_else(ptr::null::, - |s| &s.sigset as *const libc::sigset_t), - oldset.map_or_else(ptr::null_mut::, - |os| &mut os.sigset as *mut libc::sigset_t)) - }; - - Errno::result(res).map(drop) + oldset: Option<&mut SigSet>) -> Result<()> +{ + do_pthread_sigmask(how, set, oldset.map(|os| &mut os.sigset as *mut _ )) } /// Examine and change blocked signals. diff --git a/src/sys/signalfd.rs b/src/sys/signalfd.rs index 5425a27..6482eeb 100644 --- a/src/sys/signalfd.rs +++ b/src/sys/signalfd.rs @@ -98,10 +98,15 @@ impl SignalFd { } pub fn read_signal(&mut self) -> Result> { - let mut buffer: [u8; SIGNALFD_SIGINFO_SIZE] = unsafe { mem::uninitialized() }; + let mut buffer = mem::MaybeUninit::<[u8; SIGNALFD_SIGINFO_SIZE]>::uninit(); - match unistd::read(self.0, &mut buffer) { - Ok(SIGNALFD_SIGINFO_SIZE) => Ok(Some(unsafe { mem::transmute(buffer) })), + let res = Errno::result(unsafe { + libc::read(self.0, + buffer.as_mut_ptr() as *mut libc::c_void, + SIGNALFD_SIGINFO_SIZE as libc::size_t) + }).map(|r| r as usize); + match res { + Ok(SIGNALFD_SIGINFO_SIZE) => Ok(Some(unsafe { mem::transmute(buffer.assume_init()) })), Ok(_) => unreachable!("partial read on signalfd"), Err(Error::Sys(Errno::EAGAIN)) => Ok(None), Err(error) => Err(error) diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs index cbec71f..2ad453f 100644 --- a/src/sys/socket/addr.rs +++ b/src/sys/socket/addr.rs @@ -475,9 +475,7 @@ impl Ipv6Addr { #[allow(clippy::many_single_char_names)] #[allow(clippy::too_many_arguments)] pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { - let mut in6_addr_var: libc::in6_addr = unsafe{mem::uninitialized()}; - in6_addr_var.s6_addr = to_u8_array!(a,b,c,d,e,f,g,h); - Ipv6Addr(in6_addr_var) + Ipv6Addr(libc::in6_addr{s6_addr: to_u8_array!(a,b,c,d,e,f,g,h)}) } pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr { diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 662d880..beaa69a 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -854,20 +854,21 @@ pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage], ptr::null_mut() }; - let mhdr = { + let mhdr = unsafe { // Musl's msghdr has private fields, so this is the only way to // initialize it. - let mut mhdr: msghdr = unsafe{mem::uninitialized()}; - mhdr.msg_name = name as *mut _; - mhdr.msg_namelen = namelen; + let mut mhdr = mem::MaybeUninit::::uninit(); + let p = mhdr.as_mut_ptr(); + (*p).msg_name = name as *mut _; + (*p).msg_namelen = namelen; // transmute iov into a mutable pointer. sendmsg doesn't really mutate // the buffer, but the standard says that it takes a mutable pointer - mhdr.msg_iov = iov.as_ptr() as *mut _; - mhdr.msg_iovlen = iov.len() as _; - mhdr.msg_control = cmsg_ptr; - mhdr.msg_controllen = capacity as _; - mhdr.msg_flags = 0; - mhdr + (*p).msg_iov = iov.as_ptr() as *mut _; + (*p).msg_iovlen = iov.len() as _; + (*p).msg_control = cmsg_ptr; + (*p).msg_controllen = capacity as _; + (*p).msg_flags = 0; + mhdr.assume_init() }; // Encode each cmsg. This must happen after initializing the header because @@ -898,7 +899,7 @@ pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>], cmsg_buffer: Option<&'a mut dyn CmsgBuffer>, flags: MsgFlags) -> Result> { - let mut address: sockaddr_storage = unsafe { mem::uninitialized() }; + let mut address = mem::MaybeUninit::uninit(); let (msg_control, msg_controllen) = match cmsg_buffer { Some(cmsgspace) => { let msg_buf = cmsgspace.as_bytes_mut(); @@ -906,18 +907,19 @@ pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>], }, None => (ptr::null_mut(), 0), }; - let mut mhdr = { + let mut mhdr = unsafe { // Musl's msghdr has private fields, so this is the only way to // initialize it. - let mut mhdr: msghdr = unsafe{mem::uninitialized()}; - mhdr.msg_name = &mut address as *mut sockaddr_storage as *mut c_void; - mhdr.msg_namelen = mem::size_of::() as socklen_t; - mhdr.msg_iov = iov.as_ptr() as *mut iovec; - mhdr.msg_iovlen = iov.len() as _; - mhdr.msg_control = msg_control as *mut c_void; - mhdr.msg_controllen = msg_controllen as _; - mhdr.msg_flags = 0; - mhdr + let mut mhdr = mem::MaybeUninit::::uninit(); + let p = mhdr.as_mut_ptr(); + (*p).msg_name = address.as_mut_ptr() as *mut c_void; + (*p).msg_namelen = mem::size_of::() as socklen_t; + (*p).msg_iov = iov.as_ptr() as *mut iovec; + (*p).msg_iovlen = iov.len() as _; + (*p).msg_control = msg_control as *mut c_void; + (*p).msg_controllen = msg_controllen as _; + (*p).msg_flags = 0; + mhdr.assume_init() }; let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) }; @@ -935,7 +937,9 @@ pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>], }; let address = unsafe { - sockaddr_storage_to_addr(&address, mhdr.msg_namelen as usize).ok() + sockaddr_storage_to_addr(&address.assume_init(), + mhdr.msg_namelen as usize + ).ok() }; RecvMsg { bytes: r as usize, @@ -1190,18 +1194,18 @@ pub fn setsockopt(fd: RawFd, opt: O, val: &O::Val) -> Result<()> /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html) pub fn getpeername(fd: RawFd) -> Result { unsafe { - let mut addr: sockaddr_storage = mem::uninitialized(); + let mut addr = mem::MaybeUninit::uninit(); let mut len = mem::size_of::() as socklen_t; let ret = libc::getpeername( fd, - &mut addr as *mut libc::sockaddr_storage as *mut libc::sockaddr, + addr.as_mut_ptr() as *mut libc::sockaddr, &mut len ); Errno::result(ret)?; - sockaddr_storage_to_addr(&addr, len as usize) + sockaddr_storage_to_addr(&addr.assume_init(), len as usize) } } @@ -1210,18 +1214,18 @@ pub fn getpeername(fd: RawFd) -> Result { /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html) pub fn getsockname(fd: RawFd) -> Result { unsafe { - let mut addr: sockaddr_storage = mem::uninitialized(); + let mut addr = mem::MaybeUninit::uninit(); let mut len = mem::size_of::() as socklen_t; let ret = libc::getsockname( fd, - &mut addr as *mut libc::sockaddr_storage as *mut libc::sockaddr, + addr.as_mut_ptr() as *mut libc::sockaddr, &mut len ); Errno::result(ret)?; - sockaddr_storage_to_addr(&addr, len as usize) + sockaddr_storage_to_addr(&addr.assume_init(), len as usize) } } diff --git a/src/sys/stat.rs b/src/sys/stat.rs index 66c8c9d..2958225 100644 --- a/src/sys/stat.rs +++ b/src/sys/stat.rs @@ -78,49 +78,49 @@ pub fn umask(mode: Mode) -> Mode { } pub fn stat(path: &P) -> Result { - let mut dst = unsafe { mem::uninitialized() }; + let mut dst = mem::MaybeUninit::uninit(); let res = path.with_nix_path(|cstr| { unsafe { - libc::stat(cstr.as_ptr(), &mut dst as *mut FileStat) + libc::stat(cstr.as_ptr(), dst.as_mut_ptr()) } })?; Errno::result(res)?; - Ok(dst) + Ok(unsafe{dst.assume_init()}) } pub fn lstat(path: &P) -> Result { - let mut dst = unsafe { mem::uninitialized() }; + let mut dst = mem::MaybeUninit::uninit(); let res = path.with_nix_path(|cstr| { unsafe { - libc::lstat(cstr.as_ptr(), &mut dst as *mut FileStat) + libc::lstat(cstr.as_ptr(), dst.as_mut_ptr()) } })?; Errno::result(res)?; - Ok(dst) + Ok(unsafe{dst.assume_init()}) } pub fn fstat(fd: RawFd) -> Result { - let mut dst = unsafe { mem::uninitialized() }; - let res = unsafe { libc::fstat(fd, &mut dst as *mut FileStat) }; + let mut dst = mem::MaybeUninit::uninit(); + let res = unsafe { libc::fstat(fd, dst.as_mut_ptr()) }; Errno::result(res)?; - Ok(dst) + Ok(unsafe{dst.assume_init()}) } pub fn fstatat(dirfd: RawFd, pathname: &P, f: AtFlags) -> Result { - let mut dst = unsafe { mem::uninitialized() }; + let mut dst = mem::MaybeUninit::uninit(); let res = pathname.with_nix_path(|cstr| { - unsafe { libc::fstatat(dirfd, cstr.as_ptr(), &mut dst as *mut FileStat, f.bits() as libc::c_int) } + unsafe { libc::fstatat(dirfd, cstr.as_ptr(), dst.as_mut_ptr(), f.bits() as libc::c_int) } })?; Errno::result(res)?; - Ok(dst) + Ok(unsafe{dst.assume_init()}) } /// Change the file permission bits of the file specified by a file descriptor. diff --git a/src/sys/statfs.rs b/src/sys/statfs.rs index d4596bf..c71b576 100644 --- a/src/sys/statfs.rs +++ b/src/sys/statfs.rs @@ -15,6 +15,7 @@ pub type fsid_t = libc::__fsid_t; pub type fsid_t = libc::fsid_t; #[derive(Clone, Copy)] +#[repr(transparent)] pub struct Statfs(libc::statfs); #[cfg(target_os = "freebsd")] @@ -434,16 +435,17 @@ impl Debug for Statfs { pub fn statfs(path: &P) -> Result { unsafe { - let mut stat: Statfs = mem::uninitialized(); - let res = path.with_nix_path(|path| libc::statfs(path.as_ptr(), &mut stat.0))?; - Errno::result(res).map(|_| stat) + let mut stat = mem::MaybeUninit::::uninit(); + let res = path.with_nix_path(|path| libc::statfs(path.as_ptr(), stat.as_mut_ptr()))?; + Errno::result(res).map(|_| Statfs(stat.assume_init())) } } pub fn fstatfs(fd: &T) -> Result { unsafe { - let mut stat: Statfs = mem::uninitialized(); - Errno::result(libc::fstatfs(fd.as_raw_fd(), &mut stat.0)).map(|_| stat) + let mut stat = mem::MaybeUninit::::uninit(); + Errno::result(libc::fstatfs(fd.as_raw_fd(), stat.as_mut_ptr())) + .map(|_| Statfs(stat.assume_init())) } } diff --git a/src/sys/statvfs.rs b/src/sys/statvfs.rs index e598036..2614780 100644 --- a/src/sys/statvfs.rs +++ b/src/sys/statvfs.rs @@ -55,8 +55,7 @@ libc_bitflags!( /// Wrapper around the POSIX `statvfs` struct /// /// For more information see the [`statvfs(3)` man pages](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_statvfs.h.html). -// FIXME: Replace with repr(transparent) -#[repr(C)] +#[repr(transparent)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct Statvfs(libc::statvfs); @@ -124,12 +123,12 @@ impl Statvfs { pub fn statvfs(path: &P) -> Result { unsafe { Errno::clear(); - let mut stat: Statvfs = mem::uninitialized(); + let mut stat = mem::MaybeUninit::::uninit(); let res = path.with_nix_path(|path| - libc::statvfs(path.as_ptr(), &mut stat.0) + libc::statvfs(path.as_ptr(), stat.as_mut_ptr()) )?; - Errno::result(res).map(|_| stat) + Errno::result(res).map(|_| Statvfs(stat.assume_init())) } } @@ -137,8 +136,9 @@ pub fn statvfs(path: &P) -> Result { pub fn fstatvfs(fd: &T) -> Result { unsafe { Errno::clear(); - let mut stat: Statvfs = mem::uninitialized(); - Errno::result(libc::fstatvfs(fd.as_raw_fd(), &mut stat.0)).map(|_| stat) + let mut stat = mem::MaybeUninit::::uninit(); + Errno::result(libc::fstatvfs(fd.as_raw_fd(), stat.as_mut_ptr())) + .map(|_| Statvfs(stat.assume_init())) } } diff --git a/src/sys/sysinfo.rs b/src/sys/sysinfo.rs index 4c8e389..9807b44 100644 --- a/src/sys/sysinfo.rs +++ b/src/sys/sysinfo.rs @@ -7,6 +7,7 @@ use errno::Errno; /// System info structure returned by `sysinfo`. #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] +#[repr(transparent)] pub struct SysInfo(libc::sysinfo); impl SysInfo { @@ -66,7 +67,7 @@ impl SysInfo { /// /// [See `sysinfo(2)`](http://man7.org/linux/man-pages/man2/sysinfo.2.html). pub fn sysinfo() -> Result { - let mut info: libc::sysinfo = unsafe { mem::uninitialized() }; - let res = unsafe { libc::sysinfo(&mut info) }; - Errno::result(res).map(|_| SysInfo(info)) + let mut info = mem::MaybeUninit::uninit(); + let res = unsafe { libc::sysinfo(info.as_mut_ptr()) }; + Errno::result(res).map(|_| unsafe{ SysInfo(info.assume_init()) }) } diff --git a/src/sys/termios.rs b/src/sys/termios.rs index c7cdf10..978e6a9 100644 --- a/src/sys/termios.rs +++ b/src/sys/termios.rs @@ -1045,13 +1045,13 @@ pub fn cfmakesane(termios: &mut Termios) { /// this structure *will not* reconfigure the port, instead the modifications should be done to /// the `Termios` structure and then the port should be reconfigured using `tcsetattr()`. pub fn tcgetattr(fd: RawFd) -> Result { - let mut termios: libc::termios = unsafe { mem::uninitialized() }; + let mut termios = mem::MaybeUninit::uninit(); - let res = unsafe { libc::tcgetattr(fd, &mut termios) }; + let res = unsafe { libc::tcgetattr(fd, termios.as_mut_ptr()) }; Errno::result(res)?; - Ok(termios.into()) + unsafe { Ok(termios.assume_init().into()) } } /// Set the configuration for a terminal (see diff --git a/src/sys/utsname.rs b/src/sys/utsname.rs index ab09c7d..bf1a814 100644 --- a/src/sys/utsname.rs +++ b/src/sys/utsname.rs @@ -3,8 +3,8 @@ use libc::{self, c_char}; use std::ffi::CStr; use std::str::from_utf8_unchecked; -#[repr(C)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[repr(transparent)] pub struct UtsName(libc::utsname); impl UtsName { @@ -31,9 +31,9 @@ impl UtsName { pub fn uname() -> UtsName { unsafe { - let mut ret: UtsName = mem::uninitialized(); - libc::uname(&mut ret.0); - ret + let mut ret = mem::MaybeUninit::uninit(); + libc::uname(ret.as_mut_ptr()); + UtsName(ret.assume_init()) } } diff --git a/src/ucontext.rs b/src/ucontext.rs index 5e10e7d..1bcfdd9 100644 --- a/src/ucontext.rs +++ b/src/ucontext.rs @@ -14,11 +14,11 @@ pub struct UContext { impl UContext { #[cfg(not(target_env = "musl"))] pub fn get() -> Result { - let mut context: libc::ucontext_t = unsafe { mem::uninitialized() }; - let res = unsafe { - libc::getcontext(&mut context as *mut libc::ucontext_t) - }; - Errno::result(res).map(|_| UContext { context: context }) + let mut context = mem::MaybeUninit::::uninit(); + let res = unsafe { libc::getcontext(context.as_mut_ptr()) }; + Errno::result(res).map(|_| unsafe { + UContext { context: context.assume_init()} + }) } #[cfg(not(target_env = "musl"))] diff --git a/src/unistd.rs b/src/unistd.rs index 1099965..4dca01b 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -1009,13 +1009,13 @@ pub fn lseek64(fd: RawFd, offset: libc::off64_t, whence: Whence) -> Result Result<(RawFd, RawFd)> { unsafe { - let mut fds: [c_int; 2] = mem::uninitialized(); + let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit(); - let res = libc::pipe(fds.as_mut_ptr()); + let res = libc::pipe(fds.as_mut_ptr() as *mut c_int); Errno::result(res)?; - Ok((fds[0], fds[1])) + Ok((fds.assume_init()[0], fds.assume_init()[1])) } } @@ -1036,13 +1036,15 @@ pub fn pipe() -> Result<(RawFd, RawFd)> { target_os = "netbsd", target_os = "openbsd"))] pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> { - let mut fds: [c_int; 2] = unsafe { mem::uninitialized() }; + let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit(); - let res = unsafe { libc::pipe2(fds.as_mut_ptr(), flags.bits()) }; + let res = unsafe { + libc::pipe2(fds.as_mut_ptr() as *mut c_int, flags.bits()) + }; Errno::result(res)?; - Ok((fds[0], fds[1])) + unsafe { Ok((fds.assume_init()[0], fds.assume_init()[1])) } } /// Like `pipe`, but allows setting certain file descriptor flags. @@ -1058,15 +1060,17 @@ pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> { note="pipe2(2) is not actually atomic on these platforms. Use pipe(2) and fcntl(2) instead" )] pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> { - let mut fds: [c_int; 2] = unsafe { mem::uninitialized() }; + let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit(); - let res = unsafe { libc::pipe(fds.as_mut_ptr()) }; + let res = unsafe { libc::pipe(fds.as_mut_ptr() as *mut c_int) }; Errno::result(res)?; - pipe2_setflags(fds[0], fds[1], flags)?; + unsafe { + pipe2_setflags(fds.assume_init()[0], fds.assume_init()[1], flags)?; - Ok((fds[0], fds[1])) + Ok((fds.assume_init()[0], fds.assume_init()[1])) + } } #[cfg(any(target_os = "ios", target_os = "macos"))] diff --git a/test/sys/test_ptrace.rs b/test/sys/test_ptrace.rs index 24d9b52..a563092 100644 --- a/test/sys/test_ptrace.rs +++ b/test/sys/test_ptrace.rs @@ -46,7 +46,7 @@ fn test_ptrace_getsiginfo() { #[test] #[cfg(any(target_os = "android", target_os = "linux"))] fn test_ptrace_setsiginfo() { - let siginfo = unsafe { mem::uninitialized() }; + let siginfo = unsafe { mem::zeroed() }; if let Err(Error::UnsupportedOperation) = ptrace::setsiginfo(getpid(), &siginfo) { panic!("ptrace_setsiginfo returns Error::UnsupportedOperation!"); }