diff --git a/doc/api/errors.md b/doc/api/errors.md index 4f7e2651c93471..c5e851644268dd 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -783,6 +783,12 @@ Encoding provided to `util.TextDecoder()` API was not one of the A `Promise` that was callbackified via `util.callbackify()` was rejected with a falsy value. + +### ERR_FS_INVALID_SYMLINK_TYPE + +An invalid symlink type was passed to the [`fs.symlink()`][] or +[`fs.symlinkSync()`][] methods. + ### ERR_HTTP_HEADERS_SENT @@ -1609,6 +1615,8 @@ Creation of a [`zlib`][] object failed due to incorrect configuration. [`dgram.createSocket()`]: dgram.html#dgram_dgram_createsocket_options_callback [`ERR_INVALID_ARG_TYPE`]: #ERR_INVALID_ARG_TYPE [`EventEmitter`]: events.html#events_class_eventemitter +[`fs.symlink()`]: fs.html#fs_symlink +[`fs.symlinkSync()`]: fs.html#fs_symlinksync [`hash.digest()`]: crypto.html#crypto_hash_digest_encoding [`hash.update()`]: crypto.html#crypto_hash_update_data_inputencoding [`readable._read()`]: stream.html#stream_readable_read_size_1 diff --git a/lib/fs.js b/lib/fs.js index 9554620a040a3a..fe657c3c24f67d 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -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 5b18a7026e0396..779343e0664e8b 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', diff --git a/src/node_constants.cc b/src/node_constants.cc index d478d434000fca..9ecffead538153 100644 --- a/src/node_constants.cc +++ b/src/node_constants.cc @@ -1028,6 +1028,8 @@ void DefineOpenSSLConstants(Local target) { } void DefineSystemConstants(Local target) { + NODE_DEFINE_CONSTANT(target, UV_FS_SYMLINK_DIR); + NODE_DEFINE_CONSTANT(target, UV_FS_SYMLINK_JUNCTION); // file access modes NODE_DEFINE_CONSTANT(target, O_RDONLY); NODE_DEFINE_CONSTANT(target, O_WRONLY); diff --git a/src/node_file.cc b/src/node_file.cc index e7ad4900c43797..272e0906447357 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -95,14 +95,12 @@ using v8::Object; using v8::String; using v8::Value; -#define TYPE_ERROR(msg) env->ThrowTypeError(msg) +#ifndef MIN +# define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif #define GET_OFFSET(a) ((a)->IsNumber() ? (a)->IntegerValue() : -1) -#define ASSERT_PATH(path) \ - if (*path == nullptr) \ - return TYPE_ERROR( #path " must be a string or Buffer"); - FSReqWrap* FSReqWrap::New(Environment* env, Local req, const char* syscall, @@ -521,11 +519,10 @@ static void InternalModuleStat(const FunctionCallbackInfo& args) { static void Stat(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - if (args.Length() < 1) - return TYPE_ERROR("path required"); + CHECK_GE(args.Length(), 1); BufferValue path(env->isolate(), args[0]); - ASSERT_PATH(path) + CHECK_NE(*path, nullptr); if (args[1]->IsObject()) { ASYNC_CALL(AfterStat, stat, args[1], UTF8, *path) @@ -539,11 +536,10 @@ static void Stat(const FunctionCallbackInfo& args) { static void LStat(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - if (args.Length() < 1) - return TYPE_ERROR("path required"); + CHECK_GE(args.Length(), 1); BufferValue path(env->isolate(), args[0]); - ASSERT_PATH(path) + CHECK_NE(*path, nullptr); if (args[1]->IsObject()) { ASYNC_CALL(AfterStat, lstat, args[1], UTF8, *path) @@ -573,29 +569,15 @@ static void FStat(const FunctionCallbackInfo& args) { static void Symlink(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - int len = args.Length(); - if (len < 1) - return TYPE_ERROR("target path required"); - if (len < 2) - return TYPE_ERROR("src path required"); + CHECK_GE(args.Length(), 3); BufferValue target(env->isolate(), args[0]); - ASSERT_PATH(target) + CHECK_NE(*target, nullptr); BufferValue path(env->isolate(), args[1]); - ASSERT_PATH(path) - - int flags = 0; - - if (args[2]->IsString()) { - node::Utf8Value mode(env->isolate(), args[2]); - if (strcmp(*mode, "dir") == 0) { - flags |= UV_FS_SYMLINK_DIR; - } else if (strcmp(*mode, "junction") == 0) { - flags |= UV_FS_SYMLINK_JUNCTION; - } else if (strcmp(*mode, "file") != 0) { - return env->ThrowError("Unknown symlink type"); - } - } + CHECK_NE(*path, nullptr); + + CHECK(args[2]->IsUint32()); + int flags = args[2]->Uint32Value(env->context()).ToChecked(); if (args[3]->IsObject()) { ASYNC_DEST_CALL(AfterNoArgs, symlink, args[3], *path, @@ -608,17 +590,13 @@ static void Symlink(const FunctionCallbackInfo& args) { static void Link(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - int len = args.Length(); - if (len < 1) - return TYPE_ERROR("src path required"); - if (len < 2) - return TYPE_ERROR("dest path required"); + CHECK_GE(args.Length(), 2); BufferValue src(env->isolate(), args[0]); - ASSERT_PATH(src) + CHECK_NE(*src, nullptr); BufferValue dest(env->isolate(), args[1]); - ASSERT_PATH(dest) + CHECK_NE(*dest, nullptr); if (args[2]->IsObject()) { ASYNC_DEST_CALL(AfterNoArgs, link, args[2], *dest, UTF8, *src, *dest) @@ -632,11 +610,10 @@ static void ReadLink(const FunctionCallbackInfo& args) { const int argc = args.Length(); - if (argc < 1) - return TYPE_ERROR("path required"); + CHECK_GE(argc, 1); BufferValue path(env->isolate(), args[0]); - ASSERT_PATH(path) + CHECK_NE(*path, nullptr); const enum encoding encoding = ParseEncoding(env->isolate(), args[1], UTF8); @@ -666,16 +643,12 @@ static void ReadLink(const FunctionCallbackInfo& args) { static void Rename(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - int len = args.Length(); - if (len < 1) - return TYPE_ERROR("old path required"); - if (len < 2) - return TYPE_ERROR("new path required"); + CHECK_GE(args.Length(), 2); BufferValue old_path(env->isolate(), args[0]); - ASSERT_PATH(old_path) + CHECK_NE(*old_path, nullptr); BufferValue new_path(env->isolate(), args[1]); - ASSERT_PATH(new_path) + CHECK_NE(*new_path, nullptr); if (args[2]->IsObject()) { ASYNC_DEST_CALL(AfterNoArgs, rename, args[2], *new_path, @@ -732,11 +705,10 @@ static void Fsync(const FunctionCallbackInfo& args) { static void Unlink(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - if (args.Length() < 1) - return TYPE_ERROR("path required"); + CHECK_GE(args.Length(), 1); BufferValue path(env->isolate(), args[0]); - ASSERT_PATH(path) + CHECK_NE(*path, nullptr); if (args[1]->IsObject()) { ASYNC_CALL(AfterNoArgs, unlink, args[1], UTF8, *path) @@ -748,11 +720,10 @@ static void Unlink(const FunctionCallbackInfo& args) { static void RMDir(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - if (args.Length() < 1) - return TYPE_ERROR("path required"); + CHECK_GE(args.Length(), 1); BufferValue path(env->isolate(), args[0]); - ASSERT_PATH(path) + CHECK_NE(*path, nullptr); if (args[1]->IsObject()) { ASYNC_CALL(AfterNoArgs, rmdir, args[1], UTF8, *path) @@ -764,13 +735,11 @@ static void RMDir(const FunctionCallbackInfo& args) { static void MKDir(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - if (args.Length() < 2) - return TYPE_ERROR("path and mode are required"); - if (!args[1]->IsInt32()) - return TYPE_ERROR("mode must be an integer"); + CHECK_GE(args.Length(), 2); + CHECK(args[1]->IsInt32()); BufferValue path(env->isolate(), args[0]); - ASSERT_PATH(path) + CHECK_NE(*path, nullptr); int mode = static_cast(args[1]->Int32Value()); @@ -785,7 +754,7 @@ static void RealPath(const FunctionCallbackInfo& args) { CHECK_GE(args.Length(), 2); Environment* env = Environment::GetCurrent(args); BufferValue path(env->isolate(), args[0]); - ASSERT_PATH(path) + CHECK_NE(*path, nullptr); const enum encoding encoding = ParseEncoding(env->isolate(), args[1], UTF8); @@ -813,11 +782,10 @@ static void ReadDir(const FunctionCallbackInfo& args) { const int argc = args.Length(); - if (argc < 1) - return TYPE_ERROR("path required"); + CHECK_GE(args.Length(), 1); BufferValue path(env->isolate(), args[0]); - ASSERT_PATH(path) + CHECK_NE(*path, nullptr); const enum encoding encoding = ParseEncoding(env->isolate(), args[1], UTF8); @@ -876,20 +844,12 @@ static void ReadDir(const FunctionCallbackInfo& args) { static void Open(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - int len = args.Length(); - if (len < 1) - return TYPE_ERROR("path required"); - if (len < 2) - return TYPE_ERROR("flags required"); - if (len < 3) - return TYPE_ERROR("mode required"); - if (!args[1]->IsInt32()) - return TYPE_ERROR("flags must be an int"); - if (!args[2]->IsInt32()) - return TYPE_ERROR("mode must be an int"); + CHECK_GE(args.Length(), 3); + CHECK(args[1]->IsInt32()); + CHECK(args[2]->IsInt32()); BufferValue path(env->isolate(), args[0]); - ASSERT_PATH(path) + CHECK_NE(*path, nullptr); int flags = args[1]->Int32Value(); int mode = static_cast(args[2]->Int32Value()); @@ -906,17 +866,13 @@ static void Open(const FunctionCallbackInfo& args) { static void CopyFile(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - if (!args[0]->IsString()) - return TYPE_ERROR("src must be a string"); - if (!args[1]->IsString()) - return TYPE_ERROR("dest must be a string"); - if (!args[2]->IsInt32()) - return TYPE_ERROR("flags must be an int"); + CHECK_GE(args.Length(), 3); + CHECK(args[2]->IsInt32()); BufferValue src(env->isolate(), args[0]); - ASSERT_PATH(src) + CHECK_NE(*src, nullptr); BufferValue dest(env->isolate(), args[1]); - ASSERT_PATH(dest) + CHECK_NE(*dest, nullptr); int flags = args[2]->Int32Value(); if (args[3]->IsObject()) { @@ -940,9 +896,7 @@ static void CopyFile(const FunctionCallbackInfo& args) { static void WriteBuffer(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - if (!args[0]->IsInt32()) - return env->ThrowTypeError("First argument must be file descriptor"); - + CHECK(args[0]->IsInt32()); CHECK(Buffer::HasInstance(args[1])); int fd = args[0]->Int32Value(); @@ -954,14 +908,10 @@ static void WriteBuffer(const FunctionCallbackInfo& args) { int64_t pos = GET_OFFSET(args[4]); Local req = args[5]; - if (off > buffer_length) - return env->ThrowRangeError("offset out of bounds"); - if (len > buffer_length) - return env->ThrowRangeError("length out of bounds"); - if (off + len < off) - return env->ThrowRangeError("off + len overflow"); - if (!Buffer::IsWithinBounds(off, len, buffer_length)) - return env->ThrowRangeError("off + len > buffer.length"); + CHECK_LE(off, buffer_length); + CHECK_LE(len, buffer_length); + CHECK_GE(off + len, off); + CHECK(Buffer::IsWithinBounds(off, len, buffer_length)); buf += off; @@ -999,10 +949,7 @@ static void WriteBuffers(const FunctionCallbackInfo& args) { for (uint32_t i = 0; i < iovs.length(); i++) { Local chunk = chunks->Get(i); - - if (!Buffer::HasInstance(chunk)) - return env->ThrowTypeError("Array elements all need to be buffers"); - + CHECK(Buffer::HasInstance(chunk)); iovs[i] = uv_buf_init(Buffer::Data(chunk), Buffer::Length(chunk)); } @@ -1027,8 +974,7 @@ static void WriteBuffers(const FunctionCallbackInfo& args) { static void WriteString(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - if (!args[0]->IsInt32()) - return env->ThrowTypeError("First argument must be file descriptor"); + CHECK(args[0]->IsInt32()); Local req; Local string = args[1]; @@ -1149,13 +1095,11 @@ static void Read(const FunctionCallbackInfo& args) { static void Chmod(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - if (args.Length() < 2) - return TYPE_ERROR("path and mode are required"); - if (!args[1]->IsInt32()) - return TYPE_ERROR("mode must be an integer"); + CHECK_GE(args.Length(), 2); + CHECK(args[1]->IsInt32()); BufferValue path(env->isolate(), args[0]); - ASSERT_PATH(path) + CHECK_NE(*path, nullptr); int mode = static_cast(args[1]->Int32Value()); @@ -1194,19 +1138,12 @@ static void Chown(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); int len = args.Length(); - if (len < 1) - return TYPE_ERROR("path required"); - if (len < 2) - return TYPE_ERROR("uid required"); - if (len < 3) - return TYPE_ERROR("gid required"); - if (!args[1]->IsUint32()) - return TYPE_ERROR("uid must be an unsigned int"); - if (!args[2]->IsUint32()) - return TYPE_ERROR("gid must be an unsigned int"); + CHECK_GE(len, 3); + CHECK(args[1]->IsUint32()); + CHECK(args[2]->IsUint32()); BufferValue path(env->isolate(), args[0]); - ASSERT_PATH(path) + CHECK_NE(*path, nullptr); uv_uid_t uid = static_cast(args[1]->Uint32Value()); uv_gid_t gid = static_cast(args[2]->Uint32Value()); @@ -1244,20 +1181,12 @@ static void FChown(const FunctionCallbackInfo& args) { static void UTimes(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - int len = args.Length(); - if (len < 1) - return TYPE_ERROR("path required"); - if (len < 2) - return TYPE_ERROR("atime required"); - if (len < 3) - return TYPE_ERROR("mtime required"); - if (!args[1]->IsNumber()) - return TYPE_ERROR("atime must be a number"); - if (!args[2]->IsNumber()) - return TYPE_ERROR("mtime must be a number"); + CHECK_GE(args.Length(), 3); + CHECK(args[1]->IsNumber()); + CHECK(args[2]->IsNumber()); BufferValue path(env->isolate(), args[0]); - ASSERT_PATH(path) + CHECK_NE(*path, nullptr); const double atime = static_cast(args[1]->NumberValue()); const double mtime = static_cast(args[2]->NumberValue()); diff --git a/test/parallel/test-fs-chmod.js b/test/parallel/test-fs-chmod.js index 9eae75c3c71bcd..92d420a0815a4f 100644 --- a/test/parallel/test-fs-chmod.js +++ b/test/parallel/test-fs-chmod.js @@ -113,7 +113,7 @@ fs.open(file2, 'w', common.mustCall((err, fd) => { { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "mode" argument must be of type number' + message: 'The "mode" argument must be of type integer' } ); @@ -151,7 +151,7 @@ if (fs.lchmod) { { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "fd" argument must be of type number' + message: 'The "fd" argument must be of type integer' } ); common.expectsError( @@ -159,26 +159,24 @@ if (fs.lchmod) { { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "fd" argument must be of type number' + message: 'The "fd" argument must be of type integer' } ); }); -[-1, 0xFFFFFFFF + 1].forEach((i) => { +[false, 1, {}, [], null, undefined].forEach((i) => { common.expectsError( - () => fs.fchmod(i, 0o000), + () => fs.chmod(i, 1, common.mustNotCall()), { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "fd" argument is out of range' + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError } ); common.expectsError( - () => fs.fchmodSync(i, 0o000), + () => fs.chmodSync(i, 1), { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "fd" argument is out of range' + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError } ); }); diff --git a/test/parallel/test-fs-chown-type-check.js b/test/parallel/test-fs-chown-type-check.js new file mode 100644 index 00000000000000..897c3e1de2d7e2 --- /dev/null +++ b/test/parallel/test-fs-chown-type-check.js @@ -0,0 +1,52 @@ +'use strict'; + +const common = require('../common'); +const fs = require('fs'); + +[false, 1, {}, [], null, undefined].forEach((i) => { + common.expectsError( + () => fs.chown(i, 1, 1, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.chownSync(i, 1, 1), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); +}); + +[false, 'test', {}, [], null, undefined].forEach((i) => { + common.expectsError( + () => fs.chown('not_a_file_that_exists', i, 1, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.chown('not_a_file_that_exists', 1, i, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.chownSync('not_a_file_that_exists', i, 1), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.chownSync('not_a_file_that_exists', 1, i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); +}); diff --git a/test/parallel/test-fs-close-errors.js b/test/parallel/test-fs-close-errors.js index 040f6def447b4d..cadcf2f78c4aa4 100644 --- a/test/parallel/test-fs-close-errors.js +++ b/test/parallel/test-fs-close-errors.js @@ -9,7 +9,7 @@ const fs = require('fs'); { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "fd" argument must be of type number' + message: 'The "fd" argument must be of type integer' } ); common.expectsError( @@ -17,26 +17,7 @@ const fs = require('fs'); { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "fd" argument must be of type number' - } - ); -}); - -[-1, 0xFFFFFFFF + 1].forEach((i) => { - common.expectsError( - () => fs.close(i), - { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "fd" argument is out of range' - } - ); - common.expectsError( - () => fs.closeSync(i), - { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "fd" argument is out of range' + message: 'The "fd" argument must be of type integer' } ); }); diff --git a/test/parallel/test-fs-copyfile.js b/test/parallel/test-fs-copyfile.js index 2977a5984706c3..bfda5ccfd758f8 100644 --- a/test/parallel/test-fs-copyfile.js +++ b/test/parallel/test-fs-copyfile.js @@ -70,9 +70,36 @@ common.expectsError(() => { }); // Throws if the source path is not a string. -assert.throws(() => { - fs.copyFileSync(null, dest); -}, /^TypeError: src must be a string$/); +[false, 1, {}, [], null, undefined].forEach((i) => { + common.expectsError( + () => fs.copyFile(i, dest, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.copyFile(src, i, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.copyFileSync(i, dest), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.copyFileSync(src, i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); +}); // Throws if the source path is an invalid path. common.expectsError(() => { @@ -84,11 +111,6 @@ common.expectsError(() => { ' Received type string' }); -// Throws if the destination path is not a string. -assert.throws(() => { - fs.copyFileSync(src, null); -}, /^TypeError: dest must be a string$/); - // Throws if the destination path is an invalid path. common.expectsError(() => { fs.copyFileSync(src, '\u0000'); diff --git a/test/parallel/test-fs-fchown.js b/test/parallel/test-fs-fchown.js index 2e75c6b909bfbc..8812fbbe3f4c37 100644 --- a/test/parallel/test-fs-fchown.js +++ b/test/parallel/test-fs-fchown.js @@ -9,7 +9,7 @@ const fs = require('fs'); { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "fd" argument must be of type number' + message: 'The "fd" argument must be of type integer' } ); common.expectsError( @@ -17,7 +17,7 @@ const fs = require('fs'); { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "fd" argument must be of type number' + message: 'The "fd" argument must be of type integer' } ); @@ -26,7 +26,7 @@ const fs = require('fs'); { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "uid" argument must be of type number' + message: 'The "uid" argument must be of type integer' } ); common.expectsError( @@ -34,7 +34,7 @@ const fs = require('fs'); { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "uid" argument must be of type number' + message: 'The "uid" argument must be of type integer' } ); @@ -43,7 +43,7 @@ const fs = require('fs'); { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "gid" argument must be of type number' + message: 'The "gid" argument must be of type integer' } ); common.expectsError( @@ -51,60 +51,7 @@ const fs = require('fs'); { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "gid" argument must be of type number' + message: 'The "gid" argument must be of type integer' } ); }); - -[-1, 0xFFFFFFFF + 1].forEach((i) => { - common.expectsError( - () => fs.fchown(i), - { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "fd" argument is out of range' - } - ); - common.expectsError( - () => fs.fchownSync(i), - { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "fd" argument is out of range' - } - ); -}); - -common.expectsError( - () => fs.fchown(1, -1), - { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "uid" argument is out of range' - } -); -common.expectsError( - () => fs.fchownSync(1, -1), - { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "uid" argument is out of range' - } -); - -common.expectsError( - () => fs.fchown(1, 1, -1), - { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "gid" argument is out of range' - } -); -common.expectsError( - () => fs.fchownSync(1, 1, -1), - { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "gid" argument is out of range' - } -); diff --git a/test/parallel/test-fs-fsync.js b/test/parallel/test-fs-fsync.js index 80443662c2f30c..ea80d4cbcdf7e4 100644 --- a/test/parallel/test-fs-fsync.js +++ b/test/parallel/test-fs-fsync.js @@ -55,7 +55,7 @@ fs.open(fileTemp, 'a', 0o777, common.mustCall(function(err, fd) { { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "fd" argument must be of type number' + message: 'The "fd" argument must be of type integer' } ); common.expectsError( @@ -63,7 +63,7 @@ fs.open(fileTemp, 'a', 0o777, common.mustCall(function(err, fd) { { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "fd" argument must be of type number' + message: 'The "fd" argument must be of type integer' } ); common.expectsError( @@ -71,7 +71,7 @@ fs.open(fileTemp, 'a', 0o777, common.mustCall(function(err, fd) { { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "fd" argument must be of type number' + message: 'The "fd" argument must be of type integer' } ); common.expectsError( @@ -79,26 +79,7 @@ fs.open(fileTemp, 'a', 0o777, common.mustCall(function(err, fd) { { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "fd" argument must be of type number' - } - ); -}); - -[-1, 0xFFFFFFFF + 1].forEach((i) => { - common.expectsError( - () => fs.fsync(i), - { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "fd" argument is out of range' - } - ); - common.expectsError( - () => fs.fsyncSync(i), - { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "fd" argument is out of range' + message: 'The "fd" argument must be of type integer' } ); }); diff --git a/test/parallel/test-fs-link.js b/test/parallel/test-fs-link.js index 525392aa2be01c..7cbfe5a15e22cd 100644 --- a/test/parallel/test-fs-link.js +++ b/test/parallel/test-fs-link.js @@ -21,16 +21,33 @@ fs.link(srcPath, dstPath, common.mustCall(callback)); // test error outputs -assert.throws( - function() { - fs.link(); - }, - /src must be a string or Buffer/ -); - -assert.throws( - function() { - fs.link('abc'); - }, - /dest must be a string or Buffer/ -); +[false, 1, [], {}, null, undefined].forEach((i) => { + common.expectsError( + () => fs.link(i, '', common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.link('', i, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.linkSync(i, ''), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.linkSync('', i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); +}); diff --git a/test/parallel/test-fs-mkdir.js b/test/parallel/test-fs-mkdir.js index 54585a3f12a64b..7cfb09295edde6 100644 --- a/test/parallel/test-fs-mkdir.js +++ b/test/parallel/test-fs-mkdir.js @@ -53,6 +53,23 @@ common.refreshTmpDir(); assert.strictEqual(exists, true); } +[false, 1, {}, [], null, undefined].forEach((i) => { + common.expectsError( + () => fs.mkdir(i, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.mkdirSync(i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); +}); + // Keep the event loop alive so the async mkdir() requests // have a chance to run (since they don't ref the event loop). process.nextTick(() => {}); diff --git a/test/parallel/test-fs-open.js b/test/parallel/test-fs-open.js index 94817844bdcb4c..e988a7e197bfb4 100644 --- a/test/parallel/test-fs-open.js +++ b/test/parallel/test-fs-open.js @@ -43,3 +43,20 @@ fs.open(__filename, 'r', common.mustCall((err) => { fs.open(__filename, 'rs', common.mustCall((err) => { assert.ifError(err); })); + +[false, 1, [], {}, null, undefined].forEach((i) => { + common.expectsError( + () => fs.open(i, 'r', common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.openSync(i, 'r', common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); +}); diff --git a/test/parallel/test-fs-readdir.js b/test/parallel/test-fs-readdir.js index a5c7ebfe688c41..76e6a4dc37619e 100644 --- a/test/parallel/test-fs-readdir.js +++ b/test/parallel/test-fs-readdir.js @@ -33,3 +33,20 @@ assert.throws(function() { fs.readdir(__filename, common.mustCall(function(e) { assert.strictEqual(e.code, 'ENOTDIR'); })); + +[false, 1, [], {}, null, undefined].forEach((i) => { + common.expectsError( + () => fs.readdir(i, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.readdirSync(i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); +}); diff --git a/test/parallel/test-fs-readlink-type-check.js b/test/parallel/test-fs-readlink-type-check.js new file mode 100644 index 00000000000000..914c1e55af5b2e --- /dev/null +++ b/test/parallel/test-fs-readlink-type-check.js @@ -0,0 +1,21 @@ +'use strict'; + +const common = require('../common'); +const fs = require('fs'); + +[false, 1, {}, [], null, undefined].forEach((i) => { + common.expectsError( + () => fs.readlink(i, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.readlinkSync(i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); +}); diff --git a/test/parallel/test-fs-rename-type-check.js b/test/parallel/test-fs-rename-type-check.js new file mode 100644 index 00000000000000..68126e9f7e66e8 --- /dev/null +++ b/test/parallel/test-fs-rename-type-check.js @@ -0,0 +1,43 @@ +'use strict'; + +const common = require('../common'); +const fs = require('fs'); + +[false, 1, [], {}, null, undefined].forEach((i) => { + common.expectsError( + () => fs.rename(i, 'does-not-exist', common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: + 'The "oldPath" argument must be one of type string, Buffer, or URL' + } + ); + common.expectsError( + () => fs.rename('does-not-exist', i, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: + 'The "newPath" argument must be one of type string, Buffer, or URL' + } + ); + common.expectsError( + () => fs.renameSync(i, 'does-not-exist'), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: + 'The "oldPath" argument must be one of type string, Buffer, or URL' + } + ); + common.expectsError( + () => fs.renameSync('does-not-exist', i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: + 'The "newPath" argument must be one of type string, Buffer, or URL' + } + ); +}); diff --git a/test/parallel/test-fs-rmdir-type-check.js b/test/parallel/test-fs-rmdir-type-check.js new file mode 100644 index 00000000000000..fc2106b8cabee7 --- /dev/null +++ b/test/parallel/test-fs-rmdir-type-check.js @@ -0,0 +1,21 @@ +'use strict'; + +const common = require('../common'); +const fs = require('fs'); + +[false, 1, [], {}, null, undefined].forEach((i) => { + common.expectsError( + () => fs.rmdir(i, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.rmdirSync(i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); +}); diff --git a/test/parallel/test-fs-stat.js b/test/parallel/test-fs-stat.js index 57fccc15869fe2..7f0f535d0c590c 100644 --- a/test/parallel/test-fs-stat.js +++ b/test/parallel/test-fs-stat.js @@ -137,7 +137,7 @@ fs.stat(__filename, common.mustCall(function(err, s) { { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "fd" argument must be of type number' + message: 'The "fd" argument must be of type integer' } ); common.expectsError( @@ -145,26 +145,38 @@ fs.stat(__filename, common.mustCall(function(err, s) { { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "fd" argument must be of type number' + message: 'The "fd" argument must be of type integer' } ); }); -[-1, 0xFFFFFFFF + 1].forEach((i) => { +[false, 1, {}, [], null, undefined].forEach((i) => { common.expectsError( - () => fs.fstat(i), + () => fs.lstat(i, common.mustNotCall()), { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "fd" argument is out of range' + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError } ); common.expectsError( - () => fs.fstatSync(i), + () => fs.lstatSync(i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.stat(i, common.mustNotCall()), { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "fd" argument is out of range' + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.statSync(i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError } ); }); diff --git a/test/parallel/test-fs-symlink.js b/test/parallel/test-fs-symlink.js index 1de7532068c5e5..a830b12c246c8f 100644 --- a/test/parallel/test-fs-symlink.js +++ b/test/parallel/test-fs-symlink.js @@ -57,6 +57,63 @@ fs.symlink(linkData, linkPath, common.mustCall(function(err) { })); })); +[false, 1, {}, [], null, undefined].forEach((i) => { + common.expectsError( + () => fs.symlink(i, '', common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: + 'The "target" argument must be one of type string, Buffer, or URL' + } + ); + common.expectsError( + () => fs.symlink('', i, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: + 'The "path" argument must be one of type string, Buffer, or URL' + } + ); + common.expectsError( + () => fs.symlinkSync(i, ''), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: + 'The "target" argument must be one of type string, Buffer, or URL' + } + ); + common.expectsError( + () => fs.symlinkSync('', i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: + 'The "path" argument must be one of type string, Buffer, or URL' + } + ); +}); + +common.expectsError( + () => fs.symlink('', '', '🍏', common.mustNotCall()), + { + code: 'ERR_FS_INVALID_SYMLINK_TYPE', + type: Error, + message: + 'Symlink type must be one of "dir", "file", or "junction". Received "🍏"' + } +); +common.expectsError( + () => fs.symlinkSync('', '', '🍏'), + { + code: 'ERR_FS_INVALID_SYMLINK_TYPE', + type: Error, + message: + 'Symlink type must be one of "dir", "file", or "junction". Received "🍏"' + } +); process.on('exit', function() { assert.notStrictEqual(linkTime, fileTime); diff --git a/test/parallel/test-fs-truncate.js b/test/parallel/test-fs-truncate.js index 7690ec7c24d60e..b32d1ceb2b4e55 100644 --- a/test/parallel/test-fs-truncate.js +++ b/test/parallel/test-fs-truncate.js @@ -187,7 +187,7 @@ function testFtruncate(cb) { { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "len" argument must be of type number' + message: 'The "len" argument must be of type integer' } ); }); @@ -215,7 +215,7 @@ function testFtruncate(cb) { { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "fd" argument must be of type number' + message: 'The "fd" argument must be of type integer' } ); common.expectsError( @@ -223,26 +223,7 @@ function testFtruncate(cb) { { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "fd" argument must be of type number' - } - ); -}); - -[-1, 0xFFFFFFFF + 1].forEach((i) => { - common.expectsError( - () => fs.ftruncate(i), - { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "fd" argument is out of range' - } - ); - common.expectsError( - () => fs.ftruncateSync(i), - { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "fd" argument is out of range' + message: 'The "fd" argument must be of type integer' } ); }); diff --git a/test/parallel/test-fs-unlink-type-check.js b/test/parallel/test-fs-unlink-type-check.js new file mode 100644 index 00000000000000..7fe3ce946c89d5 --- /dev/null +++ b/test/parallel/test-fs-unlink-type-check.js @@ -0,0 +1,21 @@ +'use strict'; + +const common = require('../common'); +const fs = require('fs'); + +[false, 1, {}, [], null, undefined].forEach((i) => { + common.expectsError( + () => fs.unlink(i, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.unlinkSync(i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); +}); diff --git a/test/parallel/test-fs-utimes.js b/test/parallel/test-fs-utimes.js index c9455486836c9c..ca3471cddf0c56 100644 --- a/test/parallel/test-fs-utimes.js +++ b/test/parallel/test-fs-utimes.js @@ -100,9 +100,8 @@ function testIt(atime, mtime, callback) { common.expectsError( () => fs.futimesSync(-1, atime, mtime), { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "fd" argument is out of range' + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError } ); tests_run++; @@ -130,9 +129,8 @@ function testIt(atime, mtime, callback) { common.expectsError( () => fs.futimes(-1, atime, mtime, common.mustNotCall()), { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The "fd" argument is out of range' + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, } ); @@ -206,3 +204,20 @@ if (common.isWindows) { const overflow_stats = fs.statSync(path); assert.strictEqual(overflow_mtime, overflow_stats.mtime.getTime()); } + +[false, 0, {}, [], null, undefined].forEach((i) => { + common.expectsError( + () => fs.utimes(i, new Date(), new Date(), common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.utimesSync(i, new Date(), new Date()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); +}); diff --git a/test/parallel/test-fs-write.js b/test/parallel/test-fs-write.js index ccf2d9b40f7934..cd52a57c367d54 100644 --- a/test/parallel/test-fs-write.js +++ b/test/parallel/test-fs-write.js @@ -86,3 +86,20 @@ fs.open(fn3, 'w', 0o644, common.mustCall(function(err, fd) { fs.write(fd, expected, done); })); + +[false, 'test', {}, [], null, undefined].forEach((i) => { + common.expectsError( + () => fs.write(i, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); + common.expectsError( + () => fs.writeSync(i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + } + ); +});