mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-14 07:10:34 -07:00
fix(core): prevent infinite recursion in symlink resolution (#21750)
This commit is contained in:
@@ -375,7 +375,12 @@ export function resolveToRealPath(pathStr: string): string {
|
||||
return robustRealpath(path.resolve(resolvedPath));
|
||||
}
|
||||
|
||||
function robustRealpath(p: string): string {
|
||||
function robustRealpath(p: string, visited = new Set<string>()): string {
|
||||
const key = process.platform === 'win32' ? p.toLowerCase() : p;
|
||||
if (visited.has(key)) {
|
||||
throw new Error(`Infinite recursion detected in robustRealpath: ${p}`);
|
||||
}
|
||||
visited.add(key);
|
||||
try {
|
||||
return fs.realpathSync(p);
|
||||
} catch (e: unknown) {
|
||||
@@ -385,14 +390,25 @@ function robustRealpath(p: string): string {
|
||||
if (stat.isSymbolicLink()) {
|
||||
const target = fs.readlinkSync(p);
|
||||
const resolvedTarget = path.resolve(path.dirname(p), target);
|
||||
return robustRealpath(resolvedTarget);
|
||||
return robustRealpath(resolvedTarget, visited);
|
||||
}
|
||||
} catch (lstatError: unknown) {
|
||||
// Not a symlink, or lstat failed. Re-throw if it's not an expected
|
||||
// ENOENT (e.g., a permissions error), otherwise resolve parent.
|
||||
if (
|
||||
!(
|
||||
lstatError &&
|
||||
typeof lstatError === 'object' &&
|
||||
'code' in lstatError &&
|
||||
lstatError.code === 'ENOENT'
|
||||
)
|
||||
) {
|
||||
throw lstatError;
|
||||
}
|
||||
} catch {
|
||||
// Not a symlink, or lstat failed. Just resolve parent.
|
||||
}
|
||||
const parent = path.dirname(p);
|
||||
if (parent === p) return p;
|
||||
return path.join(robustRealpath(parent), path.basename(p));
|
||||
return path.join(robustRealpath(parent, visited), path.basename(p));
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user