From 242a6a02457ed298e3273f001bd76cca10dc2f08 Mon Sep 17 00:00:00 2001 From: Matthew Gregan Date: Tue, 20 Jun 2017 15:30:48 +1200 Subject: [PATCH] Fix sendmsg on macOS when passing a zero entry cmsgs array. --- CHANGELOG.md | 2 ++ src/sys/socket/mod.rs | 8 +++++++- test/sys/test_socket.rs | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9eb9b913a4..7499566f48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). `MacOS/x86_64,i686` ([#553](https://github.com/nix-rust/nix/pull/553)), `NetBSD/x64_64` ([#538](https://github.com/nix-rust/nix/pull/538)), and `FreeBSD/x86_64,i686` ([#536](https://github.com/nix-rust/nix/pull/536)). +- Fixed `sys::socket::sendmsg` with zero entry `cmsgs` parameter. + ([#623](https://github.com/nix-rust/nix/pull/623)) ## [0.8.1] 2017-04-16 diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 3a7e5eba7c..042f9a0060 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -277,12 +277,18 @@ pub fn sendmsg<'a>(fd: RawFd, iov: &[IoVec<&'a [u8]>], cmsgs: &[ControlMessage<' None => (0 as *const _, 0), }; + let cmsg_ptr = if capacity > 0 { + cmsg_buffer.as_ptr() as *const c_void + } else { + ptr::null() + }; + let mhdr = msghdr { msg_name: name as *const c_void, msg_namelen: namelen, msg_iov: iov.as_ptr(), msg_iovlen: iov.len() as size_t, - msg_control: cmsg_buffer.as_ptr() as *const c_void, + msg_control: cmsg_ptr, msg_controllen: capacity as size_t, msg_flags: 0, }; diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index b5465aa0b6..8ba195addb 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -145,6 +145,39 @@ pub fn test_scm_rights() { close(w).unwrap(); } +#[test] +pub fn test_sendmsg_empty_cmsg() { + use nix::sys::uio::IoVec; + use nix::unistd::close; + use nix::sys::socket::{socketpair, sendmsg, recvmsg, + AddressFamily, SockType, SockFlag, + CmsgSpace, MsgFlags, + MSG_TRUNC, MSG_CTRUNC}; + + let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, 0, + SockFlag::empty()) + .unwrap(); + + { + let iov = [IoVec::from_slice(b"hello")]; + assert_eq!(sendmsg(fd1, &iov, &[], MsgFlags::empty(), None).unwrap(), 5); + close(fd1).unwrap(); + } + + { + let mut buf = [0u8; 5]; + let iov = [IoVec::from_mut_slice(&mut buf[..])]; + let mut cmsgspace: CmsgSpace<[RawFd; 1]> = CmsgSpace::new(); + let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap(); + + for _ in msg.cmsgs() { + panic!("unexpected cmsg"); + } + assert_eq!(msg.flags & (MSG_TRUNC | MSG_CTRUNC), MsgFlags::empty()); + close(fd2).unwrap(); + } +} + // Test creating and using named unix domain sockets #[test] pub fn test_unixdomain() {