From 837137fe469e563ea44a830b80ad11eeb6f058ba Mon Sep 17 00:00:00 2001 From: James M Snell Date: Mon, 26 Apr 2021 10:58:41 -0700 Subject: [PATCH] src: fix validation of negative offset to avoid abort Fixes: https://github.com/nodejs/node/issues/24640 Signed-off-by: James M Snell --- lib/fs.js | 8 +-- lib/internal/fs/promises.js | 4 +- lib/internal/fs/utils.js | 4 ++ test/parallel/test-fs-read-type.js | 4 -- test/parallel/test-fs-write-negativeoffset.js | 55 +++++++++++++++++++ 5 files changed, 65 insertions(+), 10 deletions(-) create mode 100644 test/parallel/test-fs-write-negativeoffset.js diff --git a/lib/fs.js b/lib/fs.js index e6cf8527e8720d..9078343263437c 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -543,7 +543,7 @@ function read(fd, buffer, offset, length, position, callback) { if (offset == null) { offset = 0; } else { - validateInteger(offset, 'offset'); + validateInteger(offset, 'offset', 0); } length |= 0; @@ -599,7 +599,7 @@ function readSync(fd, buffer, offset, length, position) { if (offset == null) { offset = 0; } else { - validateInteger(offset, 'offset'); + validateInteger(offset, 'offset', 0); } length |= 0; @@ -679,7 +679,7 @@ function write(fd, buffer, offset, length, position, callback) { if (offset == null || typeof offset === 'function') { offset = 0; } else { - validateInteger(offset, 'offset'); + validateInteger(offset, 'offset', 0); } if (typeof length !== 'number') length = buffer.byteLength - offset; @@ -730,7 +730,7 @@ function writeSync(fd, buffer, offset, length, position) { if (offset == null) { offset = 0; } else { - validateInteger(offset, 'offset'); + validateInteger(offset, 'offset', 0); } if (typeof length !== 'number') length = buffer.byteLength - offset; diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index 75052ab4c4f20f..e7f38219178952 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -432,7 +432,7 @@ async function read(handle, bufferOrOptions, offset, length, position) { if (offset == null) { offset = 0; } else { - validateInteger(offset, 'offset'); + validateInteger(offset, 'offset', 0); } length |= 0; @@ -475,7 +475,7 @@ async function write(handle, buffer, offset, length, position) { if (offset == null) { offset = 0; } else { - validateInteger(offset, 'offset'); + validateInteger(offset, 'offset', 0); } if (typeof length !== 'number') length = buffer.byteLength - offset; diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index bf4d8457531c0b..6bbc06f7a1ea85 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -655,6 +655,10 @@ const validateOffsetLengthWrite = hideStackFrames( if (length > byteLength - offset) { throw new ERR_OUT_OF_RANGE('length', `<= ${byteLength - offset}`, length); } + + if (length < 0) { + throw new ERR_OUT_OF_RANGE('length', '> 0', length); + } } ); diff --git a/test/parallel/test-fs-read-type.js b/test/parallel/test-fs-read-type.js index 81440ab57eb802..2baab18dc9f483 100644 --- a/test/parallel/test-fs-read-type.js +++ b/test/parallel/test-fs-read-type.js @@ -44,8 +44,6 @@ assert.throws(() => { }, { code: 'ERR_OUT_OF_RANGE', name: 'RangeError', - message: 'The value of "offset" is out of range. It must be >= 0. ' + - 'Received -1' }); assert.throws(() => { @@ -157,8 +155,6 @@ assert.throws(() => { }, { code: 'ERR_OUT_OF_RANGE', name: 'RangeError', - message: 'The value of "offset" is out of range. ' + - 'It must be >= 0. Received -1' }); assert.throws(() => { diff --git a/test/parallel/test-fs-write-negativeoffset.js b/test/parallel/test-fs-write-negativeoffset.js new file mode 100644 index 00000000000000..b1c6ed9039b7d7 --- /dev/null +++ b/test/parallel/test-fs-write-negativeoffset.js @@ -0,0 +1,55 @@ +'use strict'; + +// Tests that passing a negative offset does not crash the process + +const common = require('../common'); + +const { + join, +} = require('path'); + +const { + closeSync, + open, + write, + writeSync, +} = require('fs'); + +const assert = require('assert'); + +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); + +const filename = join(tmpdir.path, 'test.txt'); + +open(filename, 'w+', common.mustSucceed((fd) => { + assert.throws(() => { + write(fd, Buffer.alloc(0), -1, common.mustNotCall()); + }, { + code: 'ERR_OUT_OF_RANGE', + }); + assert.throws(() => { + writeSync(fd, Buffer.alloc(0), -1); + }, { + code: 'ERR_OUT_OF_RANGE', + }); + closeSync(fd); +})); + +const filename2 = join(tmpdir.path, 'test2.txt'); + +// Make sure negative length's don't cause aborts either + +open(filename2, 'w+', common.mustSucceed((fd) => { + assert.throws(() => { + write(fd, Buffer.alloc(0), 0, -1, common.mustNotCall()); + }, { + code: 'ERR_OUT_OF_RANGE', + }); + assert.throws(() => { + writeSync(fd, Buffer.alloc(0), 0, -1); + }, { + code: 'ERR_OUT_OF_RANGE', + }); + closeSync(fd); +}));