diff --git a/lib/fs.js b/lib/fs.js index 221f79ae0bcdd5..b804336bcf6193 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -78,6 +78,7 @@ const { const { isUint32, validateAndMaskMode, + validateInteger, validateInt32, validateUint32 } = require('internal/validators'); @@ -609,6 +610,7 @@ function truncate(path, len, callback) { len = 0; } + validateInteger(len, 'len'); callback = maybeCallback(callback); fs.open(path, 'r+', function(er, fd) { if (er) return callback(er); @@ -649,11 +651,7 @@ function ftruncate(fd, len = 0, callback) { len = 0; } validateUint32(fd, 'fd'); - // TODO(BridgeAR): This does not seem right. - // There does not seem to be any validation before and if there is any, it - // should work similar to validateUint32 or not have a upper cap at all. - // This applies to all usage of `validateInt32(len, 'len')`. - validateInt32(len, 'len'); + validateInteger(len, 'len'); len = Math.max(0, len); const req = new FSReqWrap(); req.oncomplete = makeCallback(callback); @@ -662,7 +660,7 @@ function ftruncate(fd, len = 0, callback) { function ftruncateSync(fd, len = 0) { validateUint32(fd, 'fd'); - validateInt32(len, 'len'); + validateInteger(len, 'len'); len = Math.max(0, len); const ctx = {}; binding.ftruncate(fd, len, undefined, ctx); diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index 9700765f085732..687dfb5aead2a8 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -33,7 +33,7 @@ const { const { isUint32, validateAndMaskMode, - validateInt32, + validateInteger, validateUint32 } = require('internal/validators'); const pathModule = require('path'); @@ -263,7 +263,7 @@ async function truncate(path, len = 0) { async function ftruncate(handle, len = 0) { validateFileHandle(handle); - validateInt32(len, 'len'); + validateInteger(len, 'len'); len = Math.max(0, len); return binding.ftruncate(handle.fd, len, kUsePromises); } diff --git a/lib/internal/validators.js b/lib/internal/validators.js index 7fea1bdf84c173..17b10dab189133 100644 --- a/lib/internal/validators.js +++ b/lib/internal/validators.js @@ -48,6 +48,20 @@ function validateAndMaskMode(value, name, def) { throw new ERR_INVALID_ARG_VALUE(name, value, modeDesc); } +function validateInteger(value, name) { + let err; + + if (typeof value !== 'number') + err = new ERR_INVALID_ARG_TYPE(name, 'number', value); + else if (!Number.isSafeInteger(value)) + err = new ERR_OUT_OF_RANGE(name, 'an integer', value); + + if (err) { + Error.captureStackTrace(err, validateInteger); + throw err; + } +} + function validateInt32(value, name, min = -2147483648, max = 2147483647) { // The defaults for min and max correspond to the limits of 32-bit integers. if (!isInt32(value)) { @@ -93,6 +107,7 @@ module.exports = { isInt32, isUint32, validateAndMaskMode, + validateInteger, validateInt32, validateUint32 }; diff --git a/test/parallel/test-fs-truncate.js b/test/parallel/test-fs-truncate.js index eb469b8e271aed..8193e05bb7d4b0 100644 --- a/test/parallel/test-fs-truncate.js +++ b/test/parallel/test-fs-truncate.js @@ -179,6 +179,16 @@ function testFtruncate(cb) { process.on('exit', () => fs.closeSync(fd)); ['', false, null, {}, []].forEach((input) => { + assert.throws( + () => fs.truncate(file5, input, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError [ERR_INVALID_ARG_TYPE]', + message: 'The "len" argument must be of type number. ' + + `Received type ${typeof input}` + } + ); + assert.throws( () => fs.ftruncate(fd, input), { @@ -192,7 +202,7 @@ function testFtruncate(cb) { [-1.5, 1.5].forEach((input) => { assert.throws( - () => fs.ftruncate(fd, input), + () => fs.truncate(file5, input), { code: 'ERR_OUT_OF_RANGE', name: 'RangeError [ERR_OUT_OF_RANGE]', @@ -200,17 +210,14 @@ function testFtruncate(cb) { `an integer. Received ${input}` } ); - }); - // 2 ** 31 = 2147483648 - [2147483648, -2147483649].forEach((input) => { assert.throws( () => fs.ftruncate(fd, input), { code: 'ERR_OUT_OF_RANGE', name: 'RangeError [ERR_OUT_OF_RANGE]', message: 'The value of "len" is out of range. It must be ' + - `>= -2147483648 && <= 2147483647. Received ${input}` + `an integer. Received ${input}` } ); });