Skip to content

Fix infinite recursion in project discovery on symlink cycles - #4421

Open
michaelglass wants to merge 1 commit into
fsprojects:masterfrom
michaelglass:fix/symlink-project-discovery-loop
Open

Fix infinite recursion in project discovery on symlink cycles#4421
michaelglass wants to merge 1 commit into
fsprojects:masterfrom
michaelglass:fix/symlink-project-discovery-loop

Conversation

@michaelglass

Copy link
Copy Markdown

Summary

  • detect directory cycles while recursively resolving project paths
  • prune already-visited project discovery directories
  • add a regression covering symlink loops

Verification

  • Release build passed
  • unit suite: 1,250 total, 1,242 passed, 8 skipped
  • symlink-loop regression passed
  • legacy net461 integration is not runnable to completion on this Apple Silicon/Rosetta host
  • netcore integration reaches an unrelated existing Group conditions for dotnet sdk projects #2394 conditions test whose generated shell command fails because an unquoted semicolon is interpreted by macOS shell (PROPERTYZ: command not found)

No integration failure touched the symlink-discovery path.

ProjectFile.SearchAllProjectRelatedFiles walks the directory tree to find
*proj* files, following directory symlinks with no cycle detection. A
self-referential or cyclic directory symlink — e.g. the macOS SDK ncurses
symlink loops inside a Nix `.devenv` profile — drives the walk into
unbounded recursion, so `paket restore` hangs (surfacing downstream as
"project.assets.json stale ... 'dotnet restore' timed out after 300s").

Resolve each directory to its canonical, symlink-followed path and skip
ones already visited. Symlinks are still followed (legitimately symlinked
project directories are still discovered) — only repeats are pruned, so
cycles terminate and each physical project is reported once.

Canonicalization uses libc `realpath` on Unix (Paket.Core targets
net461/netstandard2.0, which lack DirectoryInfo.ResolveLinkTarget) with a
lexical Path.GetFullPath fallback on Windows and on any failure.

Adds a regression test: red without the fix (the project is found 32x
before the path outgrows PATH_MAX), green with it (found exactly once).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant