mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-22 04:34:44 +00:00
Merge pull request #1674 from lightpanda-io/atob-unpadded-base64
accept must accept unpadded data in atob
This commit is contained in:
@@ -75,6 +75,16 @@
|
|||||||
testing.expectEqual('abc', atob('YWJj'));
|
testing.expectEqual('abc', atob('YWJj'));
|
||||||
testing.expectEqual('0123456789', atob('MDEyMzQ1Njc4OQ=='));
|
testing.expectEqual('0123456789', atob('MDEyMzQ1Njc4OQ=='));
|
||||||
testing.expectEqual('The quick brown fox jumps over the lazy dog', atob('VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw=='));
|
testing.expectEqual('The quick brown fox jumps over the lazy dog', atob('VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw=='));
|
||||||
|
|
||||||
|
// atob must accept unpadded base64 (forgiving-base64 decode per HTML spec)
|
||||||
|
testing.expectEqual('a', atob('YQ')); // 2 chars, len%4==2, needs '=='
|
||||||
|
testing.expectEqual('ab', atob('YWI')); // 3 chars, len%4==3, needs '='
|
||||||
|
testing.expectEqual('ceil', atob('Y2VpbA')); // 6 chars, len%4==2, needs '=='
|
||||||
|
|
||||||
|
// length % 4 == 1 must still throw
|
||||||
|
testing.expectError('Error: InvalidCharacterError', () => {
|
||||||
|
atob('Y');
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script id=btoa_atob_roundtrip>
|
<script id=btoa_atob_roundtrip>
|
||||||
|
|||||||
@@ -396,9 +396,28 @@ pub fn btoa(_: *const Window, input: []const u8, page: *Page) ![]const u8 {
|
|||||||
|
|
||||||
pub fn atob(_: *const Window, input: []const u8, page: *Page) ![]const u8 {
|
pub fn atob(_: *const Window, input: []const u8, page: *Page) ![]const u8 {
|
||||||
const trimmed = std.mem.trim(u8, input, &std.ascii.whitespace);
|
const trimmed = std.mem.trim(u8, input, &std.ascii.whitespace);
|
||||||
const decoded_len = std.base64.standard.Decoder.calcSizeForSlice(trimmed) catch return error.InvalidCharacterError;
|
// Per HTML spec "forgiving-base64 decode" algorithm:
|
||||||
|
// https://infra.spec.whatwg.org/#forgiving-base64-decode
|
||||||
|
const padded: []const u8 = switch (trimmed.len % 4) {
|
||||||
|
1 => return error.InvalidCharacterError,
|
||||||
|
2 => blk: {
|
||||||
|
const buf = try page.call_arena.alloc(u8, trimmed.len + 2);
|
||||||
|
@memcpy(buf[0..trimmed.len], trimmed);
|
||||||
|
buf[trimmed.len] = '=';
|
||||||
|
buf[trimmed.len + 1] = '=';
|
||||||
|
break :blk buf;
|
||||||
|
},
|
||||||
|
3 => blk: {
|
||||||
|
const buf = try page.call_arena.alloc(u8, trimmed.len + 1);
|
||||||
|
@memcpy(buf[0..trimmed.len], trimmed);
|
||||||
|
buf[trimmed.len] = '=';
|
||||||
|
break :blk buf;
|
||||||
|
},
|
||||||
|
else => trimmed,
|
||||||
|
};
|
||||||
|
const decoded_len = std.base64.standard.Decoder.calcSizeForSlice(padded) catch return error.InvalidCharacterError;
|
||||||
const decoded = try page.call_arena.alloc(u8, decoded_len);
|
const decoded = try page.call_arena.alloc(u8, decoded_len);
|
||||||
std.base64.standard.Decoder.decode(decoded, trimmed) catch return error.InvalidCharacterError;
|
std.base64.standard.Decoder.decode(decoded, padded) catch return error.InvalidCharacterError;
|
||||||
return decoded;
|
return decoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user