authorgravatar for skdishansachin@proton.meskdishansachin <skdishansachin@proton.me> 2026-07-04 08:11:51+00:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2026-07-11 00:07:06+02:00
loge95c656d9aac7bea3c9b265ab08114888cd9717c
tree5996eca888b276b2e7c0bf095b6d0514ab97a41b
parent7796e5cdffd52073b56f6b9176dc0b99dedb62ef

Uri: use findLast for @ delimiter in authority parsing


1 files changed, 22 insertions(+), 1 deletions(-)

lib/std/Uri.zig+22-1
......@@ -191,7 +191,11 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri {
191191 }
192192
193193 var start_of_host: usize = 0;
194 if (std.mem.find(u8, authority, "@")) |index| {
194 // Use findLast to handle unencoded @ in userinfo gracefully,
195 // e.g. scheme://user:p@ssword@hostname. This deviates from RFC3986
196 // (which requires @ to be percent-encoded as %40 in userinfo) but
197 // is more robust against URIs in the wild.
198 if (std.mem.findLast(u8, authority, "@")) |index| {
195199 start_of_host = index + 1;
196200 const user_info = authority[0..index];
197201
......@@ -621,6 +625,23 @@ test "authority" {
621625 try std.testing.expectEqual(@as(u16, 1234), (try parse("scheme://user:password@hostname:1234")).port.?);
622626 try std.testing.expectEqualStrings("user", (try parse("scheme://user:password@hostname:1234")).user.?.percent_encoded);
623627 try std.testing.expectEqualStrings("password", (try parse("scheme://user:password@hostname:1234")).password.?.percent_encoded);
628
629 try std.testing.expectEqualStrings("user", (try parse("scheme://user:p@ssword@hostname:1234")).user.?.percent_encoded);
630 try std.testing.expectEqualStrings("p@ssword", (try parse("scheme://user:p@ssword@hostname:1234")).password.?.percent_encoded);
631 try std.testing.expectEqualStrings("hostname", (try parse("scheme://user:p@ssword@hostname:1234")).host.?.percent_encoded);
632
633 try std.testing.expectEqualStrings("user", (try parse("scheme://user:p@@@word@hostname:1234")).user.?.percent_encoded);
634 try std.testing.expectEqualStrings("p@@@word", (try parse("scheme://user:p@@@word@hostname:1234")).password.?.percent_encoded);
635 try std.testing.expectEqualStrings("hostname", (try parse("scheme://user:p@@@word@hostname:1234")).host.?.percent_encoded);
636
637 try std.testing.expectEqualStrings("user@name", (try parse("scheme://user@name@hostname")).user.?.percent_encoded);
638 try std.testing.expectEqual(@as(?Component, null), (try parse("scheme://user@name@hostname")).password);
639 try std.testing.expectEqualStrings("hostname", (try parse("scheme://user@name@hostname")).host.?.percent_encoded);
640
641 try std.testing.expectEqualStrings("user@name", (try parse("scheme://user@name@hostname:1234")).user.?.percent_encoded);
642 try std.testing.expectEqual(@as(?Component, null), (try parse("scheme://user@name@hostname:1234")).password);
643 try std.testing.expectEqualStrings("hostname", (try parse("scheme://user@name@hostname:1234")).host.?.percent_encoded);
644 try std.testing.expectEqual(@as(u16, 1234), (try parse("scheme://user@name@hostname:1234")).port.?);
624645}
625646
626647test "authority.password" {