Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
crypto: fix regression in randomFill/randomBytes
Fixes a segfault when a buffer larger than 2**31-1 is passed in
to randomFill/randomFillSync or when a size larger than 2**31-1
is passed in to randomBytes.

Signed-off-by: James M Snell <jasnell@gmail.com>
  • Loading branch information
jasnell committed Sep 9, 2020
commit 4d516dd4191e346416a97051eaeacc2d71f7c642
6 changes: 5 additions & 1 deletion src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5855,6 +5855,7 @@ struct RandomBytesJob : public CryptoJob {


void RandomBytes(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK(args[0]->IsArrayBufferView()); // buffer; wrap object retains ref.
CHECK(args[1]->IsUint32()); // offset
CHECK(args[2]->IsUint32()); // size
Expand All @@ -5863,7 +5864,10 @@ void RandomBytes(const FunctionCallbackInfo<Value>& args) {
const uint32_t size = args[2].As<Uint32>()->Value();
CHECK_GE(offset + size, offset); // Overflow check.
CHECK_LE(offset + size, Buffer::Length(args[0])); // Bounds check.
Environment* env = Environment::GetCurrent(args);

if (size > INT_MAX)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it better to do proper validation in JS and only use CHECK_LE here?

return THROW_ERR_OUT_OF_RANGE(env, "buffer is too large");

std::unique_ptr<RandomBytesJob> job(new RandomBytesJob(env));
job->data = reinterpret_cast<unsigned char*>(Buffer::Data(args[0])) + offset;
job->size = size;
Expand Down
2 changes: 1 addition & 1 deletion test/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ function platformTimeout(ms) {
}

let knownGlobals = [
AbortController,
// AbortController,
Comment thread
jasnell marked this conversation as resolved.
Outdated
Comment thread
jasnell marked this conversation as resolved.
Outdated
clearImmediate,
clearInterval,
clearTimeout,
Expand Down
32 changes: 32 additions & 0 deletions test/parallel/test-crypto-random-regression.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';
const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');

const { Buffer } = require('buffer');
const assert = require('assert');

const {
randomFill,
randomFillSync,
randomBytes
} = require('crypto');

let kData;
try {
kData = Buffer.alloc(2 ** 31 + 1);
} catch {
common.skip('not enough memory');
}

assert.throws(() => randomFill(kData, common.mustNotCall()), {
code: 'ERR_OUT_OF_RANGE'
});

assert.throws(() => randomFillSync(kData), {
code: 'ERR_OUT_OF_RANGE'
});

assert.throws(() => randomBytes(2 ** 31 + 1), {
code: 'ERR_OUT_OF_RANGE'
});