Skip to content

Commit

Permalink
fix: Avoid following circular symlinks (#126)
Browse files Browse the repository at this point in the history
  • Loading branch information
joshhunt authored Apr 8, 2024
1 parent 4349b07 commit cf8b197
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 3 deletions.
22 changes: 20 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -114,12 +129,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();
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/symlinks/circular-symlink
1 change: 1 addition & 0 deletions test/fixtures/symlinks/folder-a/folder-a-file.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hello a
1 change: 1 addition & 0 deletions test/fixtures/symlinks/folder-a/link-to-b
1 change: 1 addition & 0 deletions test/fixtures/symlinks/folder-b/folder-b-file.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
world b
1 change: 1 addition & 0 deletions test/fixtures/symlinks/folder-b/link-to-a
38 changes: 37 additions & 1 deletion test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -818,12 +818,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(
Expand Down

0 comments on commit cf8b197

Please sign in to comment.