1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-21 21:31:13 +01:00

Fix #4266 - prevent OOM when analysing closure unioned with invokable class

This commit is contained in:
Matt Brown 2020-10-02 00:47:42 -04:00
parent 6ad5e1c013
commit c9e47450a7
3 changed files with 47 additions and 3 deletions

View File

@ -695,7 +695,8 @@ class FunctionCallAnalyzer extends CallAnalyzer
$stmt,
$real_stmt,
$function_name,
$context
$context,
$var_type_part
);
}
}
@ -746,7 +747,8 @@ class FunctionCallAnalyzer extends CallAnalyzer
PhpParser\Node\Expr\FuncCall $stmt,
PhpParser\Node\Expr\FuncCall $real_stmt,
PhpParser\Node\Expr $function_name,
Context $context
Context $context,
Type\Atomic $atomic_type
) : void {
$old_data_provider = $statements_analyzer->node_data;
@ -772,6 +774,8 @@ class FunctionCallAnalyzer extends CallAnalyzer
$statements_analyzer->addSuppressedIssues(['PossiblyInvalidMethodCall']);
}
$statements_analyzer->node_data->setType($function_name, new Type\Union([$atomic_type]));
\Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze(
$statements_analyzer,
$fake_method_call,

View File

@ -45,7 +45,15 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
$was_inside_use = $context->inside_use;
$context->inside_use = true;
if (ExpressionAnalyzer::analyze($statements_analyzer, $stmt->var, $context) === false) {
$existing_stmt_var_type = null;
if (!$real_method_call) {
$existing_stmt_var_type = $statements_analyzer->node_data->getType($stmt->var);
}
if ($existing_stmt_var_type) {
$statements_analyzer->node_data->setType($stmt->var, $existing_stmt_var_type);
} elseif (ExpressionAnalyzer::analyze($statements_analyzer, $stmt->var, $context) === false) {
return false;
}

View File

@ -575,6 +575,38 @@ class ReturnTypeManipulationTest extends FileManipulationTest
false,
true,
],
'dontOOM' => [
'<?php
class FC {
public function __invoke() : void {}
}
function foo(): string {
if (rand(0, 1)) {
$cb = new FC();
} else {
$cb = function() {};
}
$cb();
}',
'<?php
class FC {
public function __invoke() : void {}
}
function foo(): string {
if (rand(0, 1)) {
$cb = new FC();
} else {
$cb = function() {};
}
$cb();
}',
'7.3',
['InvalidReturnType'],
false,
true,
],
];
}
}