authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-01-24 14:58:44 -08:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-01-24 14:58:44 -08:00
loga16a1a608262e9881e127922c8f27921c4af8407
tree654651873bc39d79473127e897b258448ef9834d
parent597ddd6da5c8289836e8e4bf261bd30997b4fe17

pass parseFail with base


3 files changed, 68 insertions(+), 6 deletions(-)

generate.ts-2
...@@ -114,8 +114,6 @@ for (const c of cases) {...@@ -114,8 +114,6 @@ for (const c of cases) {
114}114}
115115
116w.write(`\n`);116w.write(`\n`);
117// prettier-ignore
118if (false)
119for (const c of cases) {117for (const c of cases) {
120 if (c.base === null) continue;118 if (c.base === null) continue;
121 if (!c.failure) continue;119 if (!c.failure) continue;
url.zig+8-4
...@@ -34,8 +34,12 @@ pub const URL = struct {...@@ -34,8 +34,12 @@ pub const URL = struct {
3434
35 /// Caller owns memory and is responsible for freeing `url.href`.35 /// Caller owns memory and is responsible for freeing `url.href`.
36 pub fn parse(alloc: std.mem.Allocator, input: []const u8, base: ?[]const u8) !URL {36 pub fn parse(alloc: std.mem.Allocator, input: []const u8, base: ?[]const u8) !URL {
37 const u = try parseBasic(alloc, input, if (base) |b| try parseBasic(alloc, b, null, null) else null, null);37 if (base) |b| {
38 return u;38 const b_url = try parseBasic(alloc, b, null, null);
39 defer alloc.free(b_url.href);
40 return parseBasic(alloc, input, b_url, null);
41 }
42 return parseBasic(alloc, input, if (base) |b| try parseBasic(alloc, b, null, null) else null, null);
39 }43 }
4044
41 /// https://url.spec.whatwg.org/#concept-basic-url-parser45 /// https://url.spec.whatwg.org/#concept-basic-url-parser
...@@ -976,7 +980,7 @@ fn parseIPv6(input: []const u8) !u128 {...@@ -976,7 +980,7 @@ fn parseIPv6(input: []const u8) !u128 {
976 std.debug.assert(extras.matchesAll(u8, input, std.ascii.isAscii));980 std.debug.assert(extras.matchesAll(u8, input, std.ascii.isAscii));
977 var pointer: usize = 0;981 var pointer: usize = 0;
978 // 5. If c is U+003A (:), then:982 // 5. If c is U+003A (:), then:
979 if (input[pointer] == ':') {983 if (input.len > 0 and input[pointer] == ':') {
980 // 1. If remaining does not start with U+003A (:), IPv6-invalid-compression validation error, return failure.984 // 1. If remaining does not start with U+003A (:), IPv6-invalid-compression validation error, return failure.
981 if (!std.mem.startsWith(u8, input[pointer + 1 ..], ":")) return error.InvalidURL;985 if (!std.mem.startsWith(u8, input[pointer + 1 ..], ":")) return error.InvalidURL;
982 // 2. Increase pointer by 2.986 // 2. Increase pointer by 2.
...@@ -1233,7 +1237,7 @@ fn parseIPv4(input: []const u8) !u32 {...@@ -1233,7 +1237,7 @@ fn parseIPv4(input: []const u8) !u32 {
1233 // 7. If any but the last item in numbers is greater than 255, then return failure.1237 // 7. If any but the last item in numbers is greater than 255, then return failure.
1234 for (0..numbers_len - 1) |i| if (numbers[i] > 255) return error.InvalidURL;1238 for (0..numbers_len - 1) |i| if (numbers[i] > 255) return error.InvalidURL;
1235 // 8. If the last item in numbers is greater than or equal to 256^(5 − numbers’s size), then return failure.1239 // 8. If the last item in numbers is greater than or equal to 256^(5 − numbers’s size), then return failure.
1236 if (numbers[numbers_len - 1] >= std.math.pow(u32, 256, 5 - numbers_len)) return error.InvalidURL;1240 if (numbers[numbers_len - 1] >= std.math.pow(u64, 256, 5 - numbers_len)) return error.InvalidURL;
1237 // 9. Let ipv4 be the last item in numbers.1241 // 9. Let ipv4 be the last item in numbers.
1238 var ipv4 = numbers[numbers_len - 1];1242 var ipv4 = numbers[numbers_len - 1];
1239 // 10. Remove the last item from numbers.1243 // 10. Remove the last item from numbers.
zig-out/test.zig+60
...@@ -264,6 +264,66 @@ test { try parseFail("stun://test:test", null); }...@@ -264,6 +264,66 @@ test { try parseFail("stun://test:test", null); }
264test { try parseFail("stun://[:1]", null); }264test { try parseFail("stun://[:1]", null); }
265test { try parseFail("non-special://host\\a", null); }265test { try parseFail("non-special://host\\a", null); }
266266
267test { try parseFail("http://f:b/c", "http://example.org/foo/bar"); }
268test { try parseFail("http://f: /c", "http://example.org/foo/bar"); }
269test { try parseFail("http://f:fifty-two/c", "http://example.org/foo/bar"); }
270test { try parseFail("http://f:999999/c", "http://example.org/foo/bar"); }
271test { try parseFail("non-special://f:999999/c", "http://example.org/foo/bar"); }
272test { try parseFail("http://f: 21 / b ? d # e ", "http://example.org/foo/bar"); }
273test { try parseFail("http://[1::2]:3:4", "http://example.org/foo/bar"); }
274test { try parseFail("http://2001::1", "http://example.org/foo/bar"); }
275test { try parseFail("http://2001::1]", "http://example.org/foo/bar"); }
276test { try parseFail("http://2001::1]:80", "http://example.org/foo/bar"); }
277test { try parseFail("http://[::127.0.0.1.]", "http://example.org/foo/bar"); }
278test { try parseFail("http://example example.com", "http://other.com/"); }
279test { try parseFail("http://Goo%20 goo%7C|.com", "http://other.com/"); }
280test { try parseFail("http://[]", "http://other.com/"); }
281test { try parseFail("http://[:]", "http://other.com/"); }
282test { try parseFail("http://GOO\xc2\xa0\xe3\x80\x80goo.com", "http://other.com/"); }
283test { try parseFail("http://\xef\xb7\x90zyx.com", "http://other.com/"); }
284test { try parseFail("http://%ef%b7%90zyx.com", "http://other.com/"); }
285test { try parseFail("http://\xef\xbc\x85\xef\xbc\x94\xef\xbc\x91.com", "http://other.com/"); }
286test { try parseFail("http://%ef%bc%85%ef%bc%94%ef%bc%91.com", "http://other.com/"); }
287test { try parseFail("http://\xef\xbc\x85\xef\xbc\x90\xef\xbc\x90.com", "http://other.com/"); }
288test { try parseFail("http://%ef%bc%85%ef%bc%90%ef%bc%90.com", "http://other.com/"); }
289test { try parseFail("http://%zz%66%a.com", "http://other.com/"); }
290test { try parseFail("http://%25", "http://other.com/"); }
291test { try parseFail("http://hello%00", "http://other.com/"); }
292test { try parseFail("http://192.168.0.257", "http://other.com/"); }
293test { try parseFail("http://%3g%78%63%30%2e%30%32%35%30%2E.01", "http://other.com/"); }
294test { try parseFail("http://192.168.0.1 hello", "http://other.com/"); }
295test { try parseFail("http://[google.com]", "http://other.com/"); }
296test { try parseFail("http://[::1.2.3.4x]", "http://other.com/"); }
297test { try parseFail("http://[::1.2.3.]", "http://other.com/"); }
298test { try parseFail("http://[::1.2.]", "http://other.com/"); }
299test { try parseFail("http://[::.1.2]", "http://other.com/"); }
300test { try parseFail("http://[::1.]", "http://other.com/"); }
301test { try parseFail("http://[::.1]", "http://other.com/"); }
302test { try parseFail("http://[::%31]", "http://other.com/"); }
303test { try parseFail("http://%5B::1]", "http://other.com/"); }
304test { try parseFail("i", "sc:sd"); }
305test { try parseFail("i", "sc:sd/sd"); }
306test { try parseFail("../i", "sc:sd"); }
307test { try parseFail("../i", "sc:sd/sd"); }
308test { try parseFail("/i", "sc:sd"); }
309test { try parseFail("/i", "sc:sd/sd"); }
310test { try parseFail("?i", "sc:sd"); }
311test { try parseFail("?i", "sc:sd/sd"); }
312test { try parseFail("http:", "https://example.org/foo/bar"); }
313test { try parseFail("http://10000000000", "http://other.com/"); }
314test { try parseFail("http://4294967296", "http://other.com/"); }
315test { try parseFail("http://0xffffffff1", "http://other.com/"); }
316test { try parseFail("http://256.256.256.256", "http://other.com/"); }
317test { try parseFail("http://[0:1:2:3:4:5:6:7:8]", "http://example.net/"); }
318test { try parseFail("http://f:4294967377/c", "http://example.org/"); }
319test { try parseFail("http://f:18446744073709551697/c", "http://example.org/"); }
320test { try parseFail("http://f:340282366920938463463374607431768211537/c", "http://example.org/"); }
321test { try parseFail("test-a-colon.html", "a:"); }
322test { try parseFail("test-a-colon-b.html", "a:b"); }
323test { try parseFail("http://1.2.3.4.5", "http://other.com/"); }
324test { try parseFail("http://1.2.3.4.5.", "http://other.com/"); }
325test { try parseFail("http://256.256.256.256.256", "http://other.com/"); }
326test { try parseFail("http://256.256.256.256.256.", "http://other.com/"); }
267327
268test { try parsePass("https://test:@test", null, "https://test@test/", "https://test", "https:", "test", "", "test", "test", "", "/", "", ""); }328test { try parsePass("https://test:@test", null, "https://test@test/", "https://test", "https:", "test", "", "test", "test", "", "/", "", ""); }
269test { try parsePass("https://:@test", null, "https://test/", "https://test", "https:", "", "", "test", "test", "", "/", "", ""); }329test { try parsePass("https://:@test", null, "https://test/", "https://test", "https:", "", "", "test", "test", "", "/", "", ""); }