diff options
author | James M Snell <jasnell@gmail.com> | 2017-12-13 14:24:34 -0800 |
---|---|---|
committer | James M Snell <jasnell@gmail.com> | 2017-12-22 12:49:10 -0800 |
commit | 6100e12667429acad1827b6d918e512e55a7a6a7 (patch) | |
tree | 4fac815add3abf5d54112723798ecc78cb3e06fa /lib | |
parent | 92fc14a4595d460394cad8ad5a091dcc450068a5 (diff) | |
download | android-node-v8-6100e12667429acad1827b6d918e512e55a7a6a7.tar.gz android-node-v8-6100e12667429acad1827b6d918e512e55a7a6a7.tar.bz2 android-node-v8-6100e12667429acad1827b6d918e512e55a7a6a7.zip |
fs: move type checking to js
PR-URL: https://github.com/nodejs/node/pull/17667
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/fs.js | 463 | ||||
-rw-r--r-- | lib/internal/errors.js | 2 |
2 files changed, 321 insertions, 144 deletions
@@ -63,6 +63,9 @@ const errnoException = util._errnoException; let truncateWarn = true; +function isInt32(n) { return n === (n | 0); } +function isUint32(n) { return n === (n >>> 0); } + function showTruncateDeprecation() { if (truncateWarn) { process.emitWarning( @@ -636,10 +639,8 @@ fs.readFileSync = function(path, options) { }; fs.close = function(fd, callback) { - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); const req = new FSReqWrap(); req.oncomplete = makeCallback(callback); @@ -647,10 +648,8 @@ fs.close = function(fd, callback) { }; fs.closeSync = function(fd) { - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); return binding.close(fd); }; @@ -673,7 +672,15 @@ fs.open = function(path, flags, mode, callback_) { return; if (!nullCheck(path, callback)) return; - var req = new FSReqWrap(); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + + if (!isUint32(mode)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'integer'); + + const req = new FSReqWrap(); req.oncomplete = callback; binding.open(pathModule.toNamespacedPath(path), @@ -686,15 +693,21 @@ fs.openSync = function(path, flags, mode) { mode = modeNum(mode, 0o666); handleError((path = getPathFromURL(path))); nullCheck(path); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + + if (!isUint32(mode)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'integer'); + return binding.open(pathModule.toNamespacedPath(path), stringToFlags(flags), mode); }; fs.read = function(fd, buffer, offset, length, position, callback) { - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); if (!isUint8Array(buffer)) throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'buffer', ['Buffer', 'Uint8Array']); @@ -714,7 +727,7 @@ fs.read = function(fd, buffer, offset, length, position, callback) { if (length < 0 || offset + length > buffer.length) throw new errors.RangeError('ERR_OUT_OF_RANGE', 'length'); - if (!Number.isInteger(position)) + if (!isUint32(position)) position = -1; function wrapper(err, bytesRead) { @@ -732,10 +745,8 @@ Object.defineProperty(fs.read, internalUtil.customPromisifyArgs, { value: ['bytesRead', 'buffer'], enumerable: false }); fs.readSync = function(fd, buffer, offset, length, position) { - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); if (!isUint8Array(buffer)) throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'buffer', ['Buffer', 'Uint8Array']); @@ -753,7 +764,7 @@ fs.readSync = function(fd, buffer, offset, length, position) { if (length < 0 || offset + length > buffer.length) throw new errors.RangeError('ERR_OUT_OF_RANGE', 'length'); - if (!Number.isInteger(position)) + if (!isUint32(position)) position = -1; return binding.read(fd, buffer, offset, length, position); @@ -769,20 +780,25 @@ fs.write = function(fd, buffer, offset, length, position, callback) { callback(err, written || 0, buffer); } - var req = new FSReqWrap(); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); + + const req = new FSReqWrap(); req.oncomplete = wrapper; if (isUint8Array(buffer)) { callback = maybeCallback(callback || position || length || offset); - if (typeof offset !== 'number') { + if (typeof offset !== 'number') offset = 0; - } - if (typeof length !== 'number') { + if (typeof length !== 'number') length = buffer.length - offset; - } - if (typeof position !== 'number') { + if (typeof position !== 'number') position = null; - } + const byteLength = buffer.byteLength; + if (offset > byteLength) + throw new errors.RangeError('ERR_OUT_OF_RANGE', 'offset'); + if (offset + length > byteLength || offset + length > kMaxLength) + throw new errors.RangeError('ERR_OUT_OF_RANGE', 'length'); return binding.writeBuffer(fd, buffer, offset, length, position, req); } @@ -809,6 +825,8 @@ Object.defineProperty(fs.write, internalUtil.customPromisifyArgs, // OR // fs.writeSync(fd, string[, position[, encoding]]); fs.writeSync = function(fd, buffer, offset, length, position) { + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); if (isUint8Array(buffer)) { if (position === undefined) position = null; @@ -816,6 +834,11 @@ fs.writeSync = function(fd, buffer, offset, length, position) { offset = 0; if (typeof length !== 'number') length = buffer.length - offset; + const byteLength = buffer.byteLength; + if (offset > byteLength) + throw new errors.RangeError('ERR_OUT_OF_RANGE', 'offset'); + if (offset + length > byteLength || offset + length > kMaxLength) + throw new errors.RangeError('ERR_OUT_OF_RANGE', 'length'); return binding.writeBuffer(fd, buffer, offset, length, position); } if (typeof buffer !== 'string') @@ -835,7 +858,16 @@ fs.rename = function(oldPath, newPath, callback) { if (!nullCheck(oldPath, callback)) return; if (!nullCheck(newPath, callback)) return; - var req = new FSReqWrap(); + + if (typeof oldPath !== 'string' && !isUint8Array(oldPath)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'oldPath', + ['string', 'Buffer', 'URL']); + } + if (typeof newPath !== 'string' && !isUint8Array(newPath)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'newPath', + ['string', 'Buffer', 'URL']); + } + const req = new FSReqWrap(); req.oncomplete = callback; binding.rename(pathModule.toNamespacedPath(oldPath), pathModule.toNamespacedPath(newPath), @@ -847,6 +879,14 @@ fs.renameSync = function(oldPath, newPath) { handleError((newPath = getPathFromURL(newPath))); nullCheck(oldPath); nullCheck(newPath); + if (typeof oldPath !== 'string' && !isUint8Array(oldPath)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'oldPath', + ['string', 'Buffer', 'URL']); + } + if (typeof newPath !== 'string' && !isUint8Array(newPath)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'newPath', + ['string', 'Buffer', 'URL']); + } return binding.rename(pathModule.toNamespacedPath(oldPath), pathModule.toNamespacedPath(newPath)); }; @@ -897,35 +937,26 @@ fs.truncateSync = function(path, len) { return ret; }; -fs.ftruncate = function(fd, len, callback) { +fs.ftruncate = function(fd, len = 0, callback) { if (typeof len === 'function') { callback = len; len = 0; - } else if (len === undefined) { - len = 0; } - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); - if (!Number.isInteger(len)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'len', 'number'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); + if (!isInt32(len)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'len', 'integer'); len = Math.max(0, len); const req = new FSReqWrap(); req.oncomplete = makeCallback(callback); binding.ftruncate(fd, len, req); }; -fs.ftruncateSync = function(fd, len) { - if (len === undefined) { - len = 0; - } - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); - if (!Number.isInteger(len)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'len', 'number'); +fs.ftruncateSync = function(fd, len = 0) { + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); + if (!isInt32(len)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'len', 'integer'); len = Math.max(0, len); return binding.ftruncate(fd, len); }; @@ -935,7 +966,11 @@ fs.rmdir = function(path, callback) { if (handleError((path = getPathFromURL(path)), callback)) return; if (!nullCheck(path, callback)) return; - var req = new FSReqWrap(); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + const req = new FSReqWrap(); req.oncomplete = callback; binding.rmdir(pathModule.toNamespacedPath(path), req); }; @@ -943,42 +978,38 @@ fs.rmdir = function(path, callback) { fs.rmdirSync = function(path) { handleError((path = getPathFromURL(path))); nullCheck(path); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } return binding.rmdir(pathModule.toNamespacedPath(path)); }; fs.fdatasync = function(fd, callback) { - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); const req = new FSReqWrap(); req.oncomplete = makeCallback(callback); binding.fdatasync(fd, req); }; fs.fdatasyncSync = function(fd) { - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); return binding.fdatasync(fd); }; fs.fsync = function(fd, callback) { - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); const req = new FSReqWrap(); req.oncomplete = makeCallback(callback); binding.fsync(fd, req); }; fs.fsyncSync = function(fd) { - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); return binding.fsync(fd); }; @@ -988,18 +1019,31 @@ fs.mkdir = function(path, mode, callback) { if (handleError((path = getPathFromURL(path)), callback)) return; if (!nullCheck(path, callback)) return; - var req = new FSReqWrap(); + + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + mode = modeNum(mode, 0o777); + if (!isUint32(mode)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'integer'); + + const req = new FSReqWrap(); req.oncomplete = callback; - binding.mkdir(pathModule.toNamespacedPath(path), - modeNum(mode, 0o777), - req); + binding.mkdir(pathModule.toNamespacedPath(path), mode, req); }; fs.mkdirSync = function(path, mode) { handleError((path = getPathFromURL(path))); nullCheck(path); - return binding.mkdir(pathModule.toNamespacedPath(path), - modeNum(mode, 0o777)); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + mode = modeNum(mode, 0o777); + if (!isUint32(mode)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'integer'); + return binding.mkdir(pathModule.toNamespacedPath(path), mode); }; fs.readdir = function(path, options, callback) { @@ -1008,7 +1052,13 @@ fs.readdir = function(path, options, callback) { if (handleError((path = getPathFromURL(path)), callback)) return; if (!nullCheck(path, callback)) return; - var req = new FSReqWrap(); + + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + + const req = new FSReqWrap(); req.oncomplete = callback; binding.readdir(pathModule.toNamespacedPath(path), options.encoding, req); }; @@ -1017,14 +1067,16 @@ fs.readdirSync = function(path, options) { options = getOptions(options, {}); handleError((path = getPathFromURL(path))); nullCheck(path); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } return binding.readdir(pathModule.toNamespacedPath(path), options.encoding); }; fs.fstat = function(fd, callback) { - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); const req = new FSReqWrap(); req.oncomplete = makeStatsCallback(callback); binding.fstat(fd, req); @@ -1035,7 +1087,11 @@ fs.lstat = function(path, callback) { if (handleError((path = getPathFromURL(path)), callback)) return; if (!nullCheck(path, callback)) return; - var req = new FSReqWrap(); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + const req = new FSReqWrap(); req.oncomplete = callback; binding.lstat(pathModule.toNamespacedPath(path), req); }; @@ -1045,16 +1101,18 @@ fs.stat = function(path, callback) { if (handleError((path = getPathFromURL(path)), callback)) return; if (!nullCheck(path, callback)) return; - var req = new FSReqWrap(); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + const req = new FSReqWrap(); req.oncomplete = callback; binding.stat(pathModule.toNamespacedPath(path), req); }; fs.fstatSync = function(fd) { - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); binding.fstat(fd); return statsFromValues(); }; @@ -1062,6 +1120,10 @@ fs.fstatSync = function(fd) { fs.lstatSync = function(path) { handleError((path = getPathFromURL(path))); nullCheck(path); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } binding.lstat(pathModule.toNamespacedPath(path)); return statsFromValues(); }; @@ -1069,6 +1131,10 @@ fs.lstatSync = function(path) { fs.statSync = function(path) { handleError((path = getPathFromURL(path))); nullCheck(path); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } binding.stat(pathModule.toNamespacedPath(path)); return statsFromValues(); }; @@ -1079,7 +1145,11 @@ fs.readlink = function(path, options, callback) { if (handleError((path = getPathFromURL(path)), callback)) return; if (!nullCheck(path, callback)) return; - var req = new FSReqWrap(); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'oldPath', + ['string', 'Buffer', 'URL']); + } + const req = new FSReqWrap(); req.oncomplete = callback; binding.readlink(pathModule.toNamespacedPath(path), options.encoding, req); }; @@ -1088,6 +1158,10 @@ fs.readlinkSync = function(path, options) { options = getOptions(options, {}); handleError((path = getPathFromURL(path))); nullCheck(path); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'oldPath', + ['string', 'Buffer', 'URL']); + } return binding.readlink(pathModule.toNamespacedPath(path), options.encoding); }; @@ -1106,6 +1180,27 @@ function preprocessSymlinkDestination(path, type, linkPath) { } } +function stringToSymlinkType(type) { + let flags = 0; + if (typeof type === 'string') { + switch (type) { + case 'dir': + flags |= constants.UV_FS_SYMLINK_DIR; + break; + case 'junction': + flags |= constants.UV_FS_SYMLINK_JUNCTION; + break; + case 'file': + break; + default: + const err = new errors.Error('ERR_FS_INVALID_SYMLINK_TYPE', type); + Error.captureStackTrace(err, stringToSymlinkType); + throw err; + } + } + return flags; +} + fs.symlink = function(target, path, type_, callback_) { var type = (typeof type_ === 'string' ? type_ : null); var callback = makeCallback(arguments[arguments.length - 1]); @@ -1119,13 +1214,20 @@ fs.symlink = function(target, path, type_, callback_) { if (!nullCheck(target, callback)) return; if (!nullCheck(path, callback)) return; - var req = new FSReqWrap(); - req.oncomplete = callback; + if (typeof target !== 'string' && !isUint8Array(target)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'target', + ['string', 'Buffer', 'URL']); + } + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + const flags = stringToSymlinkType(type); + const req = new FSReqWrap(); + req.oncomplete = callback; binding.symlink(preprocessSymlinkDestination(target, type, path), - pathModule.toNamespacedPath(path), - type, - req); + pathModule.toNamespacedPath(path), flags, req); }; fs.symlinkSync = function(target, path, type) { @@ -1135,9 +1237,17 @@ fs.symlinkSync = function(target, path, type) { nullCheck(target); nullCheck(path); + if (typeof target !== 'string' && !isUint8Array(target)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'target', + ['string', 'Buffer', 'URL']); + } + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + const flags = stringToSymlinkType(type); return binding.symlink(preprocessSymlinkDestination(target, type, path), - pathModule.toNamespacedPath(path), - type); + pathModule.toNamespacedPath(path), flags); }; fs.link = function(existingPath, newPath, callback) { @@ -1152,7 +1262,16 @@ fs.link = function(existingPath, newPath, callback) { if (!nullCheck(existingPath, callback)) return; if (!nullCheck(newPath, callback)) return; - var req = new FSReqWrap(); + if (typeof existingPath !== 'string' && !isUint8Array(existingPath)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'existingPath', + ['string', 'Buffer', 'URL']); + } + if (typeof newPath !== 'string' && !isUint8Array(newPath)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'newPath', + ['string', 'Buffer', 'URL']); + } + + const req = new FSReqWrap(); req.oncomplete = callback; binding.link(pathModule.toNamespacedPath(existingPath), @@ -1165,6 +1284,14 @@ fs.linkSync = function(existingPath, newPath) { handleError((newPath = getPathFromURL(newPath))); nullCheck(existingPath); nullCheck(newPath); + if (typeof existingPath !== 'string' && !isUint8Array(existingPath)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'existingPath', + ['string', 'Buffer', 'URL']); + } + if (typeof newPath !== 'string' && !isUint8Array(newPath)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'newPath', + ['string', 'Buffer', 'URL']); + } return binding.link(pathModule.toNamespacedPath(existingPath), pathModule.toNamespacedPath(newPath)); }; @@ -1174,7 +1301,11 @@ fs.unlink = function(path, callback) { if (handleError((path = getPathFromURL(path)), callback)) return; if (!nullCheck(path, callback)) return; - var req = new FSReqWrap(); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + const req = new FSReqWrap(); req.oncomplete = callback; binding.unlink(pathModule.toNamespacedPath(path), req); }; @@ -1182,17 +1313,19 @@ fs.unlink = function(path, callback) { fs.unlinkSync = function(path) { handleError((path = getPathFromURL(path))); nullCheck(path); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } return binding.unlink(pathModule.toNamespacedPath(path)); }; fs.fchmod = function(fd, mode, callback) { mode = modeNum(mode); - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); - if (!Number.isInteger(mode)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'number'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); + if (!isUint32(mode)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'integer'); if (mode < 0 || mode > 0o777) throw new errors.RangeError('ERR_OUT_OF_RANGE', 'mode'); @@ -1203,12 +1336,10 @@ fs.fchmod = function(fd, mode, callback) { fs.fchmodSync = function(fd, mode) { mode = modeNum(mode); - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); - if (!Number.isInteger(mode)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'number'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); + if (!isUint32(mode)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'integer'); if (mode < 0 || mode > 0o777) throw new errors.RangeError('ERR_OUT_OF_RANGE', 'mode'); return binding.fchmod(fd, mode); @@ -1257,17 +1388,31 @@ fs.chmod = function(path, mode, callback) { if (handleError((path = getPathFromURL(path)), callback)) return; if (!nullCheck(path, callback)) return; - var req = new FSReqWrap(); + + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + mode = modeNum(mode); + if (!isUint32(mode)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'integer'); + + const req = new FSReqWrap(); req.oncomplete = callback; - binding.chmod(pathModule.toNamespacedPath(path), - modeNum(mode), - req); + binding.chmod(pathModule.toNamespacedPath(path), mode, req); }; fs.chmodSync = function(path, mode) { handleError((path = getPathFromURL(path))); nullCheck(path); - return binding.chmod(pathModule.toNamespacedPath(path), modeNum(mode)); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + mode = modeNum(mode); + if (!isUint32(mode)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'integer'); + return binding.chmod(pathModule.toNamespacedPath(path), mode); }; if (constants.O_SYMLINK !== undefined) { @@ -1289,18 +1434,12 @@ if (constants.O_SYMLINK !== undefined) { } fs.fchown = function(fd, uid, gid, callback) { - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); - if (!Number.isInteger(uid)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'uid', 'number'); - if (uid < 0) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'uid'); - if (!Number.isInteger(gid)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'gid', 'number'); - if (gid < 0) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'gid'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); + if (!isUint32(uid)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'uid', 'integer'); + if (!isUint32(gid)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'gid', 'integer'); const req = new FSReqWrap(); req.oncomplete = makeCallback(callback); @@ -1308,18 +1447,12 @@ fs.fchown = function(fd, uid, gid, callback) { }; fs.fchownSync = function(fd, uid, gid) { - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); - if (!Number.isInteger(uid)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'uid', 'number'); - if (uid < 0) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'uid'); - if (!Number.isInteger(gid)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'gid', 'number'); - if (gid < 0) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'gid'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); + if (!isUint32(uid)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'uid', 'integer'); + if (!isUint32(gid)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'gid', 'integer'); return binding.fchown(fd, uid, gid); }; @@ -1329,7 +1462,17 @@ fs.chown = function(path, uid, gid, callback) { if (handleError((path = getPathFromURL(path)), callback)) return; if (!nullCheck(path, callback)) return; - var req = new FSReqWrap(); + + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + if (!isUint32(uid)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'uid', 'integer'); + if (!isUint32(gid)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'gid', 'integer'); + + const req = new FSReqWrap(); req.oncomplete = callback; binding.chown(pathModule.toNamespacedPath(path), uid, gid, req); }; @@ -1337,6 +1480,14 @@ fs.chown = function(path, uid, gid, callback) { fs.chownSync = function(path, uid, gid) { handleError((path = getPathFromURL(path))); nullCheck(path); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + if (!isUint32(uid)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'uid', 'integer'); + if (!isUint32(gid)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'gid', 'integer'); return binding.chown(pathModule.toNamespacedPath(path), uid, gid); }; @@ -1370,7 +1521,13 @@ fs.utimes = function(path, atime, mtime, callback) { if (handleError((path = getPathFromURL(path)), callback)) return; if (!nullCheck(path, callback)) return; - var req = new FSReqWrap(); + + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + + const req = new FSReqWrap(); req.oncomplete = callback; binding.utimes(pathModule.toNamespacedPath(path), toUnixTimestamp(atime), @@ -1381,16 +1538,18 @@ fs.utimes = function(path, atime, mtime, callback) { fs.utimesSync = function(path, atime, mtime) { handleError((path = getPathFromURL(path))); nullCheck(path); - atime = toUnixTimestamp(atime); - mtime = toUnixTimestamp(mtime); - binding.utimes(pathModule.toNamespacedPath(path), atime, mtime); + if (typeof path !== 'string' && !isUint8Array(path)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', + ['string', 'Buffer', 'URL']); + } + binding.utimes(pathModule.toNamespacedPath(path), + toUnixTimestamp(atime), + toUnixTimestamp(mtime)); }; fs.futimes = function(fd, atime, mtime, callback) { - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); atime = toUnixTimestamp(atime, 'atime'); mtime = toUnixTimestamp(mtime, 'mtime'); const req = new FSReqWrap(); @@ -1399,10 +1558,8 @@ fs.futimes = function(fd, atime, mtime, callback) { }; fs.futimesSync = function(fd, atime, mtime) { - if (!Number.isInteger(fd)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number'); - if (fd < 0 || fd > 0xFFFFFFFF) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd'); + if (!isUint32(fd)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'integer'); atime = toUnixTimestamp(atime, 'atime'); mtime = toUnixTimestamp(mtime, 'mtime'); binding.futimes(fd, atime, mtime); @@ -2098,6 +2255,15 @@ fs.copyFile = function(src, dest, flags, callback) { if (!nullCheck(dest, callback)) return; + if (typeof src !== 'string' && !isUint8Array(src)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'src', + ['string', 'Buffer', 'URL']); + } + if (typeof dest !== 'string' && !isUint8Array(dest)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'dest', + ['string', 'Buffer', 'URL']); + } + src = pathModule._makeLong(src); dest = pathModule._makeLong(dest); flags = flags | 0; @@ -2116,6 +2282,15 @@ fs.copyFileSync = function(src, dest, flags) { handleError(dest); nullCheck(dest); + if (typeof src !== 'string' && !isUint8Array(src)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'src', + ['string', 'Buffer', 'URL']); + } + if (typeof dest !== 'string' && !isUint8Array(dest)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'dest', + ['string', 'Buffer', 'URL']); + } + src = pathModule._makeLong(src); dest = pathModule._makeLong(dest); flags = flags | 0; diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 5b18a7026e..779343e066 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -307,6 +307,8 @@ E('ERR_ENCODING_INVALID_ENCODED_DATA', 'The encoded data was not valid for encoding %s'); E('ERR_ENCODING_NOT_SUPPORTED', 'The "%s" encoding is not supported'); E('ERR_FALSY_VALUE_REJECTION', 'Promise was rejected with falsy value'); +E('ERR_FS_INVALID_SYMLINK_TYPE', + 'Symlink type must be one of "dir", "file", or "junction". Received "%s"'); E('ERR_HTTP2_ALREADY_SHUTDOWN', 'Http2Session is already shutdown or destroyed'); E('ERR_HTTP2_CONNECT_AUTHORITY', |