From a16a1a608262e9881e127922c8f27921c4af8407 Mon Sep 17 00:00:00 2001 From: Meghan Denny Date: Sat, 24 Jan 2026 14:58:44 -0800 Subject: [PATCH] pass parseFail with base --- generate.ts | 2 -- url.zig | 12 ++++++---- zig-out/test.zig | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/generate.ts b/generate.ts index fc1a36aca355c2cf36bbc6f88980d5d6ac4a425d..69c032c5ca6e5f9b6882f04009dc4195c8af7d87 100644 --- a/generate.ts +++ b/generate.ts @@ -114,8 +114,6 @@ for (const c of cases) { } w.write(`\n`); -// prettier-ignore -if (false) for (const c of cases) { if (c.base === null) continue; if (!c.failure) continue; diff --git a/url.zig b/url.zig index e8a665c19152da52ad7dad2252e5e382a9e56476..d6e296023c30e555117e605ab7d0f6616442a2d3 100644 --- a/url.zig +++ b/url.zig @@ -34,8 +34,12 @@ pub const URL = struct { /// Caller owns memory and is responsible for freeing `url.href`. pub fn parse(alloc: std.mem.Allocator, input: []const u8, base: ?[]const u8) !URL { - const u = try parseBasic(alloc, input, if (base) |b| try parseBasic(alloc, b, null, null) else null, null); - return u; + if (base) |b| { + const b_url = try parseBasic(alloc, b, null, null); + defer alloc.free(b_url.href); + return parseBasic(alloc, input, b_url, null); + } + return parseBasic(alloc, input, if (base) |b| try parseBasic(alloc, b, null, null) else null, null); } /// https://url.spec.whatwg.org/#concept-basic-url-parser @@ -976,7 +980,7 @@ fn parseIPv6(input: []const u8) !u128 { std.debug.assert(extras.matchesAll(u8, input, std.ascii.isAscii)); var pointer: usize = 0; // 5. If c is U+003A (:), then: - if (input[pointer] == ':') { + if (input.len > 0 and input[pointer] == ':') { // 1. If remaining does not start with U+003A (:), IPv6-invalid-compression validation error, return failure. if (!std.mem.startsWith(u8, input[pointer + 1 ..], ":")) return error.InvalidURL; // 2. Increase pointer by 2. @@ -1233,7 +1237,7 @@ fn parseIPv4(input: []const u8) !u32 { // 7. If any but the last item in numbers is greater than 255, then return failure. for (0..numbers_len - 1) |i| if (numbers[i] > 255) return error.InvalidURL; // 8. If the last item in numbers is greater than or equal to 256^(5 − numbers’s size), then return failure. - if (numbers[numbers_len - 1] >= std.math.pow(u32, 256, 5 - numbers_len)) return error.InvalidURL; + if (numbers[numbers_len - 1] >= std.math.pow(u64, 256, 5 - numbers_len)) return error.InvalidURL; // 9. Let ipv4 be the last item in numbers. var ipv4 = numbers[numbers_len - 1]; // 10. Remove the last item from numbers. diff --git a/zig-out/test.zig b/zig-out/test.zig index f3d3a74e8d6b8688df164a11ec878896a9f79f23..e85facde221c8342a8b4eb65ef865e1f4092e64f 100644 --- a/zig-out/test.zig +++ b/zig-out/test.zig @@ -264,6 +264,66 @@ test { try parseFail("stun://test:test", null); } test { try parseFail("stun://[:1]", null); } test { try parseFail("non-special://host\\a", null); } +test { try parseFail("http://f:b/c", "http://example.org/foo/bar"); } +test { try parseFail("http://f: /c", "http://example.org/foo/bar"); } +test { try parseFail("http://f:fifty-two/c", "http://example.org/foo/bar"); } +test { try parseFail("http://f:999999/c", "http://example.org/foo/bar"); } +test { try parseFail("non-special://f:999999/c", "http://example.org/foo/bar"); } +test { try parseFail("http://f: 21 / b ? d # e ", "http://example.org/foo/bar"); } +test { try parseFail("http://[1::2]:3:4", "http://example.org/foo/bar"); } +test { try parseFail("http://2001::1", "http://example.org/foo/bar"); } +test { try parseFail("http://2001::1]", "http://example.org/foo/bar"); } +test { try parseFail("http://2001::1]:80", "http://example.org/foo/bar"); } +test { try parseFail("http://[::127.0.0.1.]", "http://example.org/foo/bar"); } +test { try parseFail("http://example example.com", "http://other.com/"); } +test { try parseFail("http://Goo%20 goo%7C|.com", "http://other.com/"); } +test { try parseFail("http://[]", "http://other.com/"); } +test { try parseFail("http://[:]", "http://other.com/"); } +test { try parseFail("http://GOO\xc2\xa0\xe3\x80\x80goo.com", "http://other.com/"); } +test { try parseFail("http://\xef\xb7\x90zyx.com", "http://other.com/"); } +test { try parseFail("http://%ef%b7%90zyx.com", "http://other.com/"); } +test { try parseFail("http://\xef\xbc\x85\xef\xbc\x94\xef\xbc\x91.com", "http://other.com/"); } +test { try parseFail("http://%ef%bc%85%ef%bc%94%ef%bc%91.com", "http://other.com/"); } +test { try parseFail("http://\xef\xbc\x85\xef\xbc\x90\xef\xbc\x90.com", "http://other.com/"); } +test { try parseFail("http://%ef%bc%85%ef%bc%90%ef%bc%90.com", "http://other.com/"); } +test { try parseFail("http://%zz%66%a.com", "http://other.com/"); } +test { try parseFail("http://%25", "http://other.com/"); } +test { try parseFail("http://hello%00", "http://other.com/"); } +test { try parseFail("http://192.168.0.257", "http://other.com/"); } +test { try parseFail("http://%3g%78%63%30%2e%30%32%35%30%2E.01", "http://other.com/"); } +test { try parseFail("http://192.168.0.1 hello", "http://other.com/"); } +test { try parseFail("http://[google.com]", "http://other.com/"); } +test { try parseFail("http://[::1.2.3.4x]", "http://other.com/"); } +test { try parseFail("http://[::1.2.3.]", "http://other.com/"); } +test { try parseFail("http://[::1.2.]", "http://other.com/"); } +test { try parseFail("http://[::.1.2]", "http://other.com/"); } +test { try parseFail("http://[::1.]", "http://other.com/"); } +test { try parseFail("http://[::.1]", "http://other.com/"); } +test { try parseFail("http://[::%31]", "http://other.com/"); } +test { try parseFail("http://%5B::1]", "http://other.com/"); } +test { try parseFail("i", "sc:sd"); } +test { try parseFail("i", "sc:sd/sd"); } +test { try parseFail("../i", "sc:sd"); } +test { try parseFail("../i", "sc:sd/sd"); } +test { try parseFail("/i", "sc:sd"); } +test { try parseFail("/i", "sc:sd/sd"); } +test { try parseFail("?i", "sc:sd"); } +test { try parseFail("?i", "sc:sd/sd"); } +test { try parseFail("http:", "https://example.org/foo/bar"); } +test { try parseFail("http://10000000000", "http://other.com/"); } +test { try parseFail("http://4294967296", "http://other.com/"); } +test { try parseFail("http://0xffffffff1", "http://other.com/"); } +test { try parseFail("http://256.256.256.256", "http://other.com/"); } +test { try parseFail("http://[0:1:2:3:4:5:6:7:8]", "http://example.net/"); } +test { try parseFail("http://f:4294967377/c", "http://example.org/"); } +test { try parseFail("http://f:18446744073709551697/c", "http://example.org/"); } +test { try parseFail("http://f:340282366920938463463374607431768211537/c", "http://example.org/"); } +test { try parseFail("test-a-colon.html", "a:"); } +test { try parseFail("test-a-colon-b.html", "a:b"); } +test { try parseFail("http://1.2.3.4.5", "http://other.com/"); } +test { try parseFail("http://1.2.3.4.5.", "http://other.com/"); } +test { try parseFail("http://256.256.256.256.256", "http://other.com/"); } +test { try parseFail("http://256.256.256.256.256.", "http://other.com/"); } test { try parsePass("https://test:@test", null, "https://test@test/", "https://test", "https:", "test", "", "test", "test", "", "/", "", ""); } test { try parsePass("https://:@test", null, "https://test/", "https://test", "https:", "", "", "test", "test", "", "/", "", ""); } -- 2.54.0