authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-16 11:52:52-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-29 06:20:50-07:00
log22334f573074bec8112bf686014381e3d8c4cc08
treee262f02b347e6efea75a88968eb69d926f147f99
parent90fdd21df6663d0ad99379cd056c8940e3a3e267

std: make IPv6 address parsing system-independent

before, the max length of the host name depended on the target.

4 files changed, 25 insertions(+), 8 deletions(-)

lib/std/Io/net.zig+13-6
......@@ -447,7 +447,9 @@ pub const Ip6Address = struct {
447447 pub const Unresolved = struct {
448448 /// Big endian
449449 bytes: [16]u8,
450 interface_name: ?Interface.Name,
450 /// Has not been checked to be a valid native interface name.
451 /// Externally managed memory.
452 interface_name: ?[]const u8,
451453
452454 pub const Parsed = union(enum) {
453455 success: Unresolved,
......@@ -536,7 +538,6 @@ pub const Ip6Address = struct {
536538 parts_i += 1;
537539 text_i += 1;
538540 const name = text[text_i..];
539 if (name.len > Interface.Name.max_len) return .{ .interface_name_oversized = text_i };
540541 if (name.len == 0) return .incomplete;
541542 interface_name_text = name;
542543 text_i = @intCast(text.len);
......@@ -563,7 +564,7 @@ pub const Ip6Address = struct {
563564
564565 return .{ .success = .{
565566 .bytes = @bitCast(parts),
566 .interface_name = if (interface_name_text) |t| .fromSliceUnchecked(t) else null,
567 .interface_name = interface_name_text,
567568 } };
568569 },
569570 }
......@@ -646,7 +647,7 @@ pub const Ip6Address = struct {
646647 }
647648 }
648649 }
649 if (u.interface_name) |n| try w.print("%{s}", .{n.toSlice()});
650 if (u.interface_name) |n| try w.print("%{s}", .{n});
650651 }
651652 };
652653
......@@ -678,6 +679,8 @@ pub const Ip6Address = struct {
678679 /// If this is returned, more detailed diagnostics can be obtained by
679680 /// calling the `Parsed.init` function.
680681 ParseFailed,
682 /// The interface name is longer than the host operating system supports.
683 NameTooLong,
681684 } || Interface.Name.ResolveError;
682685
683686 /// This function requires an `Io` parameter because it must query the operating
......@@ -689,7 +692,11 @@ pub const Ip6Address = struct {
689692 .success => |p| return .{
690693 .bytes = p.bytes,
691694 .port = port,
692 .interface = if (p.interface_name) |n| try n.resolve(io) else .none,
695 .interface = i: {
696 const text = p.interface_name orelse break :i .none;
697 const name: Interface.Name = try .fromSlice(text);
698 break :i try name.resolve(io);
699 },
693700 },
694701 else => return error.ParseFailed,
695702 };
......@@ -946,7 +953,7 @@ pub const Interface = struct {
946953 pub const Name = struct {
947954 bytes: [max_len:0]u8,
948955
949 pub const max_len = std.posix.IFNAMESIZE - 1;
956 pub const max_len = if (@TypeOf(std.posix.IFNAMESIZE) == void) 0 else std.posix.IFNAMESIZE - 1;
950957
951958 pub fn toSlice(n: *const Name) []const u8 {
952959 return std.mem.sliceTo(&n.bytes, 0);
lib/std/c.zig+1-1
......@@ -6855,7 +6855,7 @@ pub const IFNAMESIZE = switch (native_os) {
68556855 // https://github.com/SerenityOS/serenity/blob/9882848e0bf783dfc8e8a6d887a848d70d9c58f4/Kernel/API/POSIX/net/if.h#L50
68566856 .openbsd, .dragonfly, .netbsd, .freebsd, .macos, .ios, .tvos, .watchos, .visionos, .serenity => 16,
68576857 .illumos => 32,
6858 else => void,
6858 else => {},
68596859};
68606860
68616861pub const stack_t = switch (native_os) {
lib/std/os.zig+10-1
......@@ -201,10 +201,19 @@ pub fn getFdPath(fd: std.posix.fd_t, out_buffer: *[max_path_bytes]u8) std.posix.
201201 }
202202}
203203
204pub const FstatatError = error{
205 SystemResources,
206 AccessDenied,
207 NameTooLong,
208 FileNotFound,
209 InvalidUtf8,
210 Unexpected,
211};
212
204213/// WASI-only. Same as `fstatat` but targeting WASI.
205214/// `pathname` should be encoded as valid UTF-8.
206215/// See also `fstatat`.
207pub fn fstatat_wasi(dirfd: posix.fd_t, pathname: []const u8, flags: wasi.lookupflags_t) posix.FStatAtError!wasi.filestat_t {
216pub fn fstatat_wasi(dirfd: posix.fd_t, pathname: []const u8, flags: wasi.lookupflags_t) FstatatError!wasi.filestat_t {
208217 var stat: wasi.filestat_t = undefined;
209218 switch (wasi.path_filestat_get(dirfd, flags, pathname.ptr, pathname.len, &stat)) {
210219 .SUCCESS => return stat,
lib/std/posix.zig+1
......@@ -4945,6 +4945,7 @@ pub const AccessError = error{
49454945 /// Windows-only; file paths provided by the user must be valid WTF-8.
49464946 /// https://wtf-8.codeberg.page/
49474947 InvalidWtf8,
4948 Canceled,
49484949} || UnexpectedError;
49494950
49504951/// check user's permissions for a file