vimeo / psalm

A static analysis tool for finding errors in PHP applications
https://psalm.dev
MIT License
5.55k stars 660 forks source link

psalter crash when using MissingThrowsDocblock,MissingParamType with a combination of filesize occurs #8554

Open shadowwa opened 2 years ago

shadowwa commented 2 years ago

Hello,

I got a puzzling crash on my project when using:

psalm --alter --issues=MissingThrowsDocblock,MissingParamType --dry-run Action/Plugin.class.php 
Target PHP version: 8.1 (inferred from current PHP version)
Scanning files...
Analyzing files...

░Uncaught ValueError: strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) in /home/shad/.config/composer/vendor/vimeo/psalm/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php:169
Stack trace:
#0 /home/shad/.config/composer/vendor/vimeo/psalm/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php(169): strpos()
#1 /home/shad/.config/composer/vendor/vimeo/psalm/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php(118): Psalm\Internal\FileManipulation\FunctionDocblockManipulator->__construct()
#2 /home/shad/.config/composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php(750): Psalm\Internal\FileManipulation\FunctionDocblockManipulator::getForFunction()
#3 /home/shad/.config/composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassAnalyzer.php(1798): Psalm\Internal\Analyzer\FunctionLikeAnalyzer->analyze()
#4 /home/shad/.config/composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassAnalyzer.php(1226): Psalm\Internal\Analyzer\ClassAnalyzer->analyzeClassMethod()
#5 /home/shad/.config/composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassAnalyzer.php(550): Psalm\Internal\Analyzer\ClassAnalyzer->checkPropertyInitialization()
#6 /home/shad/.config/composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FileAnalyzer.php(229): Psalm\Internal\Analyzer\ClassAnalyzer->analyze()
#7 /home/shad/.config/composer/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php(362): Psalm\Internal\Analyzer\FileAnalyzer->analyze()
#8 /home/shad/.config/composer/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php(619): Psalm\Internal\Codebase\Analyzer->Psalm\Internal\Codebase\{closure}()
#9 /home/shad/.config/composer/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php(291): Psalm\Internal\Codebase\Analyzer->doAnalysis()
#10 /home/shad/.config/composer/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php(691): Psalm\Internal\Codebase\Analyzer->analyzeFiles()
#11 /home/shad/.config/composer/vendor/vimeo/psalm/src/Psalm/Internal/Cli/Psalter.php(407): Psalm\Internal\Analyzer\ProjectAnalyzer->check()
#12 /home/shad/.config/composer/vendor/vimeo/psalm/src/Psalm/Internal/Cli/Psalm.php(931): Psalm\Internal\Cli\Psalter::run()
#13 /home/shad/.config/composer/vendor/vimeo/psalm/src/Psalm/Internal/Cli/Psalm.php(177): Psalm\Internal\Cli\Psalm::forwardCliCall()
#14 /home/shad/.config/composer/vendor/vimeo/psalm/psalm(7): Psalm\Internal\Cli\Psalm::run()
#15 /home/shad/.config/composer/vendor/bin/psalm(120): include('/home/shad/.con...')
#16 {main}
(Psalm 4.28.0@52e96bea381e6cb07a672aefec791a5817694a26 crashed due to an uncaught Throwable)

I was able to simplify to code to obtain the test files include in the zip. the puzzling part come from the bug seems to depends of the filesize and the code:

test-psalm.zip

orklah commented 2 years ago

That's weird

There's a few of your points that can be explained though.

First, note that you're running an analysis against your plugin (while enabling that plugin). That's quite unusual but it shouldn't lead to a crash. Second, the file where the crash happens is the class dedicated to edit docblocks. That makes sense that if you remove the cause of the issue that lead to Psalm editing a docblock, the crash disappears (for example, when you remove the parameter given you're running MissingParamType). Third, the particular line that crashes is https://github.com/vimeo/psalm/blob/e3f46d9a3cb3eb3932e8a48a4c9bd6156a4494ba/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php#L169 It's a line that tries to locate the function by searching the closing bracket after the parameters.

My guess is that we're in an edge case, possibly caused by some wrong assumption by Psalm when calculating positions

Could you try debugging this to see what's going on in there?

shadowwa commented 2 years ago

here are the debug output, I also tried to see if there was a difference between a psalm installed globaly on in the project, but the crash occured in both cases.

psalm-install-global.txt psalm-install-in-project.txt