Skip to content

Commit a5828d8

Browse files
buffer: update character validation approach in atob
* Small optimization in atob validation by assuming positions of whitespace characters in allowed chars array * Improved tests for ASCII whitespace characters * Explicitly validate properties of `DOMException` in tests
1 parent a85b856 commit a5828d8

File tree

2 files changed

+20
-11
lines changed

2 files changed

+20
-11
lines changed

lib/buffer.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const {
2626
ArrayFrom,
2727
ArrayIsArray,
2828
ArrayPrototypeForEach,
29-
ArrayPrototypeIncludes,
29+
ArrayPrototypeIndexOf,
3030
MathFloor,
3131
MathMin,
3232
MathTrunc,
@@ -1232,14 +1232,12 @@ function btoa(input) {
12321232
return buf.toString('base64');
12331233
}
12341234

1235-
const asciiWhitespaceCharacters = [
1235+
// Refs: https://infra.spec.whatwg.org/#forgiving-base64-decode
1236+
const kForgivingBase64AllowedChars = [
12361237
// ASCII whitespace
12371238
// Refs: https://infra.spec.whatwg.org/#ascii-whitespace
12381239
0x09, 0x0A, 0x0C, 0x0D, 0x20,
1239-
];
12401240

1241-
// Refs: https://infra.spec.whatwg.org/#forgiving-base64-decode
1242-
const kForgivingBase64AllowedChars = [
12431241
// Uppercase letters
12441242
...ArrayFrom({ length: 26 }, (_, i) => StringPrototypeCharCodeAt('A') + i),
12451243

@@ -1266,11 +1264,13 @@ function atob(input) {
12661264
let nonAsciiWhitespaceCharCount = 0;
12671265

12681266
for (let n = 0; n < input.length; n++) {
1269-
const char = StringPrototypeCharCodeAt(input, n);
1267+
const index = ArrayPrototypeIndexOf(
1268+
kForgivingBase64AllowedChars,
1269+
StringPrototypeCharCodeAt(input, n));
12701270

1271-
if (ArrayPrototypeIncludes(kForgivingBase64AllowedChars, char)) {
1271+
if (index > 4) { // The first five char are ASCII whitespace.
12721272
nonAsciiWhitespaceCharCount++;
1273-
} else if (!ArrayPrototypeIncludes(asciiWhitespaceCharacters, char)) {
1273+
} else if (index === -1) {
12741274
throw lazyDOMException('Invalid character', 'InvalidCharacterError');
12751275
}
12761276
}

test/parallel/test-btoa-atob.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ throws(() => buffer.atob(), /TypeError/);
1414
throws(() => buffer.btoa(), /TypeError/);
1515

1616
strictEqual(atob(' '), '');
17-
strictEqual(atob(' YW\tJ\njZA=\r= '), 'abcd');
17+
strictEqual(atob(' Y\fW\tJ\njZ A=\r= '), 'abcd');
1818

1919
strictEqual(atob(null), '\x9Eée');
2020
strictEqual(atob(NaN), '5£');
@@ -26,5 +26,14 @@ strictEqual(atob({ toString: () => '' }), '');
2626
strictEqual(atob({ [Symbol.toPrimitive]: () => '' }), '');
2727

2828
throws(() => atob(Symbol()), /TypeError/);
29-
[undefined, false, () => {}, 0, 1, 0n, 1n, -Infinity, [1], {}].forEach((value) =>
30-
throws(() => atob(value), { constructor: DOMException }));
29+
[
30+
undefined, false, () => {}, {}, [1],
31+
0, 1, 0n, 1n, -Infinity,
32+
'a', 'a\n\n\n', '\ra\r\r', ' a ', '\t\t\ta', 'a\f\f\f', '\ta\r \n\f',
33+
].forEach((value) =>
34+
// See #2 - https://html.spec.whatwg.org/multipage/webappapis.html#dom-atob
35+
throws(() => atob(value), {
36+
constructor: DOMException,
37+
name: 'InvalidCharacterError',
38+
code: 5,
39+
}));

0 commit comments

Comments
 (0)