From f63a40f69b182e0b92a8d37ad0e2a3f02902c613 Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Fri, 2 Oct 2020 00:47:42 -0400 Subject: [PATCH] Fix #4266 - prevent OOM when analysing closure unioned with invokable class --- .../Expression/Call/FunctionCallAnalyzer.php | 8 +++-- .../Expression/Call/MethodCallAnalyzer.php | 10 +++++- .../ReturnTypeManipulationTest.php | 32 +++++++++++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php index 8327050011f..90c2243b17f 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php @@ -695,7 +695,8 @@ private static function getAnalyzeNamedExpression( $stmt, $real_stmt, $function_name, - $context + $context, + $var_type_part ); } } @@ -746,7 +747,8 @@ private static function analyzeInvokeCall( 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 @@ private static function analyzeInvokeCall( $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, diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php index 9e179641929..767f9e472f4 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php @@ -47,7 +47,15 @@ public static function analyze( $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; } diff --git a/tests/FileManipulation/ReturnTypeManipulationTest.php b/tests/FileManipulation/ReturnTypeManipulationTest.php index d9fcb7b0bde..488dfc02d23 100644 --- a/tests/FileManipulation/ReturnTypeManipulationTest.php +++ b/tests/FileManipulation/ReturnTypeManipulationTest.php @@ -575,6 +575,38 @@ public function getMe() { false, true, ], + 'dontOOM' => [ + '