diff options
author | Alan Somers <asomers@gmail.com> | 2019-01-15 09:23:33 -0700 |
---|---|---|
committer | Alan Somers <asomers@gmail.com> | 2019-02-14 10:15:49 -0700 |
commit | 368b9fe9436734f7fccffa2fdf3e723ee20fb836 (patch) | |
tree | 7477402cb795d097f03c88509679d5b8b926f59a /src/sys/socket/mod.rs | |
parent | ed1c90d6bc9871d9881e8fcb05370752b6a5d25b (diff) | |
download | nix-368b9fe9436734f7fccffa2fdf3e723ee20fb836.zip |
Fix error handling of RecvMsg
There were two problems:
1) It would always return Ok, even on error
2) It could panic if there was an error, because
sockaddr_storage_to_addr would be called on uninitialized memory.
Diffstat (limited to 'src/sys/socket/mod.rs')
-rw-r--r-- | src/sys/socket/mod.rs | 45 |
1 files changed, 26 insertions, 19 deletions
diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 9527d0b3..ffb68157 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -900,6 +900,9 @@ pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage], /// Receive message in scatter-gather vectors from a socket, and /// optionally receive ancillary data into the provided buffer. /// If no ancillary data is desired, use () as the type parameter. +/// +/// # References +/// [recvmsg(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html) pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>], cmsg_buffer: Option<&'a mut CmsgSpace<T>>, flags: MsgFlags) -> Result<RecvMsg<'a>> @@ -923,26 +926,30 @@ pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>], mhdr }; - let _ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) }; - - let cmsghdr = unsafe { - if mhdr.msg_controllen > 0 { - // got control message(s) - debug_assert!(!mhdr.msg_control.is_null()); - debug_assert!(msg_controllen >= mhdr.msg_controllen as usize); - CMSG_FIRSTHDR(&mhdr as *const msghdr) - } else { - ptr::null() - }.as_ref() - }; + let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) }; + + Errno::result(ret).map(|_| { + let cmsghdr = unsafe { + if mhdr.msg_controllen > 0 { + // got control message(s) + debug_assert!(!mhdr.msg_control.is_null()); + debug_assert!(msg_controllen >= mhdr.msg_controllen as usize); + CMSG_FIRSTHDR(&mhdr as *const msghdr) + } else { + ptr::null() + }.as_ref() + }; - Ok(unsafe { RecvMsg { - cmsghdr, - address: sockaddr_storage_to_addr(&address, - mhdr.msg_namelen as usize).ok(), - flags: MsgFlags::from_bits_truncate(mhdr.msg_flags), - mhdr, - } }) + let address = unsafe { + sockaddr_storage_to_addr(&address, mhdr.msg_namelen as usize).ok() + }; + RecvMsg { + cmsghdr, + address, + flags: MsgFlags::from_bits_truncate(mhdr.msg_flags), + mhdr, + } + }) } |