From 0e36fd9fb567782a2200f68984500de84ba5f887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Jos=C3=A9?= Date: Mon, 25 Nov 2024 00:07:13 -0500 Subject: [PATCH] lib: avoid excluding symlinks in recursive fs.readdir with filetypes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/nodejs/node/issues/52663 Signed-off-by: Juan José Arboleda PR-URL: https://github.com/nodejs/node/pull/55714 Reviewed-By: Ethan Arrowood Reviewed-By: James M Snell --- lib/fs.js | 5 ++- .../test-fs-readdir-types-symlinks.js | 36 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-fs-readdir-types-symlinks.js diff --git a/lib/fs.js b/lib/fs.js index b759c8e124bb45..9292826c3e2617 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -1404,9 +1404,12 @@ function readdirSyncRecursive(basePath, options) { // of the first array within the result. const length = readdirResult[0].length; for (let i = 0; i < length; i++) { + // Avoid excluding symlinks, as they are not directories. + // Refs: https://github.com/nodejs/node/issues/52663 + const stat = binding.internalModuleStat(binding, pathModule.join(path, readdirResult[0][i])); const dirent = getDirent(path, readdirResult[0][i], readdirResult[1][i]); ArrayPrototypePush(readdirResults, dirent); - if (dirent.isDirectory()) { + if (dirent.isDirectory() || stat === 1) { ArrayPrototypePush(pathsQueue, pathModule.join(dirent.parentPath, dirent.name)); } } diff --git a/test/parallel/test-fs-readdir-types-symlinks.js b/test/parallel/test-fs-readdir-types-symlinks.js new file mode 100644 index 00000000000000..afdbdb16364c03 --- /dev/null +++ b/test/parallel/test-fs-readdir-types-symlinks.js @@ -0,0 +1,36 @@ +'use strict'; + +// Refs: https://github.com/nodejs/node/issues/52663 +const common = require('../common'); +const assert = require('node:assert'); +const fs = require('node:fs'); +const path = require('node:path'); + +if (!common.canCreateSymLink()) + common.skip('insufficient privileges'); + +const tmpdir = require('../common/tmpdir'); +const readdirDir = tmpdir.path; +// clean up the tmpdir +tmpdir.refresh(); + +// a/1, a/2 +const a = path.join(readdirDir, 'a'); +fs.mkdirSync(a); +fs.writeFileSync(path.join(a, '1'), 'irrelevant'); +fs.writeFileSync(path.join(a, '2'), 'irrelevant'); + +// b/1 +const b = path.join(readdirDir, 'b'); +fs.mkdirSync(b); +fs.writeFileSync(path.join(b, '1'), 'irrelevant'); + +// b/c -> a +const c = path.join(readdirDir, 'b', 'c'); +fs.symlinkSync(a, c, 'dir'); + +// Just check that the number of entries are the same +assert.strictEqual( + fs.readdirSync(b, { recursive: true, withFileTypes: true }).length, + fs.readdirSync(b, { recursive: true, withFileTypes: false }).length +);