std: fix msghdr and cmsghdr when using musl libc

glibc and linux kernel use size_t for some field lengths while POSIX and
musl use int. This bug would have caused breakage the first time someone
tried to call sendmsg on a 64-bit big endian system when linking musl
libc.

my opinion:
* msghdr.iovlen: kernel and glibc have it right. This field should
  definitely be size_t. With int, the padding bytes are wasted for no
  reason.
* msghdr.controllen: POSIX and musl have it right. 4 bytes is plenty for
  the length, and it saves 4 bytes next to flags.
* cmsghdr.len: POSIX and musl have it right. 4 bytes is plenty for the
  length, and it saves 4 bytes since the other fields are also 32-bits
  each.
This commit is contained in:
Andrew Kelley 2025-10-01 17:18:30 -07:00
parent 96cf75977b
commit 062d17ccab
2 changed files with 44 additions and 59 deletions

View File

@ -4185,8 +4185,9 @@ pub const linger = switch (native_os) {
},
else => void,
};
pub const msghdr = switch (native_os) {
.linux => linux.msghdr,
.linux => if (@bitSizeOf(usize) > @bitSizeOf(i32) and builtin.abi.isMusl()) posix_msghdr else linux.msghdr,
.openbsd,
.emscripten,
.dragonfly,
@ -4201,36 +4202,24 @@ pub const msghdr = switch (native_os) {
.tvos,
.visionos,
.watchos,
=> extern struct {
/// optional address
name: ?*sockaddr,
/// size of address
namelen: socklen_t,
/// scatter/gather array
iov: [*]iovec,
/// # elements in iov
iovlen: i32,
/// ancillary data
control: ?*anyopaque,
/// ancillary data buffer len
controllen: socklen_t,
/// flags on received message
flags: i32,
},
// https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L74-L82
.serenity => extern struct {
name: ?*anyopaque,
namelen: socklen_t,
iov: [*]iovec,
iovlen: c_int,
control: ?*anyopaque,
controllen: socklen_t,
flags: c_int,
},
.serenity, // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L74-L82
=> private.posix_msghdr,
else => void,
};
/// https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/sys_socket.h.html
const posix_msghdr = extern struct {
name: ?*sockaddr,
namelen: socklen_t,
iov: [*]iovec,
iovlen: u32,
control: ?*anyopaque,
controllen: socklen_t,
flags: u32,
};
pub const msghdr_const = switch (native_os) {
.linux => linux.msghdr_const,
.linux => if (@bitSizeOf(usize) > @bitSizeOf(i32) and builtin.abi.isMusl()) posix_msghdr_const else linux.msghdr_const,
.openbsd,
.emscripten,
.dragonfly,
@ -4245,36 +4234,25 @@ pub const msghdr_const = switch (native_os) {
.tvos,
.visionos,
.watchos,
=> extern struct {
/// optional address
name: ?*const sockaddr,
/// size of address
namelen: socklen_t,
/// scatter/gather array
iov: [*]const iovec_const,
/// # elements in iov
iovlen: u32,
/// ancillary data
control: ?*const anyopaque,
/// ancillary data buffer len
controllen: socklen_t,
/// flags on received message
flags: i32,
},
.serenity => extern struct {
name: ?*const anyopaque,
namelen: socklen_t,
iov: [*]const iovec_const,
iovlen: c_uint,
control: ?*const anyopaque,
controllen: socklen_t,
flags: c_int,
},
.serenity,
=> posix_msghdr_const,
else => void,
};
const posix_msghdr_const = extern struct {
name: ?*const sockaddr,
namelen: socklen_t,
iov: [*]const iovec_const,
iovlen: u32,
control: ?*const anyopaque,
controllen: socklen_t,
flags: u32,
};
pub const cmsghdr = switch (native_os) {
.linux => if (@bitSizeOf(usize) > @bitSizeOf(i32) and builtin.abi.isMusl()) posix_cmsghdr else linux.cmsghdr,
// https://github.com/emscripten-core/emscripten/blob/96371ed7888fc78c040179f4d4faa82a6a07a116/system/lib/libc/musl/include/sys/socket.h#L44
.linux, .emscripten => linux.cmsghdr,
.emscripten => linux.cmsghdr,
// https://github.com/freebsd/freebsd-src/blob/b197d2abcb6895d78bc9df8404e374397aa44748/sys/sys/socket.h#L492
.freebsd,
// https://github.com/DragonFlyBSD/DragonFlyBSD/blob/107c0518337ba90e7fa49e74845d8d44320c9a6d/sys/sys/socket.h#L452
@ -4298,13 +4276,17 @@ pub const cmsghdr = switch (native_os) {
.tvos,
.visionos,
.watchos,
=> extern struct {
len: socklen_t,
level: c_int,
type: c_int,
},
=> posix_cmsghdr,
else => void,
};
const posix_cmsghdr = extern struct {
len: socklen_t,
level: c_int,
type: c_int,
};
pub const nfds_t = switch (native_os) {
.linux => linux.nfds_t,
.emscripten => emscripten.nfds_t,

View File

@ -9751,8 +9751,10 @@ pub const msghdr = extern struct {
name: ?*sockaddr,
namelen: socklen_t,
iov: [*]iovec,
/// The kernel and glibc use `usize` for this field; POSIX and musl use `c_int`.
iovlen: usize,
control: ?*anyopaque,
/// The kernel and glibc use `usize` for this field; POSIX and musl use `socklen_t`.
controllen: usize,
flags: u32,
};
@ -9769,6 +9771,7 @@ pub const msghdr_const = extern struct {
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/socket.h?id=b320789d6883cc00ac78ce83bccbfe7ed58afcf0#n105
pub const cmsghdr = extern struct {
/// The kernel and glibc use `usize` for this field; musl uses `socklen_t`.
len: usize,
level: i32,
type: i32,