authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-01 17:18:30-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-02 16:30:59-07:00
log062d17ccab495d63799e3ac8831eed485ca8cffe
tree4699f832c8636c72644fe3b5fd3d1ef1f4e0ab42
parent96cf75977bd46ccf4d0626183bc1d9e3e5d80eac

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.

2 files changed, 44 insertions(+), 59 deletions(-)

lib/std/c.zig+41-59
...@@ -4185,8 +4185,9 @@ pub const linger = switch (native_os) {...@@ -4185,8 +4185,9 @@ pub const linger = switch (native_os) {
4185 },4185 },
4186 else => void,4186 else => void,
4187};4187};
4188
4188pub const msghdr = switch (native_os) {4189pub const msghdr = switch (native_os) {
4189 .linux => linux.msghdr,4190 .linux => if (@bitSizeOf(usize) > @bitSizeOf(i32) and builtin.abi.isMusl()) posix_msghdr else linux.msghdr,
4190 .openbsd,4191 .openbsd,
4191 .emscripten,4192 .emscripten,
4192 .dragonfly,4193 .dragonfly,
...@@ -4201,36 +4202,24 @@ pub const msghdr = switch (native_os) {...@@ -4201,36 +4202,24 @@ pub const msghdr = switch (native_os) {
4201 .tvos,4202 .tvos,
4202 .visionos,4203 .visionos,
4203 .watchos,4204 .watchos,
4204 => extern struct {4205 .serenity, // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L74-L82
4205 /// optional address4206 => private.posix_msghdr,
4206 name: ?*sockaddr,
4207 /// size of address
4208 namelen: socklen_t,
4209 /// scatter/gather array
4210 iov: [*]iovec,
4211 /// # elements in iov
4212 iovlen: i32,
4213 /// ancillary data
4214 control: ?*anyopaque,
4215 /// ancillary data buffer len
4216 controllen: socklen_t,
4217 /// flags on received message
4218 flags: i32,
4219 },
4220 // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L74-L82
4221 .serenity => extern struct {
4222 name: ?*anyopaque,
4223 namelen: socklen_t,
4224 iov: [*]iovec,
4225 iovlen: c_int,
4226 control: ?*anyopaque,
4227 controllen: socklen_t,
4228 flags: c_int,
4229 },
4230 else => void,4207 else => void,
4231};4208};
4209
4210/// https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/sys_socket.h.html
4211const posix_msghdr = extern struct {
4212 name: ?*sockaddr,
4213 namelen: socklen_t,
4214 iov: [*]iovec,
4215 iovlen: u32,
4216 control: ?*anyopaque,
4217 controllen: socklen_t,
4218 flags: u32,
4219};
4220
4232pub const msghdr_const = switch (native_os) {4221pub const msghdr_const = switch (native_os) {
4233 .linux => linux.msghdr_const,4222 .linux => if (@bitSizeOf(usize) > @bitSizeOf(i32) and builtin.abi.isMusl()) posix_msghdr_const else linux.msghdr_const,
4234 .openbsd,4223 .openbsd,
4235 .emscripten,4224 .emscripten,
4236 .dragonfly,4225 .dragonfly,
...@@ -4245,36 +4234,25 @@ pub const msghdr_const = switch (native_os) {...@@ -4245,36 +4234,25 @@ pub const msghdr_const = switch (native_os) {
4245 .tvos,4234 .tvos,
4246 .visionos,4235 .visionos,
4247 .watchos,4236 .watchos,
4248 => extern struct {4237 .serenity,
4249 /// optional address4238 => posix_msghdr_const,
4250 name: ?*const sockaddr,
4251 /// size of address
4252 namelen: socklen_t,
4253 /// scatter/gather array
4254 iov: [*]const iovec_const,
4255 /// # elements in iov
4256 iovlen: u32,
4257 /// ancillary data
4258 control: ?*const anyopaque,
4259 /// ancillary data buffer len
4260 controllen: socklen_t,
4261 /// flags on received message
4262 flags: i32,
4263 },
4264 .serenity => extern struct {
4265 name: ?*const anyopaque,
4266 namelen: socklen_t,
4267 iov: [*]const iovec_const,
4268 iovlen: c_uint,
4269 control: ?*const anyopaque,
4270 controllen: socklen_t,
4271 flags: c_int,
4272 },
4273 else => void,4239 else => void,
4274};4240};
4241
4242const posix_msghdr_const = extern struct {
4243 name: ?*const sockaddr,
4244 namelen: socklen_t,
4245 iov: [*]const iovec_const,
4246 iovlen: u32,
4247 control: ?*const anyopaque,
4248 controllen: socklen_t,
4249 flags: u32,
4250};
4251
4275pub const cmsghdr = switch (native_os) {4252pub const cmsghdr = switch (native_os) {
4253 .linux => if (@bitSizeOf(usize) > @bitSizeOf(i32) and builtin.abi.isMusl()) posix_cmsghdr else linux.cmsghdr,
4276 // https://github.com/emscripten-core/emscripten/blob/96371ed7888fc78c040179f4d4faa82a6a07a116/system/lib/libc/musl/include/sys/socket.h#L444254 // https://github.com/emscripten-core/emscripten/blob/96371ed7888fc78c040179f4d4faa82a6a07a116/system/lib/libc/musl/include/sys/socket.h#L44
4277 .linux, .emscripten => linux.cmsghdr,4255 .emscripten => linux.cmsghdr,
4278 // https://github.com/freebsd/freebsd-src/blob/b197d2abcb6895d78bc9df8404e374397aa44748/sys/sys/socket.h#L4924256 // https://github.com/freebsd/freebsd-src/blob/b197d2abcb6895d78bc9df8404e374397aa44748/sys/sys/socket.h#L492
4279 .freebsd,4257 .freebsd,
4280 // https://github.com/DragonFlyBSD/DragonFlyBSD/blob/107c0518337ba90e7fa49e74845d8d44320c9a6d/sys/sys/socket.h#L4524258 // https://github.com/DragonFlyBSD/DragonFlyBSD/blob/107c0518337ba90e7fa49e74845d8d44320c9a6d/sys/sys/socket.h#L452
...@@ -4298,13 +4276,17 @@ pub const cmsghdr = switch (native_os) {...@@ -4298,13 +4276,17 @@ pub const cmsghdr = switch (native_os) {
4298 .tvos,4276 .tvos,
4299 .visionos,4277 .visionos,
4300 .watchos,4278 .watchos,
4301 => extern struct {4279 => posix_cmsghdr,
4302 len: socklen_t,4280
4303 level: c_int,
4304 type: c_int,
4305 },
4306 else => void,4281 else => void,
4307};4282};
4283
4284const posix_cmsghdr = extern struct {
4285 len: socklen_t,
4286 level: c_int,
4287 type: c_int,
4288};
4289
4308pub const nfds_t = switch (native_os) {4290pub const nfds_t = switch (native_os) {
4309 .linux => linux.nfds_t,4291 .linux => linux.nfds_t,
4310 .emscripten => emscripten.nfds_t,4292 .emscripten => emscripten.nfds_t,
lib/std/os/linux.zig+3
...@@ -9751,8 +9751,10 @@ pub const msghdr = extern struct {...@@ -9751,8 +9751,10 @@ pub const msghdr = extern struct {
9751 name: ?*sockaddr,9751 name: ?*sockaddr,
9752 namelen: socklen_t,9752 namelen: socklen_t,
9753 iov: [*]iovec,9753 iov: [*]iovec,
9754 /// The kernel and glibc use `usize` for this field; POSIX and musl use `c_int`.
9754 iovlen: usize,9755 iovlen: usize,
9755 control: ?*anyopaque,9756 control: ?*anyopaque,
9757 /// The kernel and glibc use `usize` for this field; POSIX and musl use `socklen_t`.
9756 controllen: usize,9758 controllen: usize,
9757 flags: u32,9759 flags: u32,
9758};9760};
...@@ -9769,6 +9771,7 @@ pub const msghdr_const = extern struct {...@@ -9769,6 +9771,7 @@ pub const msghdr_const = extern struct {
97699771
9770// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/socket.h?id=b320789d6883cc00ac78ce83bccbfe7ed58afcf0#n1059772// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/socket.h?id=b320789d6883cc00ac78ce83bccbfe7ed58afcf0#n105
9771pub const cmsghdr = extern struct {9773pub const cmsghdr = extern struct {
9774 /// The kernel and glibc use `usize` for this field; musl uses `socklen_t`.
9772 len: usize,9775 len: usize,
9773 level: i32,9776 level: i32,
9774 type: i32,9777 type: i32,