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-29 06:20:48-07:00
log961961cf85618083702799ef60f9f77dec806774
treee1d9725761771c3ad79379c1e4a526796f5a6487
parent95dee2af9c6ed17286a1b3be81b11093c2ecb5f2

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
...@@ -4087,8 +4087,9 @@ pub const linger = switch (native_os) {...@@ -4087,8 +4087,9 @@ pub const linger = switch (native_os) {
4087 },4087 },
4088 else => void,4088 else => void,
4089};4089};
4090
4090pub const msghdr = switch (native_os) {4091pub const msghdr = switch (native_os) {
4091 .linux => linux.msghdr,4092 .linux => if (@bitSizeOf(usize) > @bitSizeOf(i32) and builtin.abi.isMusl()) posix_msghdr else linux.msghdr,
4092 .openbsd,4093 .openbsd,
4093 .emscripten,4094 .emscripten,
4094 .dragonfly,4095 .dragonfly,
...@@ -4102,36 +4103,24 @@ pub const msghdr = switch (native_os) {...@@ -4102,36 +4103,24 @@ pub const msghdr = switch (native_os) {
4102 .tvos,4103 .tvos,
4103 .visionos,4104 .visionos,
4104 .watchos,4105 .watchos,
4105 => extern struct {4106 .serenity, // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L74-L82
4106 /// optional address4107 => private.posix_msghdr,
4107 name: ?*sockaddr,
4108 /// size of address
4109 namelen: socklen_t,
4110 /// scatter/gather array
4111 iov: [*]iovec,
4112 /// # elements in iov
4113 iovlen: i32,
4114 /// ancillary data
4115 control: ?*anyopaque,
4116 /// ancillary data buffer len
4117 controllen: socklen_t,
4118 /// flags on received message
4119 flags: i32,
4120 },
4121 // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L74-L82
4122 .serenity => extern struct {
4123 name: ?*anyopaque,
4124 namelen: socklen_t,
4125 iov: [*]iovec,
4126 iovlen: c_int,
4127 control: ?*anyopaque,
4128 controllen: socklen_t,
4129 flags: c_int,
4130 },
4131 else => void,4108 else => void,
4132};4109};
4110
4111/// https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/sys_socket.h.html
4112const posix_msghdr = extern struct {
4113 name: ?*sockaddr,
4114 namelen: socklen_t,
4115 iov: [*]iovec,
4116 iovlen: u32,
4117 control: ?*anyopaque,
4118 controllen: socklen_t,
4119 flags: u32,
4120};
4121
4133pub const msghdr_const = switch (native_os) {4122pub const msghdr_const = switch (native_os) {
4134 .linux => linux.msghdr_const,4123 .linux => if (@bitSizeOf(usize) > @bitSizeOf(i32) and builtin.abi.isMusl()) posix_msghdr_const else linux.msghdr_const,
4135 .openbsd,4124 .openbsd,
4136 .emscripten,4125 .emscripten,
4137 .dragonfly,4126 .dragonfly,
...@@ -4145,36 +4134,25 @@ pub const msghdr_const = switch (native_os) {...@@ -4145,36 +4134,25 @@ pub const msghdr_const = switch (native_os) {
4145 .tvos,4134 .tvos,
4146 .visionos,4135 .visionos,
4147 .watchos,4136 .watchos,
4148 => extern struct {4137 .serenity,
4149 /// optional address4138 => posix_msghdr_const,
4150 name: ?*const sockaddr,
4151 /// size of address
4152 namelen: socklen_t,
4153 /// scatter/gather array
4154 iov: [*]const iovec_const,
4155 /// # elements in iov
4156 iovlen: u32,
4157 /// ancillary data
4158 control: ?*const anyopaque,
4159 /// ancillary data buffer len
4160 controllen: socklen_t,
4161 /// flags on received message
4162 flags: i32,
4163 },
4164 .serenity => extern struct {
4165 name: ?*const anyopaque,
4166 namelen: socklen_t,
4167 iov: [*]const iovec_const,
4168 iovlen: c_uint,
4169 control: ?*const anyopaque,
4170 controllen: socklen_t,
4171 flags: c_int,
4172 },
4173 else => void,4139 else => void,
4174};4140};
4141
4142const posix_msghdr_const = extern struct {
4143 name: ?*const sockaddr,
4144 namelen: socklen_t,
4145 iov: [*]const iovec_const,
4146 iovlen: u32,
4147 control: ?*const anyopaque,
4148 controllen: socklen_t,
4149 flags: u32,
4150};
4151
4175pub const cmsghdr = switch (native_os) {4152pub const cmsghdr = switch (native_os) {
4153 .linux => if (@bitSizeOf(usize) > @bitSizeOf(i32) and builtin.abi.isMusl()) posix_cmsghdr else linux.cmsghdr,
4176 // https://github.com/emscripten-core/emscripten/blob/96371ed7888fc78c040179f4d4faa82a6a07a116/system/lib/libc/musl/include/sys/socket.h#L444154 // https://github.com/emscripten-core/emscripten/blob/96371ed7888fc78c040179f4d4faa82a6a07a116/system/lib/libc/musl/include/sys/socket.h#L44
4177 .linux, .emscripten => linux.cmsghdr,4155 .emscripten => linux.cmsghdr,
4178 // https://github.com/freebsd/freebsd-src/blob/b197d2abcb6895d78bc9df8404e374397aa44748/sys/sys/socket.h#L4924156 // https://github.com/freebsd/freebsd-src/blob/b197d2abcb6895d78bc9df8404e374397aa44748/sys/sys/socket.h#L492
4179 .freebsd,4157 .freebsd,
4180 // https://github.com/DragonFlyBSD/DragonFlyBSD/blob/107c0518337ba90e7fa49e74845d8d44320c9a6d/sys/sys/socket.h#L4524158 // https://github.com/DragonFlyBSD/DragonFlyBSD/blob/107c0518337ba90e7fa49e74845d8d44320c9a6d/sys/sys/socket.h#L452
...@@ -4196,13 +4174,17 @@ pub const cmsghdr = switch (native_os) {...@@ -4196,13 +4174,17 @@ pub const cmsghdr = switch (native_os) {
4196 .tvos,4174 .tvos,
4197 .visionos,4175 .visionos,
4198 .watchos,4176 .watchos,
4199 => extern struct {4177 => posix_cmsghdr,
4200 len: socklen_t,4178
4201 level: c_int,
4202 type: c_int,
4203 },
4204 else => void,4179 else => void,
4205};4180};
4181
4182const posix_cmsghdr = extern struct {
4183 len: socklen_t,
4184 level: c_int,
4185 type: c_int,
4186};
4187
4206pub const nfds_t = switch (native_os) {4188pub const nfds_t = switch (native_os) {
4207 .linux => linux.nfds_t,4189 .linux => linux.nfds_t,
4208 .emscripten => emscripten.nfds_t,4190 .emscripten => emscripten.nfds_t,
lib/std/os/linux.zig+3
...@@ -9840,8 +9840,10 @@ pub const msghdr = extern struct {...@@ -9840,8 +9840,10 @@ pub const msghdr = extern struct {
9840 name: ?*sockaddr,9840 name: ?*sockaddr,
9841 namelen: socklen_t,9841 namelen: socklen_t,
9842 iov: [*]iovec,9842 iov: [*]iovec,
9843 /// The kernel and glibc use `usize` for this field; POSIX and musl use `c_int`.
9843 iovlen: usize,9844 iovlen: usize,
9844 control: ?*anyopaque,9845 control: ?*anyopaque,
9846 /// The kernel and glibc use `usize` for this field; POSIX and musl use `socklen_t`.
9845 controllen: usize,9847 controllen: usize,
9846 flags: u32,9848 flags: u32,
9847};9849};
...@@ -9858,6 +9860,7 @@ pub const msghdr_const = extern struct {...@@ -9858,6 +9860,7 @@ pub const msghdr_const = extern struct {
98589860
9859// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/socket.h?id=b320789d6883cc00ac78ce83bccbfe7ed58afcf0#n1059861// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/socket.h?id=b320789d6883cc00ac78ce83bccbfe7ed58afcf0#n105
9860pub const cmsghdr = extern struct {9862pub const cmsghdr = extern struct {
9863 /// The kernel and glibc use `usize` for this field; musl uses `socklen_t`.
9861 len: usize,9864 len: usize,
9862 level: i32,9865 level: i32,
9863 type: i32,9866 type: i32,