Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fix infinite recursion in specifyTypesForCountFuncCall with mixed TypeSpecifierContext#5653

Merged
ondrejmirtes merged 1 commit into
phpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-cnjm8q5
May 13, 2026
Merged

Fix infinite recursion in specifyTypesForCountFuncCall with mixed TypeSpecifierContext#5653
ondrejmirtes merged 1 commit into
phpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-cnjm8q5

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

Summary

Fixes an infinite recursion / OOM crash triggered when PHPStan analyzes a ternary expression that:

  1. Uses count($arr) > N on a constant array with optional keys as the condition
  2. Has both branches produce falsy values (e.g., count($m) > 1 ? false : '')

The crash occurs because AssignHandler calls specifyTypesInCondition in false context on the ternary, which expands it into BooleanOr(BooleanAnd(...), ...). Processing this reaches specifyTypesForCountFuncCall with a false context. The function's falsey-branch guard passes, and it recurses with $context->negate(). But negate(false) = 0b1011, which has both truthy and falsey bits set. On re-entry, the $context->falsey() guard passes again → infinite recursion → OOM.

The fix replaces $context->negate() with explicit TypeSpecifierContext::createTrue() or createTruthy(), ensuring the recursive call always uses a clean truthy context that cannot re-enter the falsey branch.

Minimal reproducer (crashes without fix):

/** @param array{0: string, 1?: string} $m */
function test(array $m): void {
    $x = count($m) > 1 ? false : '';
}

Closes phpstan/phpstan#14605

…eSpecifierContext

When specifyTypesForCountFuncCall was entered with a `false` context
(0b0100), it used $context->negate() to produce the recursive call's
context. But negate(false) = 0b1011, which has BOTH truthy AND falsey
bits set. The guard `$context->falsey()` matched this mixed context,
causing the function to re-enter its own falsey branch indefinitely.

Replace $context->negate() with an explicit createTrue()/createTruthy()
depending on whether the incoming context is strictly false or falsey.
This guarantees the recursive call uses a clean truthy context that
cannot re-enter the falsey branch.

Closes phpstan/phpstan#14605
@ondrejmirtes ondrejmirtes merged commit 8932eec into phpstan:2.1.x May 13, 2026
630 of 659 checks passed
@ondrejmirtes ondrejmirtes deleted the create-pull-request/patch-cnjm8q5 branch May 13, 2026 07:09
@staabm staabm mentioned this pull request May 13, 2026
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.

2 participants