From 473c3521d824149a1b6e528275fc00b0fb5012d2 Mon Sep 17 00:00:00 2001 From: Austin Kelleher Date: Fri, 8 Apr 2022 16:59:40 -0400 Subject: [PATCH] buffer: atob throw error when the input string is invalid The specification of `atob` has various different conditions that we need to abide by. The specific changes that were made: * `atob` now immediately throws when `undefined`, `false`, or a `number` is supplied * `atob` now strips ASCII whitespace before attempting to decode * `atob` now validates that the code point's length divided by 4 leaves a remainder that is not 1 See: https://infra.spec.whatwg.org/#forgiving-base64-decode Fixes: https://github.com/nodejs/node/issues/42646 --- lib/buffer.js | 23 ++++++++++++++++++++++- test/parallel/test-btoa-atob.js | 9 +++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/buffer.js b/lib/buffer.js index 773d56572aa2a4..2b7536643ba95d 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -1259,7 +1259,28 @@ function atob(input) { if (arguments.length === 0) { throw new ERR_MISSING_ARGS('input'); } - input = `${input}`; + + if (input === undefined || input === false || typeof input === 'number') { + throw lazyDOMException( + 'The string to be decoded is not correctly encoded.', + 'ValidationError'); + } + + // Remove all ASCII whitespace from data. + // + // See #1 - https://infra.spec.whatwg.org/#forgiving-base64 + input = `${input}`.replace(/\s/g, ''); + + // If data's code point length divides by 4 leaving a remainder of 1, then + // return failure. + // + // See #3 - https://infra.spec.whatwg.org/#forgiving-base64 + if (input.length % 4 === 1) { + throw lazyDOMException( + 'The string to be decoded is not correctly encoded.', + 'ValidationError'); + } + for (let n = 0; n < input.length; n++) { if (!ArrayPrototypeIncludes(kForgivingBase64AllowedChars, StringPrototypeCharCodeAt(input, n))) diff --git a/test/parallel/test-btoa-atob.js b/test/parallel/test-btoa-atob.js index 64f53671030ba0..3a9786f7a62111 100644 --- a/test/parallel/test-btoa-atob.js +++ b/test/parallel/test-btoa-atob.js @@ -15,3 +15,12 @@ throws(() => buffer.btoa(), /TypeError/); strictEqual(atob(' '), ''); strictEqual(atob(' YW\tJ\njZA=\r= '), 'abcd'); + +throws(() => buffer.atob(undefined), /ValidationError/); +throws(() => buffer.atob(false), /ValidationError/); +throws(() => buffer.atob(1), /ValidationError/); +throws(() => buffer.atob(0), /ValidationError/); +throws(() => buffer.atob('a'), /ValidationError/); +throws(() => buffer.atob('a '), /ValidationError/); +throws(() => buffer.atob(' a'), /ValidationError/); +throws(() => buffer.atob('aaaaa'), /ValidationError/);