Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Symlink loops prevent finding all files, but phan still exits with a successful exit code #4842

Open
anomiex opened this issue Mar 5, 2024 · 0 comments

Comments

@anomiex
Copy link

anomiex commented Mar 5, 2024

If Phan runs into a symlink loop when trying to find files, it will print a warning, not find all of the files that should be processed, and then may exit with a successful exit code.

Reproduction

  1. Create an empty directory for the test.
  2. composer require --dev phan/phan
  3. Create a file with something Phan will complain about: printf '<?php\n\nfoo();' > foo.php
  4. Create the directory with a symlink loop. For some reason I find I have to create two symlinks for it to reproduce the bug. 🤷 mkdir subdir && ln -s . subdir/loop1 && ln -s . subdir/loop2
  5. For good measure, create another file with something Phan will complain about: printf '<?php\n\nxxx();' > xxx.php
  6. Run Phan and examine its exit code: vendor/bin/phan --debug --directory . --exclude-directory-list vendor; echo $?

Actual results

Phan prints a warning, doesn't scan any of the files, and exits with a status of 0.

WARNING: Caught exception while listing files in '.': RecursiveDirectoryIterator::__construct(./subdir/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop2/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop2/loop2/loop2/loop2/loop2/loop2/loop2/loop2): Failed to open directory: Too many levels of symbolic links
Phan did not parse any files in the project "/tmp/test" - This may be an issue with the Phan config or CLI options.
0

In some of the real-life cases where I ran into this, Phan did process a subset of the files it was supposed to process, presumably whichever ones it found before running into the symlink loop.

Expected results

Either Phan detects the loop and still analyzes both PHP files, or it prints an error that it couldn't successfully process the provided directories and exits with a non-zero status.

To be clear, I'd be happy with it doing something like this:

ERROR: Caught exception while listing files in '.': RecursiveDirectoryIterator::__construct(./subdir/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop2/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop2/loop2/loop2/loop2/loop2/loop2/loop2/loop2): Failed to open directory: Too many levels of symbolic links
1

The non-zero exit code would make our CI that's running Phan indicate that an error occurred. Then I'd be notified to look into it, at which point I'd figure out what I needed to change in our config (probably an addition to exclude_file_list or exclude_file_regex) to avoid having Phan look into whichever path has the loop.

I'd also be happy with this:

WARNING: Caught exception while listing files in '.': RecursiveDirectoryIterator::__construct(./subdir/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop2/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop1/loop2/loop2/loop2/loop2/loop2/loop2/loop2/loop2): Failed to open directory: Too many levels of symbolic links
[... processing proceeds with all files that would have been found if it weren't for the loop ...]
Phan's analysis is complete
foo.php:3 PhanUndeclaredFunction Call to undeclared function \foo()
xxx.php:3 PhanUndeclaredFunction Call to undeclared function \xxx()
1

But making that happen would likely be more effort and I don't know that it would be worth it.

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

No branches or pull requests

1 participant