From 3f9c917b9b63b0474c9d40b5f1d4884600006a9c Mon Sep 17 00:00:00 2001 From: joshhunt Date: Sun, 31 Mar 2024 15:22:01 +0100 Subject: [PATCH 1/2] fix: Don't follow circular symlinks --- index.js | 22 ++++++++++++++++++++-- test/fixtures/symlinks/circular-symlink | 1 + 2 files changed, 21 insertions(+), 2 deletions(-) create mode 120000 test/fixtures/symlinks/circular-symlink diff --git a/index.js b/index.js index fdaed62..f9fca9e 100644 --- a/index.js +++ b/index.js @@ -24,6 +24,21 @@ function isFound(glob) { return isGlob(glob); } +function getSymlinkInfo(filepath, cb) { + fs.realpath(filepath, function (err, realPath) { + if (err) return cb(err); + + fs.lstat(realPath, function (err, lstat) { + if (err) return cb(err); + + cb(null, { + destinationPath: realPath, + destinationStat: lstat, + }); + }); + }); +} + function walkdir() { var readdirOpts = { withFileTypes: true, @@ -95,12 +110,15 @@ function walkdir() { if (dirent.isSymbolicLink()) { // If it's a symlink, check if the symlink points to a directory - fs.stat(nextpath, function (err, stats) { + getSymlinkInfo(nextpath, function (err, info) { if (err) { return cb(err); } - if (stats.isDirectory()) { + if ( + info.destinationStat.isDirectory() && + !nextpath.startsWith(info.destinationPath + path.sep) // don't follow circular symlinks + ) { cb(null, nextpath); } else { cb(); diff --git a/test/fixtures/symlinks/circular-symlink b/test/fixtures/symlinks/circular-symlink new file mode 120000 index 0000000..6581736 --- /dev/null +++ b/test/fixtures/symlinks/circular-symlink @@ -0,0 +1 @@ +../../ \ No newline at end of file From f43e1f1455ecdcd2a4dedb99a9ca9d84a1047918 Mon Sep 17 00:00:00 2001 From: Josh Hunt Date: Sat, 6 Apr 2024 11:48:07 +0100 Subject: [PATCH 2/2] add more test cases --- .../symlinks/folder-a/folder-a-file.txt | 1 + test/fixtures/symlinks/folder-a/link-to-b | 1 + .../symlinks/folder-b/folder-b-file.txt | 1 + test/fixtures/symlinks/folder-b/link-to-a | 1 + test/index.js | 38 ++++++++++++++++++- 5 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/symlinks/folder-a/folder-a-file.txt create mode 120000 test/fixtures/symlinks/folder-a/link-to-b create mode 100644 test/fixtures/symlinks/folder-b/folder-b-file.txt create mode 120000 test/fixtures/symlinks/folder-b/link-to-a diff --git a/test/fixtures/symlinks/folder-a/folder-a-file.txt b/test/fixtures/symlinks/folder-a/folder-a-file.txt new file mode 100644 index 0000000..74614c9 --- /dev/null +++ b/test/fixtures/symlinks/folder-a/folder-a-file.txt @@ -0,0 +1 @@ +hello a diff --git a/test/fixtures/symlinks/folder-a/link-to-b b/test/fixtures/symlinks/folder-a/link-to-b new file mode 120000 index 0000000..50822b2 --- /dev/null +++ b/test/fixtures/symlinks/folder-a/link-to-b @@ -0,0 +1 @@ +../folder-b \ No newline at end of file diff --git a/test/fixtures/symlinks/folder-b/folder-b-file.txt b/test/fixtures/symlinks/folder-b/folder-b-file.txt new file mode 100644 index 0000000..2d684fd --- /dev/null +++ b/test/fixtures/symlinks/folder-b/folder-b-file.txt @@ -0,0 +1 @@ +world b diff --git a/test/fixtures/symlinks/folder-b/link-to-a b/test/fixtures/symlinks/folder-b/link-to-a new file mode 120000 index 0000000..4caf2d9 --- /dev/null +++ b/test/fixtures/symlinks/folder-b/link-to-a @@ -0,0 +1 @@ +../folder-a \ No newline at end of file diff --git a/test/index.js b/test/index.js index c87c057..a59bf59 100644 --- a/test/index.js +++ b/test/index.js @@ -765,12 +765,48 @@ function suite(moduleName) { dir + '/fixtures/symlinks/symlink-dest/hey/isaidhey/whatsgoingon/test.txt', }, + + { + cwd: dir, + base: dir + '/fixtures/symlinks', + path: dir + '/fixtures/symlinks/folder-a/folder-a-file.txt', + }, + { + cwd: dir, + base: dir + '/fixtures/symlinks', + path: dir + '/fixtures/symlinks/folder-b/folder-b-file.txt', + }, + + // It should follow these circular symlinks, but not infinitely + { + cwd: dir, + base: dir + '/fixtures/symlinks', + path: dir + '/fixtures/symlinks/folder-a/link-to-b/folder-b-file.txt', + }, + { + cwd: dir, + base: dir + '/fixtures/symlinks', + path: dir + '/fixtures/symlinks/folder-b/link-to-a/folder-a-file.txt', + }, + + // And it should follow a symlink to a parent directory (circular symlink) without blowing up + { + cwd: dir, + base: dir + '/fixtures/symlinks', + path: + dir + + '/fixtures/symlinks/symlink-dest/hey/isaidhey/whatsgoingon/test.txt', + }, ]; function assert(pathObjs) { - expect(pathObjs.length).toBe(2); + expect(pathObjs.length).toBe(6); expect(pathObjs).toContainEqual(expected[0]); expect(pathObjs).toContainEqual(expected[1]); + expect(pathObjs).toContainEqual(expected[2]); + expect(pathObjs).toContainEqual(expected[3]); + expect(pathObjs).toContainEqual(expected[4]); + expect(pathObjs).toContainEqual(expected[5]); } stream.pipeline(