staabm/phpstan-todo-by

TodoByPackageVersionRule: backtrack limit error

Closed this issue · 5 comments

the comment

// TODO: minimumApiClientVersion:2.0 This can be removed once all API consumers use client version 2.0 or higher

Uncaught RuntimeException: Error in PCRE: Backtrack limit exhausted in /Users/staabm/workspace/phpstan-todo-by/src/utils/CommentMatcher.php:43
#0 /Users/staabm/workspace/phpstan-todo-by/src/TodoByPackageVersionRule.php(71): staabm\PHPStanTodoBy\utils\CommentMatcher::matchComments(Object(PhpParser\Node\Stmt\Nop), '{\n    @?TODO # ...')
#1 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php(107): staabm\PHPStanTodoBy\TodoByPackageVersionRule->processNode(Object(PhpParser\Node\Stmt\Nop), Object(PHPStan\Analyser\MutatingScope))
#2 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(459): PHPStan\Analyser\FileAnalyser->PHPStan\Analyser\{closure}(Object(PhpParser\Node\Stmt\Nop), Object(PHPStan\Analyser\MutatingScope))
#3 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(402): PHPStan\Analyser\NodeScopeResolver->processStmtNode(Object(PhpParser\Node\Stmt\Nop), Object(PHPStan\Analyser\MutatingScope), Object(Closure), Object(PHPStan\Analyser\StatementContext))
#4 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(641): PHPStan\Analyser\NodeScopeResolver->processStmtNodes(Object(PhpParser\Node\Stmt\Namespace_), Array, Object(PHPStan\Analyser\MutatingScope), Object(Closure), Object(PHPStan\Analyser\StatementContext))
#5 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(371): PHPStan\Analyser\NodeScopeResolver->processStmtNode(Object(PhpParser\Node\Stmt\Namespace_), Object(PHPStan\Analyser\MutatingScope), Object(Closure), Object(PHPStan\Analyser\StatementContext))
#6 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php(166): PHPStan\Analyser\NodeScopeResolver->processNodes(Array, Object(PHPStan\Analyser\MutatingScope), Object(Closure))
#7 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/Analyser.php(72): PHPStan\Analyser\FileAnalyser->analyseFile('/Users/staabm/w...', Array, Object(PHPStan\Rules\LazyRegistry), Object(PHPStan\Collectors\Registry), NULL)
#8 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/src/Command/AnalyserRunner.php(62): PHPStan\Analyser\Analyser->analyse(Array, Object(Closure), NULL, true, Array)
#9 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/src/Command/AnalyseApplication.php(209): PHPStan\Command\AnalyserRunner->runAnalyser(Array, Array, Object(Closure), NULL, true, true, '/Users/staabm/w...', Object(_PHPStan_39fe102d2\Symfony\Component\Console\Input\ArgvInput))
#10 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/src/Command/AnalyseApplication.php(101): PHPStan\Command\AnalyseApplication->runAnalyser(Array, Array, true, '/Users/staabm/w...', Object(PHPStan\Command\Symfony\SymfonyOutput), Object(PHPStan\Command\Symfony\SymfonyOutput), Object(_PHPStan_39fe102d2\Symfony\Component\Console\Input\ArgvInput))
#11 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/src/Command/AnalyseCommand.php(198): PHPStan\Command\AnalyseApplication->analyse(Array, true, Object(PHPStan\Command\Symfony\SymfonyOutput), Object(PHPStan\Command\Symfony\SymfonyOutput), false, true, '/Users/staabm/w...', Array, Object(_PHPStan_39fe102d2\Symfony\Component\Console\Input\ArgvInput))
#12 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Command/Command.php(259): PHPStan\Command\AnalyseCommand->execute(Object(_PHPStan_39fe102d2\Symfony\Component\Console\Input\ArgvInput), Object(_PHPStan_39fe102d2\Symfony\Component\Console\Output\ConsoleOutput))
#13 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(870): _PHPStan_39fe102d2\Symfony\Component\Console\Command\Command->run(Object(_PHPStan_39fe102d2\Symfony\Component\Console\Input\ArgvInput), Object(_PHPStan_39fe102d2\Symfony\Component\Console\Output\ConsoleOutput))
#14 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(261): _PHPStan_39fe102d2\Symfony\Component\Console\Application->doRunCommand(Object(PHPStan\Command\AnalyseCommand), Object(_PHPStan_39fe102d2\Symfony\Component\Console\Input\ArgvInput), Object(_PHPStan_39fe102d2\Symfony\Component\Console\Output\ConsoleOutput))
#15 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(157): _PHPStan_39fe102d2\Symfony\Component\Console\Application->doRun(Object(_PHPStan_39fe102d2\Symfony\Component\Console\Input\ArgvInput), Object(_PHPStan_39fe102d2\Symfony\Component\Console\Output\ConsoleOutput))
#16 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/bin/phpstan(124): _PHPStan_39fe102d2\Symfony\Component\Console\Application->run()
#17 phar:///Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan.phar/bin/phpstan(125): _PHPStan_39fe102d2\{closure}()
#18 /Users/staabm/workspace/phpstan-todo-by/vendor/phpstan/phpstan/phpstan(8): require('phar:///Users/s...')
#19 /Users/staabm/workspace/phpstan-todo-by/vendor/bin/phpstan(119): include('/Users/staabm/w...')
#20 {main}

triggers a PCRE backtrack limit error

@glaubinix do you have a idea why the example you gave runs into backtrack limits on this regex pattern?

or maybe @Seldaek has an idea?

If I saw this correct, then you used the regex used by Composer/Packagist.org to validate a package name? If the package name part is one long string without / then the PCRE backtrack limit can be reached. One solution is to use possessive greedy quantifiers ++ *+ instead of + and *. Just be aware that this can cause that certain package names doesn't get matched by the regex but we haven't seen any name like that out there.

So the package name part of your regex would then look like (?:(?P<package>(php|[a-z0-9]([_.-]?[a-z0-9]++)*+/[a-z0-9](([_.]|-{1,2})?[a-z0-9]++)*+)):) # "php" or a composer package name, followed by ":"

If I saw this correct, then you used the regex used by Composer/Packagist.org to validate a package name?

rights, its from the website.

One solution is to use the greedy quantifiers ++ *+ instead of + and *.

oohh wow.. never seen this regex syntax before

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.