From a6f7722b32bd9e0c1b86a978adcb5db270a23d59 Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Fri, 3 Jul 2026 21:30:31 -0700 Subject: [PATCH] HostName: Include trailing . in max length calculation The 255 max length restriction is based on the representation in a packet, where each label has a byte prefixed denoting the length and the trailing dot is non-optional but specified as a zero-length label (so one byte with value 0 at the end). This means that for the purposes of validation, the trailing dot should be included in the length. This also ensures that max_len is always enough to hold a validated HostName, whereas before any code relying on that assumption was technically invalid as it was possible to pass through `validate` with a 256-length slice. --- lib/std/Io/net/HostName.zig | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/std/Io/net/HostName.zig b/lib/std/Io/net/HostName.zig index 26c5fc855f66a0abf270954f8947690334b5a0d7..262a86386b60f9b3b4585e7749089c02eca47efc 100644 --- a/lib/std/Io/net/HostName.zig +++ b/lib/std/Io/net/HostName.zig @@ -28,11 +28,11 @@ pub const ValidateError = error{ pub fn validate(bytes: []const u8) ValidateError!void { if (bytes.len == 0) return error.InvalidHostName; - // Ignore trailing dot (FQDN). It doesn't count toward our length. - const end = if (bytes[bytes.len - 1] == '.') bytes.len - 1 else bytes.len; - // The accepted maximum length of a hostname, including labels and dots. - if (end > max_len) return error.NameTooLong; + if (bytes.len > max_len) return error.NameTooLong; + + // Ignore trailing dot (FQDN). + const end = if (bytes[bytes.len - 1] == '.') bytes.len - 1 else bytes.len; // Hostnames are divided into dot-separated "labels", which: // @@ -83,7 +83,6 @@ test validate { const many_a_dot_buf: [127][2]u8 = @splat(.{ 'a', '.' }); const many_a_dot: []const u8 = @ptrCast(&many_a_dot_buf); try validate(many_a_dot ++ "a"); // Total length 255 (valid) - try validate(many_a_dot ++ "a."); // Total length 255 + trailing dot (valid) // Invalid hostnames try std.testing.expectError(error.InvalidHostName, validate("")); @@ -98,8 +97,8 @@ test validate { try std.testing.expectError(error.InvalidHostName, validate(".")); try std.testing.expectError(error.InvalidHostName, validate("..")); try std.testing.expectError(error.InvalidHostName, validate(&many_a ++ "a.com")); // Label length 64 (too long) + try std.testing.expectError(error.NameTooLong, validate(many_a_dot ++ "a.")); // Total length 255 + trailing dot (too long) try std.testing.expectError(error.NameTooLong, validate(many_a_dot ++ "ab")); // Total length 256 (too long) - try std.testing.expectError(error.NameTooLong, validate(many_a_dot ++ "ab.")); // Total length 256 + trailing dot (too long) } pub fn init(bytes: []const u8) ValidateError!HostName { -- 2.54.0