From 75eaf25e78fcb21b338855404b2a6082a4414911 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Wed, 20 Mar 2019 17:10:06 +0100 Subject: buffer: use stricter `from()` input validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far we did not throw an error for all types of invalid input. Functions do not return a buffer anymore and `number` and `symbol` validation is also improved. PR-URL: https://github.com/nodejs/node/pull/26825 Fixes: https://github.com/nodejs/node/issues/26741 Reviewed-By: Matteo Collina Reviewed-By: Yongsheng Zhang Reviewed-By: Michaƫl Zasso --- lib/buffer.js | 38 ++++++++++++------------------- test/parallel/test-buffer-bad-overload.js | 17 -------------- test/parallel/test-buffer-from.js | 34 +++++++++++++-------------- 3 files changed, 30 insertions(+), 59 deletions(-) delete mode 100644 test/parallel/test-buffer-bad-overload.js diff --git a/lib/buffer.js b/lib/buffer.js index 66c345885a..b5d89625b2 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -195,33 +195,23 @@ Buffer.from = function from(value, encodingOrOffset, length) { if (typeof value === 'string') return fromString(value, encodingOrOffset); - if (isAnyArrayBuffer(value)) - return fromArrayBuffer(value, encodingOrOffset, length); + if (typeof value === 'object' && value !== null) { + if (isAnyArrayBuffer(value)) + return fromArrayBuffer(value, encodingOrOffset, length); - if (value === null || value === undefined) { - throw new ERR_INVALID_ARG_TYPE( - 'first argument', - ['string', 'Buffer', 'ArrayBuffer', 'Array', 'Array-like Object'], - value - ); - } - - if (typeof value === 'number') { - throw new ERR_INVALID_ARG_TYPE('value', 'not number', value); - } + const valueOf = value.valueOf && value.valueOf(); + if (valueOf !== null && valueOf !== undefined && valueOf !== value) + return Buffer.from(valueOf, encodingOrOffset, length); - const valueOf = value.valueOf && value.valueOf(); - if (valueOf !== null && valueOf !== undefined && valueOf !== value) - return Buffer.from(valueOf, encodingOrOffset, length); - - const b = fromObject(value); - if (b) - return b; + const b = fromObject(value); + if (b) + return b; - if (typeof value[Symbol.toPrimitive] === 'function') { - return Buffer.from(value[Symbol.toPrimitive]('string'), - encodingOrOffset, - length); + if (typeof value[Symbol.toPrimitive] === 'function') { + return Buffer.from(value[Symbol.toPrimitive]('string'), + encodingOrOffset, + length); + } } throw new ERR_INVALID_ARG_TYPE( diff --git a/test/parallel/test-buffer-bad-overload.js b/test/parallel/test-buffer-bad-overload.js deleted file mode 100644 index 63acb8ebfb..0000000000 --- a/test/parallel/test-buffer-bad-overload.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; -const common = require('../common'); -const assert = require('assert'); - -Buffer.allocUnsafe(10); // Should not throw. - -const err = common.expectsError({ - code: 'ERR_INVALID_ARG_TYPE', - type: TypeError, - message: 'The "value" argument must not be of type number. ' + - 'Received type number' -}); -assert.throws(function() { - Buffer.from(10, 'hex'); -}, err); - -Buffer.from('deadbeaf', 'hex'); // Should not throw. diff --git a/test/parallel/test-buffer-from.js b/test/parallel/test-buffer-from.js index e8a9196b3d..ec79838169 100644 --- a/test/parallel/test-buffer-from.js +++ b/test/parallel/test-buffer-from.js @@ -1,6 +1,6 @@ 'use strict'; -const common = require('../common'); +require('../common'); const { deepStrictEqual, throws } = require('assert'); const { runInNewContext } = require('vm'); @@ -40,27 +40,25 @@ deepStrictEqual( [{ valueOf() { return null; } }, 'object'], [{ valueOf() { return undefined; } }, 'object'], [{ valueOf: null }, 'object'], - [Object.create(null), 'object'] + [Object.create(null), 'object'], + [new Number(true), 'number'], + [new MyBadPrimitive(), 'number'], + [Symbol(), 'symbol'], + [5n, 'bigint'], + [(one, two, three) => {}, 'function'], + [undefined, 'undefined'], + [null, 'object'] ].forEach(([input, actualType]) => { - const err = common.expectsError({ + const errObj = { code: 'ERR_INVALID_ARG_TYPE', - type: TypeError, + name: 'TypeError', message: 'The first argument must be one of type string, Buffer, ' + 'ArrayBuffer, Array, or Array-like Object. Received ' + `type ${actualType}` - }); - throws(() => Buffer.from(input), err); + }; + throws(() => Buffer.from(input), errObj); + throws(() => Buffer.from(input, 'hex'), errObj); }); -[ - new Number(true), - new MyBadPrimitive() -].forEach((input) => { - const errMsg = common.expectsError({ - code: 'ERR_INVALID_ARG_TYPE', - type: TypeError, - message: 'The "value" argument must not be of type number. ' + - 'Received type number' - }); - throws(() => Buffer.from(input), errMsg); -}); +Buffer.allocUnsafe(10); // Should not throw. +Buffer.from('deadbeaf', 'hex'); // Should not throw. -- cgit v1.2.3