diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php index 309d1b8d537..2b7b8b607ae 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php @@ -32,7 +32,6 @@ use Psalm\Type\Union; use UnexpectedValueException; -use function array_merge; use function in_array; use function strlen; @@ -171,14 +170,6 @@ public static function analyze( $removed_taints = $codebase->config->eventDispatcher->dispatchRemoveTaints($event); if ($stmt_left_type && $stmt_left_type->parent_nodes) { - // numeric types can't be tainted html or has_quotes, neither can bool - if ($statements_analyzer->data_flow_graph instanceof TaintFlowGraph - && $stmt_left_type->isSingle() - && ($stmt_left_type->isInt() || $stmt_left_type->isFloat() || $stmt_left_type->isBool()) - ) { - $removed_taints = array_merge($removed_taints, array('html', 'has_quotes')); - } - foreach ($stmt_left_type->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath( $parent_node, @@ -191,14 +182,6 @@ public static function analyze( } if ($stmt_right_type && $stmt_right_type->parent_nodes) { - // numeric types can't be tainted html or has_quotes, neither can bool - if ($statements_analyzer->data_flow_graph instanceof TaintFlowGraph - && $stmt_right_type->isSingle() - && ($stmt_right_type->isInt() || $stmt_right_type->isFloat() || $stmt_right_type->isBool()) - ) { - $removed_taints = array_merge($removed_taints, array('html', 'has_quotes')); - } - foreach ($stmt_right_type->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath( $parent_node, diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php index ec72396f28d..262935153d6 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php @@ -60,7 +60,6 @@ use Psalm\Type\Atomic\TNamedObject; use Psalm\Type\Union; -use function array_merge; use function count; use function explode; use function implode; @@ -1529,19 +1528,19 @@ private static function processTaintedness( return; } - $event = new AddRemoveTaintsEvent($expr, $context, $statements_analyzer, $codebase); - - $added_taints = $codebase->config->eventDispatcher->dispatchAddTaints($event); - $removed_taints = $codebase->config->eventDispatcher->dispatchRemoveTaints($event); - - // numeric types can't be tainted html or has_quotes, neither can bool + // numeric types can't be tainted, neither can bool if ($statements_analyzer->data_flow_graph instanceof TaintFlowGraph && $input_type->isSingle() && ($input_type->isInt() || $input_type->isFloat() || $input_type->isBool()) ) { - $removed_taints = array_merge($removed_taints, array('html', 'has_quotes')); + return; } + $event = new AddRemoveTaintsEvent($expr, $context, $statements_analyzer, $codebase); + + $added_taints = $codebase->config->eventDispatcher->dispatchAddTaints($event); + $removed_taints = $codebase->config->eventDispatcher->dispatchRemoveTaints($event); + if ($function_param->type && $function_param->type->isString() && !$input_type->isString()) { $input_type = CastAnalyzer::castStringAttempt( $statements_analyzer, diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/CastAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/CastAnalyzer.php index bbcb0e3105a..5832bb159fe 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/CastAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/CastAnalyzer.php @@ -142,9 +142,14 @@ public static function analyze( } } - $type = new Union([new TBool()], [ - 'parent_nodes' => $maybe_type->parent_nodes ?? [], - ]); + if ($statements_analyzer->data_flow_graph instanceof VariableUseGraph + ) { + $type = new Union([new TBool()], [ + 'parent_nodes' => $maybe_type->parent_nodes ?? [], + ]); + } else { + $type = Type::getBool(); + } $statements_analyzer->node_data->setType($stmt, $type); @@ -323,7 +328,11 @@ public static function castIntAttempt( $atomic_types = $stmt_type->getAtomicTypes(); - $parent_nodes = $stmt_type->parent_nodes; + $parent_nodes = []; + + if ($statements_analyzer->data_flow_graph instanceof VariableUseGraph) { + $parent_nodes = $stmt_type->parent_nodes; + } while ($atomic_types) { $atomic_type = array_pop($atomic_types); @@ -509,7 +518,11 @@ public static function castFloatAttempt( $atomic_types = $stmt_type->getAtomicTypes(); - $parent_nodes = $stmt_type->parent_nodes; + $parent_nodes = []; + + if ($statements_analyzer->data_flow_graph instanceof VariableUseGraph) { + $parent_nodes = $stmt_type->parent_nodes; + } while ($atomic_types) { $atomic_type = array_pop($atomic_types); diff --git a/tests/TaintTest.php b/tests/TaintTest.php index 7a947ca8127..6439b366c1d 100644 --- a/tests/TaintTest.php +++ b/tests/TaintTest.php @@ -177,6 +177,23 @@ public function deleteUser(PDO $pdo, string $userId) : void { } }', ], + 'untaintedInputAfterIntCast' => [ + 'code' => 'getUserId(); + } + + public function deleteUser(PDO $pdo) : void { + $userId = $this->getAppendedUserId(); + $pdo->exec("delete from users where user_id = " . $userId); + } + }', + ], 'specializedCoreFunctionCall' => [ 'code' => ' [ + 'code' => ' [ 'code' => ' 'TaintedSql', ], - 'taintedInputAfterIntCast' => [ - 'code' => 'getUserId(); - } - - public function deleteUser(PDO $pdo) : void { - $userId = $this->getAppendedUserId(); - $pdo->exec("delete from users where user_id = " . $userId); - } - }', - 'error_message' => 'TaintedSql', - ], - 'TaintForIntTypeCastUsingAnnotatedSink' => [ - 'code' => ' 'TaintedSql', - ], 'taintedInputFromReturnTypeWithBranch' => [ 'code' => '