Skip to content

Commit 7e60d89

Browse files
committed
Fix slow analysis on return with a big OR condition
1 parent 98bb0a9 commit 7e60d89

1 file changed

Lines changed: 31 additions & 0 deletions

File tree

src/Analyser/NodeScopeResolver.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@
238238
class NodeScopeResolver
239239
{
240240

241+
private const BOOLEAN_EXPRESSION_MAX_PROCESS_DEPTH = 16;
242+
241243
private const LOOP_SCOPE_ITERATIONS = 3;
242244
private const GENERALIZE_AFTER_ITERATION = 1;
243245

@@ -3659,6 +3661,21 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
36593661
);
36603662
return $result;
36613663
} elseif ($expr instanceof BooleanOr || $expr instanceof BinaryOp\LogicalOr) {
3664+
if ($this->getBooleanExpressionDepth($expr->left) > self::BOOLEAN_EXPRESSION_MAX_PROCESS_DEPTH) {
3665+
$leftResult = $this->processExprNode($stmt, $expr->left, $scope, $storage, $nodeCallback, $context->enterDeep());
3666+
$rightResult = $this->processExprNode($stmt, $expr->right, $scope, $storage, $nodeCallback, $context);
3667+
3668+
return new ExpressionResult(
3669+
$scope,
3670+
$leftResult->hasYield() || $rightResult->hasYield(),
3671+
$leftResult->isAlwaysTerminating(),
3672+
array_merge($leftResult->getThrowPoints(), $rightResult->getThrowPoints()),
3673+
array_merge($leftResult->getImpurePoints(), $rightResult->getImpurePoints()),
3674+
static fn (): MutatingScope => $scope,
3675+
static fn (): MutatingScope => $scope,
3676+
);
3677+
}
3678+
36623679
$leftResult = $this->processExprNode($stmt, $expr->left, $scope, $storage, $nodeCallback, $context->enterDeep());
36633680
$rightResult = $this->processExprNode($stmt, $expr->right, $leftResult->getFalseyScope(), $storage, $nodeCallback, $context);
36643681
$rightExprType = $rightResult->getScope()->getType($expr->right);
@@ -7848,4 +7865,18 @@ private function inferForLoopExpressions(For_ $stmt, Expr $lastCondExpr, Mutatin
78487865
return $bodyScope;
78497866
}
78507867

7868+
private function getBooleanExpressionDepth(Expr $expr, int $depth = 0): int
7869+
{
7870+
while (
7871+
$expr instanceof BinaryOp\BooleanOr
7872+
|| $expr instanceof BinaryOp\LogicalOr
7873+
|| $expr instanceof BinaryOp\BooleanAnd
7874+
|| $expr instanceof BinaryOp\LogicalAnd
7875+
) {
7876+
return $this->getBooleanExpressionDepth($expr->left, $depth + 1);
7877+
}
7878+
7879+
return $depth;
7880+
}
7881+
78517882
}

0 commit comments

Comments
 (0)