From c4e7dca8f30ff89b42e96fb8819558ed518a72dd Mon Sep 17 00:00:00 2001 From: Zach Bjornson Date: Tue, 4 May 2021 22:24:29 -0700 Subject: [PATCH] fs: fix error when writing buffers > INT32_MAX This reverts c380ee6785b72fd2f24803de80bb412dfc32e8a9. uv_fs_write returns an int, so it is not possible to ask it to write more than INT32_MAX. Instead, validate 'length' is an int32 in JS to avoid the assertion failure. PR-URL: https://github.com/nodejs/node/pull/38546 Reviewed-By: James M Snell Reviewed-By: Darshan Sen Reviewed-By: Rich Trott Reviewed-By: Luigi Pinca --- lib/internal/fs/utils.js | 2 ++ src/node_file.cc | 4 +-- test/parallel/test-fs-write-buffer-large.js | 40 +++++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 test/parallel/test-fs-write-buffer-large.js diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index abc12b7b02a4ff..823c862a6d71ad 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -624,6 +624,8 @@ const validateOffsetLengthWrite = hideStackFrames( if (length < 0) { throw new ERR_OUT_OF_RANGE('length', '>= 0', length); } + + validateInt32(length, 'length', 0); } ); diff --git a/src/node_file.cc b/src/node_file.cc index cce3540a49027f..85b3f0dae559df 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -1831,8 +1831,8 @@ static void WriteBuffer(const FunctionCallbackInfo& args) { CHECK_LE(static_cast(off_64), buffer_length); const size_t off = static_cast(off_64); - CHECK(IsSafeJsInt(args[3])); - const size_t len = static_cast(args[3].As()->Value()); + CHECK(args[3]->IsInt32()); + const size_t len = static_cast(args[3].As()->Value()); CHECK(Buffer::IsWithinBounds(off, len, buffer_length)); CHECK_LE(len, buffer_length); CHECK_GE(off + len, off); diff --git a/test/parallel/test-fs-write-buffer-large.js b/test/parallel/test-fs-write-buffer-large.js new file mode 100644 index 00000000000000..a80072354eaa0f --- /dev/null +++ b/test/parallel/test-fs-write-buffer-large.js @@ -0,0 +1,40 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const path = require('path'); +const fs = require('fs'); + +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); + +// fs.write with length > INT32_MAX + +common.skipIf32Bits(); + +let buf; +try { + buf = Buffer.allocUnsafe(0x7FFFFFFF + 1); +} catch (e) { + // If the exception is not due to memory confinement then rethrow it. + if (e.message !== 'Array buffer allocation failed') throw (e); + common.skip('skipped due to memory requirements'); +} + +const filename = path.join(tmpdir.path, 'write9.txt'); +fs.open(filename, 'w', 0o644, common.mustSucceed((fd) => { + assert.throws(() => { + fs.write(fd, + buf, + 0, + 0x7FFFFFFF + 1, + 0, + common.mustNotCall()); + }, { + code: 'ERR_OUT_OF_RANGE', + name: 'RangeError', + message: 'The value of "length" is out of range. ' + + 'It must be >= 0 && <= 2147483647. Received 2147483648' + }); + + fs.closeSync(fd); +}));