diff --git a/libc-test/tests/cmsg.rs b/libc-test/tests/cmsg.rs index b9573e1d040a..57dbefb2d203 100644 --- a/libc-test/tests/cmsg.rs +++ b/libc-test/tests/cmsg.rs @@ -17,8 +17,6 @@ mod t { extern "C" { pub fn cmsg_firsthdr(msgh: *const msghdr) -> *mut cmsghdr; - // see below - #[cfg(not(target_arch = "sparc64"))] pub fn cmsg_nxthdr(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr; pub fn cmsg_space(length: c_uint) -> usize; pub fn cmsg_len(length: c_uint) -> usize; @@ -58,9 +56,6 @@ mod t { } } - // Skip on sparc64 - // https://github.com/rust-lang/libc/issues/1239 - #[cfg(not(target_arch = "sparc64"))] #[test] fn test_cmsg_nxthdr() { // Helps to align the buffer on the stack. @@ -69,32 +64,40 @@ mod t { const CAPACITY: usize = 512; let mut buffer = Align8([0_u8; CAPACITY]); + let pcmsghdr = buffer.0.as_mut_ptr().cast::(); + let mut mhdr: msghdr = unsafe { mem::zeroed() }; - for start_ofs in 0..64 { - let pcmsghdr = buffer.0.as_mut_ptr().cast::(); - mhdr.msg_control = pcmsghdr.cast::(); - mhdr.msg_controllen = (160 - start_ofs) as _; - for cmsg_len in 0..64 { - // Address must be a multiple of 0x4 for testing on AIX. - if cfg!(target_os = "aix") && cmsg_len % std::mem::size_of::() != 0 { - continue; - } - for next_cmsg_len in 0..32 { + mhdr.msg_control = pcmsghdr.cast::(); + + for trunc in 0..64 { + mhdr.msg_controllen = (160 - trunc) as _; + + for cmsg_payload_len in 0..64 { + let mut current_cmsghdr_ptr = pcmsghdr; + assert!(!current_cmsghdr_ptr.is_null()); + let mut count = 0; + + while !current_cmsghdr_ptr.is_null() { unsafe { - pcmsghdr.cast::().write_bytes(0, CAPACITY); - (*pcmsghdr).cmsg_len = cmsg_len as _; - let libc_next = libc::CMSG_NXTHDR(&mhdr, pcmsghdr); - let next = cmsg_nxthdr(&mhdr, pcmsghdr); - assert_eq!(libc_next, next); - - if !libc_next.is_null() { - (*libc_next).cmsg_len = next_cmsg_len; - let libc_next = libc::CMSG_NXTHDR(&mhdr, pcmsghdr); - let next = cmsg_nxthdr(&mhdr, pcmsghdr); - assert_eq!(libc_next, next); - } + (*current_cmsghdr_ptr).cmsg_len = + libc::CMSG_LEN(cmsg_payload_len as _) as _; + + let libc_next = libc::CMSG_NXTHDR(&mhdr, current_cmsghdr_ptr); + let system_next = cmsg_nxthdr(&mhdr, current_cmsghdr_ptr); + assert_eq!( + system_next, libc_next, + "msg_crontrollen: {}, payload_len: {}, count: {}", + mhdr.msg_controllen, cmsg_payload_len, count + ); + + current_cmsghdr_ptr = libc_next; + count += 1; } } + + unsafe { + pcmsghdr.cast::().write_bytes(0, CAPACITY); + } } } } diff --git a/src/unix/linux_like/linux_l4re_shared.rs b/src/unix/linux_like/linux_l4re_shared.rs index bd3cfafeb6e7..7fae06c781b4 100644 --- a/src/unix/linux_like/linux_l4re_shared.rs +++ b/src/unix/linux_like/linux_l4re_shared.rs @@ -1493,15 +1493,14 @@ f! { if ((*cmsg).cmsg_len as usize) < size_of::() { return core::ptr::null_mut::(); } - let next = - (cmsg as usize + super::CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut crate::cmsghdr; - let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; - if (next.wrapping_offset(1)) as usize > max - || next as usize + super::CMSG_ALIGN((*next).cmsg_len as usize) > max - { + + let next_addr = cmsg as usize + super::CMSG_ALIGN((*cmsg).cmsg_len as usize); + let max_addr = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; + + if next_addr + size_of::() > max_addr { core::ptr::null_mut::() } else { - next + next_addr as _ } }