diff --git a/lib/internal/crypto/random.js b/lib/internal/crypto/random.js index ee510ddf06c6ec..52afbd8af3f034 100644 --- a/lib/internal/crypto/random.js +++ b/lib/internal/crypto/random.js @@ -3,7 +3,7 @@ const errors = require('internal/errors'); const { isArrayBufferView } = require('internal/util/types'); const { - randomBytes, + randomBytes: _randomBytes, randomFill: _randomFill } = process.binding('crypto'); @@ -24,7 +24,7 @@ function assertOffset(offset, length) { } } -function assertSize(size, offset, length) { +function assertSize(size, offset = 0, length = Infinity) { if (typeof size !== 'number' || size !== size) { throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'size', 'number'); } @@ -38,6 +38,13 @@ function assertSize(size, offset, length) { } } +function randomBytes(size, cb) { + assertSize(size); + if (cb !== undefined && typeof cb !== 'function') + throw new errors.TypeError('ERR_INVALID_CALLBACK'); + return _randomBytes(size, cb); +} + function randomFillSync(buf, offset = 0, size) { if (!isArrayBufferView(buf)) { throw new errors.TypeError('ERR_INVALID_ARG_TYPE', diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 1b8d14825f5c89..45d703cba161a1 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -5526,13 +5526,8 @@ void RandomBytesProcessSync(Environment* env, void RandomBytes(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - if (!args[0]->IsNumber() || args[0].As()->Value() < 0) { - return env->ThrowTypeError("size must be a number >= 0"); - } - const int64_t size = args[0]->IntegerValue(); - if (size > Buffer::kMaxLength) - return env->ThrowTypeError("size must be a uint32"); + CHECK(size <= Buffer::kMaxLength); Local obj = env->randombytes_constructor_template()-> NewInstance(env->context()).ToLocalChecked(); diff --git a/test/parallel/test-crypto-random.js b/test/parallel/test-crypto-random.js index f5dad9d62a5490..320a4358ff3ccb 100644 --- a/test/parallel/test-crypto-random.js +++ b/test/parallel/test-crypto-random.js @@ -33,12 +33,26 @@ crypto.DEFAULT_ENCODING = 'buffer'; // bump, we register a lot of exit listeners process.setMaxListeners(256); -const expectedErrorRegexp = /^TypeError: size must be a number >= 0$/; [crypto.randomBytes, crypto.pseudoRandomBytes].forEach(function(f) { [-1, undefined, null, false, true, {}, []].forEach(function(value) { - assert.throws(function() { f(value); }, expectedErrorRegexp); - assert.throws(function() { f(value, common.mustNotCall()); }, - expectedErrorRegexp); + + common.expectsError( + () => f(value), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: /^The "size" argument must be of type (number|uint32)$/ + } + ); + + common.expectsError( + () => f(value, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: /^The "size" argument must be of type (number|uint32)$/ + } + ); }); [0, 1, 2, 4, 16, 256, 1024, 101.2].forEach(function(len) { @@ -464,9 +478,14 @@ const expectedErrorRegexp = /^TypeError: size must be a number >= 0$/; // #5126, "FATAL ERROR: v8::Object::SetIndexedPropertiesToExternalArrayData() // length exceeds max acceptable value" -assert.throws(function() { - crypto.randomBytes((-1 >>> 0) + 1); -}, /^TypeError: size must be a uint32$/); +common.expectsError( + () => crypto.randomBytes((-1 >>> 0) + 1), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "size" argument must be of type uint32' + } +); [1, true, NaN, null, undefined, {}, []].forEach((i) => { common.expectsError(