mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-09-23 21:15:31 -04:00
Merge pull request #3263 from lightpanda-io/usp-invalid-escapes
webapi: URLSearchParams passes invalid percent-escapes through
This commit is contained in:
2 files changed
+25
-8
No files matched your search
@@ -635,3 +635,20 @@
|
||||
testing.expectEqual('param1=1', usp.toString());
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id=invalidPercentEscapes>
|
||||
{
|
||||
// An invalid %XX escape is not an error; the bytes pass through literally.
|
||||
testing.expectEqual('%', new URLSearchParams('id=0&value=%').get('value'));
|
||||
testing.expectEqual('%2sf*', new URLSearchParams('b=%2sf%2a').get('b'));
|
||||
testing.expectEqual('%2*f*', new URLSearchParams('b=%2%2af%2a').get('b'));
|
||||
testing.expectEqual('%*', new URLSearchParams('b=%%2a').get('b'));
|
||||
testing.expectEqual('a', new URLSearchParams('%=a').get('%'));
|
||||
testing.expectEqual('a', new URLSearchParams('%a=a').get('%a'));
|
||||
|
||||
// ... and they re-serialize with the '%' escaped.
|
||||
testing.expectEqual('id=0&value=%25', new URLSearchParams('id=0&value=%').toString());
|
||||
testing.expectEqual('b=%252sf*', new URLSearchParams('b=%2sf%2a').toString());
|
||||
testing.expectEqual('b=%25*', new URLSearchParams('b=%%2a').toString());
|
||||
}
|
||||
</script>
|
||||
@@ -315,16 +315,11 @@ fn unescape(arena: Allocator, value: []const u8, buf: []u8) !String {
|
||||
var in_i: usize = 0;
|
||||
while (in_i < value.len) {
|
||||
const b = value[in_i];
|
||||
if (b == '%') {
|
||||
if (in_i + 2 >= value.len or !std.ascii.isHex(value[in_i + 1]) or !std.ascii.isHex(value[in_i + 2])) {
|
||||
return error.InvalidEscapeSequence;
|
||||
}
|
||||
if (b == '%' and isEscapeTriplet(value, in_i)) {
|
||||
in_i += 3;
|
||||
unescaped_len -= 2;
|
||||
} else if (b == '+') {
|
||||
has_plus = true;
|
||||
in_i += 1;
|
||||
} else {
|
||||
has_plus = has_plus or b == '+';
|
||||
in_i += 1;
|
||||
}
|
||||
}
|
||||
@@ -344,7 +339,7 @@ fn unescape(arena: Allocator, value: []const u8, buf: []u8) !String {
|
||||
in_i = 0;
|
||||
for (0..unescaped_len) |i| {
|
||||
const b = value[in_i];
|
||||
if (b == '%') {
|
||||
if (b == '%' and isEscapeTriplet(value, in_i)) {
|
||||
out[i] = decodeHex(value[in_i + 1]) << 4 | decodeHex(value[in_i + 2]);
|
||||
in_i += 3;
|
||||
} else if (b == '+') {
|
||||
@@ -398,6 +393,11 @@ pub const Iterator = struct {
|
||||
}
|
||||
};
|
||||
|
||||
// True when value[i] starts a valid %XX escape
|
||||
fn isEscapeTriplet(value: []const u8, i: usize) bool {
|
||||
return i + 2 < value.len and std.ascii.isHex(value[i + 1]) and std.ascii.isHex(value[i + 2]);
|
||||
}
|
||||
|
||||
const GenericIterator = @import("../collections/iterator.zig").Entry;
|
||||
pub const KeyIterator = GenericIterator(Iterator, "0");
|
||||
pub const ValueIterator = GenericIterator(Iterator, "1");
|
||||
|
||||
Reference in new issue
Block a user