diff --git a/lib/fs.js b/lib/fs.js index 646772a813e127..7b05750307c118 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -65,7 +65,6 @@ const internalUtil = require('internal/util'); const { copyObject, getOptions, - isUint32, modeNum, nullCheck, preprocessSymlinkDestination, @@ -76,16 +75,19 @@ const { stringToSymlinkType, toUnixTimestamp, validateBuffer, - validateLen, validateOffsetLengthRead, validateOffsetLengthWrite, - validatePath, - validateUint32 + validatePath } = internalFS; const { CHAR_FORWARD_SLASH, CHAR_BACKWARD_SLASH, } = require('internal/constants'); +const { + isUint32, + validateInt32, + validateUint32 +} = require('internal/validators'); // Lazy loaded let promises; @@ -787,8 +789,8 @@ fs.ftruncate = function(fd, len = 0, callback) { // 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 `validateLen`. - validateLen(len); + // This applies to all usage of `validateInt32(len, 'len')`. + validateInt32(len, 'len'); len = Math.max(0, len); const req = new FSReqWrap(); req.oncomplete = makeCallback(callback); @@ -797,7 +799,7 @@ fs.ftruncate = function(fd, len = 0, callback) { fs.ftruncateSync = function(fd, len = 0) { validateUint32(fd, 'fd'); - validateLen(len); + validateInt32(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 97ac4c6c495b3d..4c0a256f5ad66c 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -21,7 +21,6 @@ const { copyObject, getOptions, getStatsFromBinding, - isUint32, modeNum, nullCheck, preprocessSymlinkDestination, @@ -29,12 +28,15 @@ const { stringToSymlinkType, toUnixTimestamp, validateBuffer, - validateLen, validateOffsetLengthRead, validateOffsetLengthWrite, - validatePath, - validateUint32 + validatePath } = require('internal/fs/utils'); +const { + isUint32, + validateInt32, + validateUint32 +} = require('internal/validators'); const pathModule = require('path'); const kHandle = Symbol('handle'); @@ -263,7 +265,7 @@ async function truncate(path, len = 0) { async function ftruncate(handle, len = 0) { validateFileHandle(handle); - validateLen(len); + validateInt32(len, 'len'); len = Math.max(0, len); return binding.ftruncate(handle.fd, len, kUsePromises); } diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index 0cfb89a9d3d084..2f7a8d8ced176e 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -70,9 +70,6 @@ function getOptions(options, defaultOptions) { return options; } -function isInt32(n) { return n === (n | 0); } -function isUint32(n) { return n === (n >>> 0); } - function modeNum(m, def) { if (typeof m === 'number') return m; @@ -341,26 +338,6 @@ function validateBuffer(buffer) { } } -function validateLen(len) { - let err; - - if (!isInt32(len)) { - if (typeof len !== 'number') { - err = new ERR_INVALID_ARG_TYPE('len', 'number', len); - } else if (!Number.isInteger(len)) { - err = new ERR_OUT_OF_RANGE('len', 'an integer', len); - } else { - // 2 ** 31 === 2147483648 - err = new ERR_OUT_OF_RANGE('len', '> -2147483649 && < 2147483648', len); - } - } - - if (err !== undefined) { - Error.captureStackTrace(err, validateLen); - throw err; - } -} - function validateOffsetLengthRead(offset, length, bufferLength) { let err; @@ -410,28 +387,10 @@ function validatePath(path, propName = 'path') { } } -function validateUint32(value, propName) { - if (!isUint32(value)) { - let err; - if (typeof value !== 'number') { - err = new ERR_INVALID_ARG_TYPE(propName, 'number', value); - } else if (!Number.isInteger(value)) { - err = new ERR_OUT_OF_RANGE(propName, 'an integer', value); - } else { - // 2 ** 32 === 4294967296 - err = new ERR_OUT_OF_RANGE(propName, '>= 0 && < 4294967296', value); - } - Error.captureStackTrace(err, validateUint32); - throw err; - } -} - module.exports = { assertEncoding, copyObject, getOptions, - isInt32, - isUint32, modeNum, nullCheck, preprocessSymlinkDestination, @@ -443,9 +402,7 @@ module.exports = { SyncWriteStream, toUnixTimestamp, validateBuffer, - validateLen, validateOffsetLengthRead, validateOffsetLengthWrite, - validatePath, - validateUint32 + validatePath }; diff --git a/lib/internal/validators.js b/lib/internal/validators.js new file mode 100644 index 00000000000000..556bfb2dc08f5f --- /dev/null +++ b/lib/internal/validators.js @@ -0,0 +1,58 @@ +'use strict'; + +const { + ERR_INVALID_ARG_TYPE, + ERR_OUT_OF_RANGE +} = require('internal/errors').codes; + +function isInt32(value) { + return value === (value | 0); +} + +function isUint32(value) { + return value === (value >>> 0); +} + +function validateInt32(value, name) { + if (!isInt32(value)) { + let err; + if (typeof value !== 'number') { + err = new ERR_INVALID_ARG_TYPE(name, 'number', value); + } else if (!Number.isInteger(value)) { + err = new ERR_OUT_OF_RANGE(name, 'an integer', value); + } else { + // 2 ** 31 === 2147483648 + err = new ERR_OUT_OF_RANGE(name, '> -2147483649 && < 2147483648', value); + } + Error.captureStackTrace(err, validateInt32); + throw err; + } +} + +function validateUint32(value, name, positive) { + if (!isUint32(value)) { + let err; + if (typeof value !== 'number') { + err = new ERR_INVALID_ARG_TYPE(name, 'number', value); + } else if (!Number.isInteger(value)) { + err = new ERR_OUT_OF_RANGE(name, 'an integer', value); + } else { + const min = positive ? 1 : 0; + // 2 ** 32 === 4294967296 + err = new ERR_OUT_OF_RANGE(name, `>= ${min} && < 4294967296`, value); + } + Error.captureStackTrace(err, validateUint32); + throw err; + } else if (positive && value === 0) { + const err = new ERR_OUT_OF_RANGE(name, '>= 1 && < 4294967296', value); + Error.captureStackTrace(err, validateUint32); + throw err; + } +} + +module.exports = { + isInt32, + isUint32, + validateInt32, + validateUint32 +}; diff --git a/node.gyp b/node.gyp index 10b818e683f1fc..19367d9bd9517d 100644 --- a/node.gyp +++ b/node.gyp @@ -147,6 +147,7 @@ 'lib/internal/http2/util.js', 'lib/internal/v8_prof_polyfill.js', 'lib/internal/v8_prof_processor.js', + 'lib/internal/validators.js', 'lib/internal/stream_base_commons.js', 'lib/internal/vm/module.js', 'lib/internal/streams/lazy_transform.js',