Skip to content

Commit 8bc7ac9

Browse files
committed
[upstream] fix handling of sockaddr_un.len on QNX
also extend the existing tests to exercise the getsockname(2) and getpeername(2) paths with both named and unnamed Unix sockets
1 parent 0ca2d67 commit 8bc7ac9

2 files changed

Lines changed: 26 additions & 2 deletions

File tree

library/std/src/os/unix/net/addr.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,15 @@ pub(super) fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::s
5353
let mut len = SUN_PATH_OFFSET + bytes.len();
5454
match bytes.get(0) {
5555
Some(&0) | None => {}
56-
Some(_) => len += 1,
56+
Some(_) => {
57+
// on QNX7.1 and QNX8 the `len` value returned by the SUN_LEN
58+
// macro in its libc does not include the null byte in the count so
59+
// don't add it here to match what a C program passes to bind(2) and
60+
// similar functions
61+
if cfg!(not(any(target_env = "nto80", target_env = "nto71"))) {
62+
len += 1
63+
}
64+
}
5765
}
5866
Ok((addr, len as libc::socklen_t))
5967
}
@@ -247,7 +255,13 @@ impl SocketAddr {
247255
} else if self.addr.sun_path[0] == 0 {
248256
AddressKind::Abstract(ByteStr::from_bytes(&path[1..len]))
249257
} else {
250-
AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref())
258+
// the value returned by getsockname(2) and similar on QNX7.1 and
259+
// QNX8 does not count the NUL byte terminator of the path string,
260+
// which matches the behavior of the SUN_LEN macro in libc, but
261+
// other OSes do count the NUL byte so adjust accordingly
262+
let end =
263+
if cfg!(any(target_env = "nto80", target_env = "nto71")) { len } else { len - 1 };
264+
AddressKind::Pathname(OsStr::from_bytes(&path[..end]).as_ref())
251265
}
252266
}
253267
}

library/std/src/os/unix/net/tests.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::os::cygwin::net::{SocketAddrExt, UnixSocketExt};
99
use crate::os::linux::net::{SocketAddrExt, UnixSocketExt};
1010
#[cfg(any(target_os = "android", target_os = "linux"))]
1111
use crate::os::unix::io::AsRawFd;
12+
use crate::path::Path;
1213
use crate::test_helpers::tmpdir;
1314
use crate::thread;
1415
use crate::time::Duration;
@@ -22,6 +23,12 @@ macro_rules! or_panic {
2223
};
2324
}
2425

26+
#[test]
27+
fn sock_addr_from_pathname() {
28+
let address = or_panic!(SocketAddr::from_pathname("/path/to/socket"));
29+
assert_eq!(address.as_pathname(), Some(Path::new("/path/to/socket")));
30+
}
31+
2532
#[test]
2633
#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
2734
#[cfg_attr(target_os = "vxworks", ignore = "Unix sockets are not implemented in VxWorks")]
@@ -32,6 +39,7 @@ fn basic() {
3239
let msg2 = b"world!";
3340

3441
let listener = or_panic!(UnixListener::bind(&socket_path));
42+
assert_eq!(Some(&*socket_path), listener.local_addr().unwrap().as_pathname());
3543
let thread = thread::spawn(move || {
3644
let mut stream = or_panic!(listener.accept()).0;
3745
let mut buf = [0; 5];
@@ -79,6 +87,8 @@ fn pair() {
7987
let msg2 = b"world!";
8088

8189
let (mut s1, mut s2) = or_panic!(UnixStream::pair());
90+
assert!(s1.local_addr().unwrap().is_unnamed());
91+
assert!(s2.peer_addr().unwrap().is_unnamed());
8292
let thread = thread::spawn(move || {
8393
// s1 must be moved in or the test will hang!
8494
let mut buf = [0; 5];

0 commit comments

Comments
 (0)