diff options
-rw-r--r-- | lib/fs.js | 11 | ||||
-rw-r--r-- | test/parallel/test-fs-symlink-dir-junction.js | 17 | ||||
-rw-r--r-- | test/parallel/test-fs-symlink-dir.js | 22 | ||||
-rw-r--r-- | test/parallel/test-fs-symlink.js | 12 |
4 files changed, 61 insertions, 1 deletions
diff --git a/lib/fs.js b/lib/fs.js index 6a5ebb8203a..de37a0c2a0a 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -234,7 +234,16 @@ function existsSync(path) { return false; } const ctx = { path }; - binding.access(pathModule.toNamespacedPath(path), F_OK, undefined, ctx); + const nPath = pathModule.toNamespacedPath(path); + binding.access(nPath, F_OK, undefined, ctx); + + // In case of an invalid symlink, `binding.access()` on win32 + // will **not** return an error and is therefore not enough. + // Double check with `binding.stat()`. + if (isWindows && ctx.errno === undefined) { + binding.stat(nPath, false, undefined, ctx); + } + return ctx.errno === undefined; } diff --git a/test/parallel/test-fs-symlink-dir-junction.js b/test/parallel/test-fs-symlink-dir-junction.js index fc89ad36840..42d6bc12141 100644 --- a/test/parallel/test-fs-symlink-dir-junction.js +++ b/test/parallel/test-fs-symlink-dir-junction.js @@ -53,3 +53,20 @@ fs.symlink(linkData, linkPath, 'junction', common.mustCall(function(err) { })); })); })); + +// Test invalid symlink +{ + const linkData = fixtures.path('/not/exists/dir'); + const linkPath = path.join(tmpdir.path, 'invalid_junction_link'); + + fs.symlink(linkData, linkPath, 'junction', common.mustCall(function(err) { + assert.ifError(err); + + assert(!fs.existsSync(linkPath)); + + fs.unlink(linkPath, common.mustCall(function(err) { + assert.ifError(err); + assert(!fs.existsSync(linkPath)); + })); + })); +} diff --git a/test/parallel/test-fs-symlink-dir.js b/test/parallel/test-fs-symlink-dir.js index 1ab1361a43f..707bc5b486d 100644 --- a/test/parallel/test-fs-symlink-dir.js +++ b/test/parallel/test-fs-symlink-dir.js @@ -44,3 +44,25 @@ for (const linkTarget of linkTargets) { testAsync(linkTarget, `${linkPath}-${path.basename(linkTarget)}-async`); } } + +// Test invalid symlink +{ + function testSync(target, path) { + fs.symlinkSync(target, path); + assert(!fs.existsSync(path)); + } + + function testAsync(target, path) { + fs.symlink(target, path, common.mustCall((err) => { + assert.ifError(err); + assert(!fs.existsSync(path)); + })); + } + + for (const linkTarget of linkTargets.map((p) => p + '-broken')) { + for (const linkPath of linkPaths) { + testSync(linkTarget, `${linkPath}-${path.basename(linkTarget)}-sync`); + testAsync(linkTarget, `${linkPath}-${path.basename(linkTarget)}-async`); + } + } +} diff --git a/test/parallel/test-fs-symlink.js b/test/parallel/test-fs-symlink.js index a6001103190..c52ffbc105f 100644 --- a/test/parallel/test-fs-symlink.js +++ b/test/parallel/test-fs-symlink.js @@ -58,6 +58,18 @@ fs.symlink(linkData, linkPath, common.mustCall(function(err) { })); })); +// Test invalid symlink +{ + const linkData = fixtures.path('/not/exists/file'); + const linkPath = path.join(tmpdir.path, 'symlink2.js'); + + fs.symlink(linkData, linkPath, common.mustCall(function(err) { + assert.ifError(err); + + assert(!fs.existsSync(linkPath)); + })); +} + [false, 1, {}, [], null, undefined].forEach((input) => { const errObj = { code: 'ERR_INVALID_ARG_TYPE', |