Skip to content

Commit

Permalink
fs: fix error when writing buffers > INT32_MAX
Browse files Browse the repository at this point in the history
This reverts c380ee6.
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: #38546
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
  • Loading branch information
zbjornson authored and jasnell committed May 10, 2021
1 parent 16982b6 commit 8886b63
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 2 deletions.
2 changes: 2 additions & 0 deletions lib/internal/fs/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,8 @@ const validateOffsetLengthWrite = hideStackFrames(
if (length < 0) {
throw new ERR_OUT_OF_RANGE('length', '>= 0', length);
}

validateInt32(length, 'length', 0);
}
);

Expand Down
4 changes: 2 additions & 2 deletions src/node_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1835,8 +1835,8 @@ static void WriteBuffer(const FunctionCallbackInfo<Value>& args) {
CHECK_LE(static_cast<uint64_t>(off_64), buffer_length);
const size_t off = static_cast<size_t>(off_64);

CHECK(IsSafeJsInt(args[3]));
const size_t len = static_cast<size_t>(args[3].As<Integer>()->Value());
CHECK(args[3]->IsInt32());
const size_t len = static_cast<size_t>(args[3].As<Int32>()->Value());
CHECK(Buffer::IsWithinBounds(off, len, buffer_length));
CHECK_LE(len, buffer_length);
CHECK_GE(off + len, off);
Expand Down
40 changes: 40 additions & 0 deletions test/parallel/test-fs-write-buffer-large.js
Original file line number Diff line number Diff line change
@@ -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);
}));

0 comments on commit 8886b63

Please sign in to comment.