1
0
mirror of https://github.com/danog/psalm.git synced 2024-12-11 08:49:52 +01:00

Reduce size of data flow graph when analysing array assignments

This commit is contained in:
Matt Brown 2020-11-09 22:44:36 -05:00
parent 4cb8e86737
commit e27cbfba57
5 changed files with 119 additions and 38 deletions

View File

@ -792,17 +792,33 @@ class ArrayAssignmentAnalyzer
&& ($statements_analyzer->data_flow_graph instanceof VariableUseGraph
|| !\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(
$var_var_id ?: 'assignment',
$var_location
$parent_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment(
$var_var_id ?: 'assignment',
$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);
$stmt_type->parent_nodes = [$parent_node->id => $parent_node];
if ($stmt_type->by_ref) {
$statements_analyzer->data_flow_graph->addPath(
$parent_node,
$old_parent_node,
'='
);
}
}
foreach ($stmt_type->parent_nodes as $parent_node) {

View File

@ -1235,13 +1235,16 @@ class InstancePropertyAssignmentAnalyzer
return;
}
$code_location = new CodeLocation($statements_analyzer->getSource(), $stmt);
$var_property_id = ExpressionIdentifier::getArrayVarId(
$stmt,
null,
$statements_analyzer
);
$localized_property_node = new DataFlowNode(
$property_id . '-' . $code_location->file_name . ':' . $code_location->raw_file_start,
$property_id,
$code_location,
null
$localized_property_node = DataFlowNode::getForAssignment(
$var_property_id
?: $property_id . '-' . $property_location->file_name . ':' . $property_location->raw_file_start,
$property_location
);
$data_flow_graph->addNode($localized_property_node);

View File

@ -1267,7 +1267,7 @@ class ArgumentAnalyzer
$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);
$method_name = strtolower($cased_method_name);
$class_storage = $codebase->classlike_storage_provider->get($fq_classlike_name);

View File

@ -1700,6 +1700,8 @@ class FunctionCallAnalyzer extends CallAnalyzer
])
);
}
return;
}
if ($function_name->parts === ['method_exists']) {
@ -1714,7 +1716,11 @@ class FunctionCallAnalyzer extends CallAnalyzer
} else {
$context->check_methods = false;
}
} elseif ($function_name->parts === ['class_exists']) {
return;
}
if ($function_name->parts === ['class_exists']) {
if ($first_arg) {
if ($first_arg->value instanceof PhpParser\Node\Scalar\String_) {
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->value instanceof PhpParser\Node\Scalar\String_) {
$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);
if ($var_id) {
$context->phantom_files[$var_id] = true;
}
} elseif ($function_name->parts === ['extension_loaded']) {
return;
}
if ($function_name->parts === ['extension_loaded']) {
if ($first_arg
&& $first_arg->value instanceof PhpParser\Node\Scalar\String_
) {
@ -1764,14 +1782,27 @@ class FunctionCallAnalyzer extends CallAnalyzer
$context->check_classes = false;
}
}
} elseif ($function_name->parts === ['function_exists']) {
return;
}
if ($function_name->parts === ['function_exists']) {
$context->check_functions = false;
} elseif ($function_name->parts === ['is_callable']) {
return;
}
if ($function_name->parts === ['is_callable']) {
$context->check_methods = false;
$context->check_functions = false;
} elseif ($function_name->parts === ['defined']) {
return;
}
if ($function_name->parts === ['defined']) {
$context->check_consts = false;
} elseif ($function_name->parts === ['extract']) {
return;
}
if ($function_name->parts === ['extract']) {
$context->check_variables = false;
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->possibly_assigned_var_ids[$var_id] = true;
}
} elseif ($function_name->parts === ['compact']) {
return;
}
if ($function_name->parts === ['compact']) {
$all_args_string_literals = true;
$new_items = [];
@ -1823,7 +1858,11 @@ class FunctionCallAnalyzer extends CallAnalyzer
$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();
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') {
if (IssueBuffer::accepts(
new ForbiddenCode(
@ -1850,7 +1893,9 @@ class FunctionCallAnalyzer extends CallAnalyzer
)) {
// continue
}
} elseif (isset($codebase->config->forbidden_functions[strtolower((string) $function_name)])) {
}
if (isset($codebase->config->forbidden_functions[strtolower((string) $function_name)])) {
if (IssueBuffer::accepts(
new ForbiddenCode(
'You have forbidden the use of ' . $function_name,
@ -1860,7 +1905,11 @@ class FunctionCallAnalyzer extends CallAnalyzer
)) {
// continue
}
} elseif ($function_name->parts === ['define']) {
return;
}
if ($function_name->parts === ['define']) {
if ($first_arg) {
$fq_const_name = ConstFetchAnalyzer::getConstName(
$first_arg->value,
@ -1886,7 +1935,11 @@ class FunctionCallAnalyzer extends CallAnalyzer
} else {
$context->check_consts = false;
}
} elseif ($function_name->parts === ['constant']) {
return;
}
if ($function_name->parts === ['constant']) {
if ($first_arg) {
$fq_const_name = ConstFetchAnalyzer::getConstName(
$first_arg->value,
@ -1910,7 +1963,9 @@ class FunctionCallAnalyzer extends CallAnalyzer
} else {
$context->check_consts = false;
}
} elseif ($first_arg
}
if ($first_arg
&& $function_id
&& strpos($function_id, 'is_') === 0
&& $function_id !== 'is_a'
@ -1951,7 +2006,11 @@ class FunctionCallAnalyzer extends CallAnalyzer
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);
if ($first_arg_type

View File

@ -840,13 +840,16 @@ class AtomicPropertyFetchAnalyzer
$type->parent_nodes = [$property_node->id => $property_node];
}
} else {
$code_location = new CodeLocation($statements_analyzer, $stmt->name);
$var_property_id = ExpressionIdentifier::getArrayVarId(
$stmt,
null,
$statements_analyzer
);
$localized_property_node = new DataFlowNode(
$property_id . '-' . $code_location->file_name . ':' . $code_location->raw_file_start,
$property_id,
$code_location,
null
$localized_property_node = DataFlowNode::getForAssignment(
$var_property_id
?: $property_id . '-' . $property_location->file_name . ':' . $property_location->raw_file_start,
$property_location
);
$data_flow_graph->addNode($localized_property_node);
@ -866,7 +869,7 @@ class AtomicPropertyFetchAnalyzer
$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];
}
}