summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/sys/socket/mod.rs8
-rw-r--r--test/sys/test_socket.rs39
3 files changed, 47 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 15f42a45..4ceae9c2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -60,6 +60,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Added `nix::ptrace` on all Linux-kernel-based platforms
[#624](https://github.com/nix-rust/nix/pull/624). Previously it was
only available on x86, x86-64, and ARM, and also not on Android.
+- 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 88fe02fe..c11b5367 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 b5465aa0..9f9c9bf0 100644
--- a/test/sys/test_socket.rs
+++ b/test/sys/test_socket.rs
@@ -131,7 +131,7 @@ pub fn test_scm_rights() {
panic!("unexpected cmsg");
}
}
- assert_eq!(msg.flags & (MSG_TRUNC | MSG_CTRUNC), MsgFlags::empty());
+ assert!(!msg.flags.intersects(MSG_TRUNC | MSG_CTRUNC));
close(fd2).unwrap();
}
@@ -145,6 +145,43 @@ pub fn test_scm_rights() {
close(w).unwrap();
}
+// Verify `sendmsg` builds a valid `msghdr` when passing an empty
+// `cmsgs` argument. This should result in a msghdr with a nullptr
+// msg_control field and a msg_controllen of 0 when calling into the
+// raw `sendmsg`.
+#[test]
+pub fn test_sendmsg_empty_cmsgs() {
+ 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!(!msg.flags.intersects(MSG_TRUNC | MSG_CTRUNC));
+ close(fd2).unwrap();
+ }
+}
+
// Test creating and using named unix domain sockets
#[test]
pub fn test_unixdomain() {