mirror of
https://github.com/danog/psalm.git
synced 2024-12-13 17:57:37 +01:00
Reduce size of data flow graph when analysing array assignments
This commit is contained in:
parent
4cb8e86737
commit
e27cbfba57
@ -792,17 +792,33 @@ class ArrayAssignmentAnalyzer
|
|||||||
&& ($statements_analyzer->data_flow_graph instanceof VariableUseGraph
|
&& ($statements_analyzer->data_flow_graph instanceof VariableUseGraph
|
||||||
|| !\in_array('TaintedInput', $statements_analyzer->getSuppressedIssues()))
|
|| !\in_array('TaintedInput', $statements_analyzer->getSuppressedIssues()))
|
||||||
) {
|
) {
|
||||||
if (!$stmt_type->parent_nodes) {
|
$var_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $expr->var);
|
||||||
$var_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $expr->var);
|
|
||||||
|
|
||||||
$parent_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment(
|
$parent_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment(
|
||||||
$var_var_id ?: 'assignment',
|
$var_var_id ?: 'assignment',
|
||||||
$var_location
|
$var_location
|
||||||
|
);
|
||||||
|
|
||||||
|
$statements_analyzer->data_flow_graph->addNode($parent_node);
|
||||||
|
|
||||||
|
$old_parent_nodes = $stmt_type->parent_nodes;
|
||||||
|
|
||||||
|
$stmt_type->parent_nodes = [$parent_node->id => $parent_node];
|
||||||
|
|
||||||
|
foreach ($old_parent_nodes as $old_parent_node) {
|
||||||
|
$statements_analyzer->data_flow_graph->addPath(
|
||||||
|
$old_parent_node,
|
||||||
|
$parent_node,
|
||||||
|
'='
|
||||||
);
|
);
|
||||||
|
|
||||||
$statements_analyzer->data_flow_graph->addNode($parent_node);
|
if ($stmt_type->by_ref) {
|
||||||
|
$statements_analyzer->data_flow_graph->addPath(
|
||||||
$stmt_type->parent_nodes = [$parent_node->id => $parent_node];
|
$parent_node,
|
||||||
|
$old_parent_node,
|
||||||
|
'='
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($stmt_type->parent_nodes as $parent_node) {
|
foreach ($stmt_type->parent_nodes as $parent_node) {
|
||||||
|
@ -1235,13 +1235,16 @@ class InstancePropertyAssignmentAnalyzer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$code_location = new CodeLocation($statements_analyzer->getSource(), $stmt);
|
$var_property_id = ExpressionIdentifier::getArrayVarId(
|
||||||
|
$stmt,
|
||||||
|
null,
|
||||||
|
$statements_analyzer
|
||||||
|
);
|
||||||
|
|
||||||
$localized_property_node = new DataFlowNode(
|
$localized_property_node = DataFlowNode::getForAssignment(
|
||||||
$property_id . '-' . $code_location->file_name . ':' . $code_location->raw_file_start,
|
$var_property_id
|
||||||
$property_id,
|
?: $property_id . '-' . $property_location->file_name . ':' . $property_location->raw_file_start,
|
||||||
$code_location,
|
$property_location
|
||||||
null
|
|
||||||
);
|
);
|
||||||
|
|
||||||
$data_flow_graph->addNode($localized_property_node);
|
$data_flow_graph->addNode($localized_property_node);
|
||||||
|
@ -1267,7 +1267,7 @@ class ArgumentAnalyzer
|
|||||||
$function_param->location
|
$function_param->location
|
||||||
);
|
);
|
||||||
|
|
||||||
if (strpos($cased_method_id, '::')) {
|
if ($statements_analyzer->data_flow_graph instanceof TaintFlowGraph && strpos($cased_method_id, '::')) {
|
||||||
[$fq_classlike_name, $cased_method_name] = explode('::', $cased_method_id);
|
[$fq_classlike_name, $cased_method_name] = explode('::', $cased_method_id);
|
||||||
$method_name = strtolower($cased_method_name);
|
$method_name = strtolower($cased_method_name);
|
||||||
$class_storage = $codebase->classlike_storage_provider->get($fq_classlike_name);
|
$class_storage = $codebase->classlike_storage_provider->get($fq_classlike_name);
|
||||||
|
@ -1700,6 +1700,8 @@ class FunctionCallAnalyzer extends CallAnalyzer
|
|||||||
])
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($function_name->parts === ['method_exists']) {
|
if ($function_name->parts === ['method_exists']) {
|
||||||
@ -1714,7 +1716,11 @@ class FunctionCallAnalyzer extends CallAnalyzer
|
|||||||
} else {
|
} else {
|
||||||
$context->check_methods = false;
|
$context->check_methods = false;
|
||||||
}
|
}
|
||||||
} elseif ($function_name->parts === ['class_exists']) {
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($function_name->parts === ['class_exists']) {
|
||||||
if ($first_arg) {
|
if ($first_arg) {
|
||||||
if ($first_arg->value instanceof PhpParser\Node\Scalar\String_) {
|
if ($first_arg->value instanceof PhpParser\Node\Scalar\String_) {
|
||||||
if (!$codebase->classlikes->classExists($first_arg->value->value)) {
|
if (!$codebase->classlikes->classExists($first_arg->value->value)) {
|
||||||
@ -1732,7 +1738,11 @@ class FunctionCallAnalyzer extends CallAnalyzer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($function_name->parts === ['interface_exists']) {
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($function_name->parts === ['interface_exists']) {
|
||||||
if ($first_arg) {
|
if ($first_arg) {
|
||||||
if ($first_arg->value instanceof PhpParser\Node\Scalar\String_) {
|
if ($first_arg->value instanceof PhpParser\Node\Scalar\String_) {
|
||||||
$context->phantom_classes[strtolower($first_arg->value->value)] = true;
|
$context->phantom_classes[strtolower($first_arg->value->value)] = true;
|
||||||
@ -1748,13 +1758,21 @@ class FunctionCallAnalyzer extends CallAnalyzer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($function_name->parts === ['file_exists'] && $first_arg) {
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($function_name->parts === ['file_exists'] && $first_arg) {
|
||||||
$var_id = ExpressionIdentifier::getArrayVarId($first_arg->value, null);
|
$var_id = ExpressionIdentifier::getArrayVarId($first_arg->value, null);
|
||||||
|
|
||||||
if ($var_id) {
|
if ($var_id) {
|
||||||
$context->phantom_files[$var_id] = true;
|
$context->phantom_files[$var_id] = true;
|
||||||
}
|
}
|
||||||
} elseif ($function_name->parts === ['extension_loaded']) {
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($function_name->parts === ['extension_loaded']) {
|
||||||
if ($first_arg
|
if ($first_arg
|
||||||
&& $first_arg->value instanceof PhpParser\Node\Scalar\String_
|
&& $first_arg->value instanceof PhpParser\Node\Scalar\String_
|
||||||
) {
|
) {
|
||||||
@ -1764,14 +1782,27 @@ class FunctionCallAnalyzer extends CallAnalyzer
|
|||||||
$context->check_classes = false;
|
$context->check_classes = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($function_name->parts === ['function_exists']) {
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($function_name->parts === ['function_exists']) {
|
||||||
$context->check_functions = false;
|
$context->check_functions = false;
|
||||||
} elseif ($function_name->parts === ['is_callable']) {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($function_name->parts === ['is_callable']) {
|
||||||
$context->check_methods = false;
|
$context->check_methods = false;
|
||||||
$context->check_functions = false;
|
$context->check_functions = false;
|
||||||
} elseif ($function_name->parts === ['defined']) {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($function_name->parts === ['defined']) {
|
||||||
$context->check_consts = false;
|
$context->check_consts = false;
|
||||||
} elseif ($function_name->parts === ['extract']) {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($function_name->parts === ['extract']) {
|
||||||
$context->check_variables = false;
|
$context->check_variables = false;
|
||||||
|
|
||||||
foreach ($context->vars_in_scope as $var_id => $_) {
|
foreach ($context->vars_in_scope as $var_id => $_) {
|
||||||
@ -1786,7 +1817,11 @@ class FunctionCallAnalyzer extends CallAnalyzer
|
|||||||
$context->assigned_var_ids[$var_id] = (int) $stmt->getAttribute('startFilePos');
|
$context->assigned_var_ids[$var_id] = (int) $stmt->getAttribute('startFilePos');
|
||||||
$context->possibly_assigned_var_ids[$var_id] = true;
|
$context->possibly_assigned_var_ids[$var_id] = true;
|
||||||
}
|
}
|
||||||
} elseif ($function_name->parts === ['compact']) {
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($function_name->parts === ['compact']) {
|
||||||
$all_args_string_literals = true;
|
$all_args_string_literals = true;
|
||||||
$new_items = [];
|
$new_items = [];
|
||||||
|
|
||||||
@ -1823,7 +1858,11 @@ class FunctionCallAnalyzer extends CallAnalyzer
|
|||||||
$statements_analyzer->node_data->setType($stmt, $arr_type);
|
$statements_analyzer->node_data->setType($stmt, $arr_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($function_name->parts === ['func_get_args']) {
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($function_name->parts === ['func_get_args']) {
|
||||||
$source = $statements_analyzer->getSource();
|
$source = $statements_analyzer->getSource();
|
||||||
|
|
||||||
if ($statements_analyzer->data_flow_graph
|
if ($statements_analyzer->data_flow_graph
|
||||||
@ -1839,7 +1878,11 @@ class FunctionCallAnalyzer extends CallAnalyzer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif (strtolower($function_name->parts[0]) === 'var_dump'
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strtolower($function_name->parts[0]) === 'var_dump'
|
||||||
|| strtolower($function_name->parts[0]) === 'shell_exec') {
|
|| strtolower($function_name->parts[0]) === 'shell_exec') {
|
||||||
if (IssueBuffer::accepts(
|
if (IssueBuffer::accepts(
|
||||||
new ForbiddenCode(
|
new ForbiddenCode(
|
||||||
@ -1850,7 +1893,9 @@ class FunctionCallAnalyzer extends CallAnalyzer
|
|||||||
)) {
|
)) {
|
||||||
// continue
|
// continue
|
||||||
}
|
}
|
||||||
} elseif (isset($codebase->config->forbidden_functions[strtolower((string) $function_name)])) {
|
}
|
||||||
|
|
||||||
|
if (isset($codebase->config->forbidden_functions[strtolower((string) $function_name)])) {
|
||||||
if (IssueBuffer::accepts(
|
if (IssueBuffer::accepts(
|
||||||
new ForbiddenCode(
|
new ForbiddenCode(
|
||||||
'You have forbidden the use of ' . $function_name,
|
'You have forbidden the use of ' . $function_name,
|
||||||
@ -1860,7 +1905,11 @@ class FunctionCallAnalyzer extends CallAnalyzer
|
|||||||
)) {
|
)) {
|
||||||
// continue
|
// continue
|
||||||
}
|
}
|
||||||
} elseif ($function_name->parts === ['define']) {
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($function_name->parts === ['define']) {
|
||||||
if ($first_arg) {
|
if ($first_arg) {
|
||||||
$fq_const_name = ConstFetchAnalyzer::getConstName(
|
$fq_const_name = ConstFetchAnalyzer::getConstName(
|
||||||
$first_arg->value,
|
$first_arg->value,
|
||||||
@ -1886,7 +1935,11 @@ class FunctionCallAnalyzer extends CallAnalyzer
|
|||||||
} else {
|
} else {
|
||||||
$context->check_consts = false;
|
$context->check_consts = false;
|
||||||
}
|
}
|
||||||
} elseif ($function_name->parts === ['constant']) {
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($function_name->parts === ['constant']) {
|
||||||
if ($first_arg) {
|
if ($first_arg) {
|
||||||
$fq_const_name = ConstFetchAnalyzer::getConstName(
|
$fq_const_name = ConstFetchAnalyzer::getConstName(
|
||||||
$first_arg->value,
|
$first_arg->value,
|
||||||
@ -1910,7 +1963,9 @@ class FunctionCallAnalyzer extends CallAnalyzer
|
|||||||
} else {
|
} else {
|
||||||
$context->check_consts = false;
|
$context->check_consts = false;
|
||||||
}
|
}
|
||||||
} elseif ($first_arg
|
}
|
||||||
|
|
||||||
|
if ($first_arg
|
||||||
&& $function_id
|
&& $function_id
|
||||||
&& strpos($function_id, 'is_') === 0
|
&& strpos($function_id, 'is_') === 0
|
||||||
&& $function_id !== 'is_a'
|
&& $function_id !== 'is_a'
|
||||||
@ -1951,7 +2006,11 @@ class FunctionCallAnalyzer extends CallAnalyzer
|
|||||||
new CodeLocation($statements_analyzer->getSource(), $stmt)
|
new CodeLocation($statements_analyzer->getSource(), $stmt)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} elseif ($first_arg && $function_id === 'strtolower') {
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($first_arg && $function_id === 'strtolower') {
|
||||||
$first_arg_type = $statements_analyzer->node_data->getType($first_arg->value);
|
$first_arg_type = $statements_analyzer->node_data->getType($first_arg->value);
|
||||||
|
|
||||||
if ($first_arg_type
|
if ($first_arg_type
|
||||||
|
@ -840,13 +840,16 @@ class AtomicPropertyFetchAnalyzer
|
|||||||
$type->parent_nodes = [$property_node->id => $property_node];
|
$type->parent_nodes = [$property_node->id => $property_node];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$code_location = new CodeLocation($statements_analyzer, $stmt->name);
|
$var_property_id = ExpressionIdentifier::getArrayVarId(
|
||||||
|
$stmt,
|
||||||
|
null,
|
||||||
|
$statements_analyzer
|
||||||
|
);
|
||||||
|
|
||||||
$localized_property_node = new DataFlowNode(
|
$localized_property_node = DataFlowNode::getForAssignment(
|
||||||
$property_id . '-' . $code_location->file_name . ':' . $code_location->raw_file_start,
|
$var_property_id
|
||||||
$property_id,
|
?: $property_id . '-' . $property_location->file_name . ':' . $property_location->raw_file_start,
|
||||||
$code_location,
|
$property_location
|
||||||
null
|
|
||||||
);
|
);
|
||||||
|
|
||||||
$data_flow_graph->addNode($localized_property_node);
|
$data_flow_graph->addNode($localized_property_node);
|
||||||
@ -866,7 +869,7 @@ class AtomicPropertyFetchAnalyzer
|
|||||||
$data_flow_graph->addPath($property_node, $localized_property_node, 'property-fetch');
|
$data_flow_graph->addPath($property_node, $localized_property_node, 'property-fetch');
|
||||||
}
|
}
|
||||||
|
|
||||||
$type->parent_nodes[$localized_property_node->id] = $localized_property_node;
|
$type->parent_nodes = [$localized_property_node->id => $localized_property_node];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user