fs: fix ENOTDIR in globSync when file is treated as dir

`fs.globSync` failed with `ENOTDIR` when a path component in a glob
pattern was a file but used as a directory (e.g., 'foo{,/bar}' when
'foo' is a file).

This change aligns `getDirentSync` with the asynchronous `getDirent`
by wrapping the `lstatSync` call in a `try-catch` block to safely
return `null` on such errors.

Fixes: https://github.com/nodejs/node/issues/61257
PR-URL: https://github.com/nodejs/node/pull/61259
Reviewed-By: René <contact.9a5d6388@renegade334.me.uk>
This commit is contained in:
sangwook authored and GitHub committed 2026-01-17 13:33:55 +00:00
1 parent 70ec5c009d
commit 13a662f559
2 files changed
+23 -3

No files matched your search

+4 -2
View File
@@ -65,8 +65,10 @@ async function getDirent(path) {
* @returns {DirentFromStats|null}
*/
function getDirentSync(path) {
const stat = lstatSync(path, { throwIfNoEntry: false });
if (stat === undefined) {
let stat;
try {
stat = lstatSync(path);
} catch {
return null;
}
return new DirentFromStats(basename(path), stat, dirname(path));
+19 -1
View File
@@ -2,7 +2,7 @@ import * as common from '../common/index.mjs';
import tmpdir from '../common/tmpdir.js';
import { resolve, dirname, sep, relative, join, isAbsolute } from 'node:path';
import { mkdir, writeFile, symlink, glob as asyncGlob } from 'node:fs/promises';
import { glob, globSync, Dirent, chmodSync } from 'node:fs';
import { glob, globSync, Dirent, chmodSync, writeFileSync, rmSync } from 'node:fs';
import { test, describe } from 'node:test';
import { pathToFileURL } from 'node:url';
import { promisify } from 'node:util';
@@ -543,3 +543,21 @@ describe('glob - with restricted directory', function() {
}
});
});
describe('globSync - ENOTDIR', function() {
test('should return empty array when a file is treated as a directory', () => {
const file = tmpdir.resolve('foo');
writeFileSync(file, '');
try {
const pattern = 'foo{,/bar}';
const actual = globSync(pattern, { cwd: tmpdir.path }).sort();
assert.deepStrictEqual(actual, ['foo']);
} finally {
try {
rmSync(file);
} catch {
// ignore
}
}
});
});