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 {...@@ -447,7 +447,9 @@ pub const Ip6Address = struct {
447 pub const Unresolved = struct {447 pub const Unresolved = struct {
448 /// Big endian448 /// Big endian
449 bytes: [16]u8,449 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
452 pub const Parsed = union(enum) {454 pub const Parsed = union(enum) {
453 success: Unresolved,455 success: Unresolved,
...@@ -536,7 +538,6 @@ pub const Ip6Address = struct {...@@ -536,7 +538,6 @@ pub const Ip6Address = struct {
536 parts_i += 1;538 parts_i += 1;
537 text_i += 1;539 text_i += 1;
538 const name = text[text_i..];540 const name = text[text_i..];
539 if (name.len > Interface.Name.max_len) return .{ .interface_name_oversized = text_i };
540 if (name.len == 0) return .incomplete;541 if (name.len == 0) return .incomplete;
541 interface_name_text = name;542 interface_name_text = name;
542 text_i = @intCast(text.len);543 text_i = @intCast(text.len);
...@@ -563,7 +564,7 @@ pub const Ip6Address = struct {...@@ -563,7 +564,7 @@ pub const Ip6Address = struct {
563564
564 return .{ .success = .{565 return .{ .success = .{
565 .bytes = @bitCast(parts),566 .bytes = @bitCast(parts),
566 .interface_name = if (interface_name_text) |t| .fromSliceUnchecked(t) else null,567 .interface_name = interface_name_text,
567 } };568 } };
568 },569 },
569 }570 }
...@@ -646,7 +647,7 @@ pub const Ip6Address = struct {...@@ -646,7 +647,7 @@ pub const Ip6Address = struct {
646 }647 }
647 }648 }
648 }649 }
649 if (u.interface_name) |n| try w.print("%{s}", .{n.toSlice()});650 if (u.interface_name) |n| try w.print("%{s}", .{n});
650 }651 }
651 };652 };
652653
...@@ -678,6 +679,8 @@ pub const Ip6Address = struct {...@@ -678,6 +679,8 @@ pub const Ip6Address = struct {
678 /// If this is returned, more detailed diagnostics can be obtained by679 /// If this is returned, more detailed diagnostics can be obtained by
679 /// calling the `Parsed.init` function.680 /// calling the `Parsed.init` function.
680 ParseFailed,681 ParseFailed,
682 /// The interface name is longer than the host operating system supports.
683 NameTooLong,
681 } || Interface.Name.ResolveError;684 } || Interface.Name.ResolveError;
682685
683 /// This function requires an `Io` parameter because it must query the operating686 /// This function requires an `Io` parameter because it must query the operating
...@@ -689,7 +692,11 @@ pub const Ip6Address = struct {...@@ -689,7 +692,11 @@ pub const Ip6Address = struct {
689 .success => |p| return .{692 .success => |p| return .{
690 .bytes = p.bytes,693 .bytes = p.bytes,
691 .port = port,694 .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 },
693 },700 },
694 else => return error.ParseFailed,701 else => return error.ParseFailed,
695 };702 };
...@@ -946,7 +953,7 @@ pub const Interface = struct {...@@ -946,7 +953,7 @@ pub const Interface = struct {
946 pub const Name = struct {953 pub const Name = struct {
947 bytes: [max_len:0]u8,954 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
951 pub fn toSlice(n: *const Name) []const u8 {958 pub fn toSlice(n: *const Name) []const u8 {
952 return std.mem.sliceTo(&n.bytes, 0);959 return std.mem.sliceTo(&n.bytes, 0);
lib/std/c.zig+1-1
...@@ -6855,7 +6855,7 @@ pub const IFNAMESIZE = switch (native_os) {...@@ -6855,7 +6855,7 @@ pub const IFNAMESIZE = switch (native_os) {
6855 // https://github.com/SerenityOS/serenity/blob/9882848e0bf783dfc8e8a6d887a848d70d9c58f4/Kernel/API/POSIX/net/if.h#L506855 // https://github.com/SerenityOS/serenity/blob/9882848e0bf783dfc8e8a6d887a848d70d9c58f4/Kernel/API/POSIX/net/if.h#L50
6856 .openbsd, .dragonfly, .netbsd, .freebsd, .macos, .ios, .tvos, .watchos, .visionos, .serenity => 16,6856 .openbsd, .dragonfly, .netbsd, .freebsd, .macos, .ios, .tvos, .watchos, .visionos, .serenity => 16,
6857 .illumos => 32,6857 .illumos => 32,
6858 else => void,6858 else => {},
6859};6859};
68606860
6861pub const stack_t = switch (native_os) {6861pub 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....@@ -201,10 +201,19 @@ pub fn getFdPath(fd: std.posix.fd_t, out_buffer: *[max_path_bytes]u8) std.posix.
201 }201 }
202}202}
203203
204pub const FstatatError = error{
205 SystemResources,
206 AccessDenied,
207 NameTooLong,
208 FileNotFound,
209 InvalidUtf8,
210 Unexpected,
211};
212
204/// WASI-only. Same as `fstatat` but targeting WASI.213/// WASI-only. Same as `fstatat` but targeting WASI.
205/// `pathname` should be encoded as valid UTF-8.214/// `pathname` should be encoded as valid UTF-8.
206/// See also `fstatat`.215/// 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 {
208 var stat: wasi.filestat_t = undefined;217 var stat: wasi.filestat_t = undefined;
209 switch (wasi.path_filestat_get(dirfd, flags, pathname.ptr, pathname.len, &stat)) {218 switch (wasi.path_filestat_get(dirfd, flags, pathname.ptr, pathname.len, &stat)) {
210 .SUCCESS => return stat,219 .SUCCESS => return stat,
lib/std/posix.zig+1
...@@ -4945,6 +4945,7 @@ pub const AccessError = error{...@@ -4945,6 +4945,7 @@ pub const AccessError = error{
4945 /// Windows-only; file paths provided by the user must be valid WTF-8.4945 /// Windows-only; file paths provided by the user must be valid WTF-8.
4946 /// https://wtf-8.codeberg.page/4946 /// https://wtf-8.codeberg.page/
4947 InvalidWtf8,4947 InvalidWtf8,
4948 Canceled,
4948} || UnexpectedError;4949} || UnexpectedError;
49494950
4950/// check user's permissions for a file4951/// check user's permissions for a file