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

Allow limiting connected taint paths

This commit is contained in:
Brown 2020-05-25 23:28:11 -04:00
parent 043c4b2a98
commit 953be61cf2
16 changed files with 86 additions and 24 deletions

View File

@ -10,6 +10,7 @@
<xs:complexType name="PsalmType">
<xs:choice maxOccurs="unbounded">
<xs:element name="projectFiles" type="ProjectFilesType" minOccurs="1" maxOccurs="1" />
<xs:element name="taintAnalysis" type="TaintAnalysisType" minOccurs="0" maxOccurs="1" />
<xs:element name="fileExtensions" type="FileExtensionsType" minOccurs="0" maxOccurs="1" />
<xs:element name="mockClasses" type="MockClassesType" minOccurs="0" maxOccurs="1" />
<xs:element name="stubs" type="StubsType" minOccurs="0" maxOccurs="1" />
@ -79,6 +80,12 @@
</xs:choice>
</xs:complexType>
<xs:complexType name="TaintAnalysisType">
<xs:choice maxOccurs="unbounded">
<xs:element name="ignoreFiles" minOccurs="0" maxOccurs="1" type="IgnoreFilesType" />
</xs:choice>
</xs:complexType>
<xs:complexType name="NameAttributeType">
<xs:attribute name="name" type="xs:string" use="required" />
</xs:complexType>

View File

@ -40,6 +40,7 @@ use function preg_quote;
use function preg_replace;
use Psalm\Config\IssueHandler;
use Psalm\Config\ProjectFileFilter;
use Psalm\Config\TaintAnalysisFileFilter;
use Psalm\Exception\ConfigException;
use Psalm\Internal\Analyzer\ClassLikeAnalyzer;
use Psalm\Internal\Analyzer\FileAnalyzer;
@ -550,6 +551,11 @@ class Config
*/
public $max_string_length = 1000;
/**
* @var ProjectFileFilter|null
*/
protected $taint_analysis_ignored_files;
protected function __construct()
{
self::$instance = $this;
@ -894,6 +900,14 @@ class Config
$config->project_files = ProjectFileFilter::loadFromXMLElement($config_xml->projectFiles, $base_dir, true);
}
if (isset($config_xml->taintAnalysis->ignoreFiles)) {
$config->taint_analysis_ignored_files = TaintAnalysisFileFilter::loadFromXMLElement(
$config_xml->taintAnalysis->ignoreFiles,
$base_dir,
false
);
}
if (isset($config_xml->fileExtensions)) {
$config->file_extensions = [];
@ -1349,6 +1363,12 @@ class Config
return $this->project_files && $this->project_files->forbids($file_path);
}
public function trackTaintsInPath(string $file_path) : bool
{
return !$this->taint_analysis_ignored_files
|| $this->taint_analysis_ignored_files->allows($file_path);
}
public function getReportingLevelForIssue(CodeIssue $e) : string
{
$fqcn_parts = explode('\\', get_class($e));

View File

@ -0,0 +1,10 @@
<?php
namespace Psalm\Config;
use SimpleXMLElement;
use function stripos;
use function strpos;
class TaintAnalysisFileFilter extends FileFilter
{
}

View File

@ -34,7 +34,9 @@ class EchoAnalyzer
ExpressionAnalyzer::analyze($statements_analyzer, $expr, $context);
$context->inside_call = false;
if ($codebase->taint) {
if ($codebase->taint
&& $codebase->config->trackTaintsInPath($statements_analyzer->getFilePath())
) {
$expr_location = new CodeLocation($statements_analyzer->getSource(), $expr);
$call_location = new CodeLocation($statements_analyzer->getSource(), $stmt);

View File

@ -1074,7 +1074,7 @@ class PropertyAssignmentAnalyzer
) : void {
$codebase = $statements_analyzer->getCodebase();
if (!$codebase->taint) {
if (!$codebase->taint || !$codebase->config->trackTaintsInPath($statements_analyzer->getFilePath())) {
return;
}

View File

@ -941,7 +941,9 @@ class AssignmentAnalyzer
return $context->vars_in_scope[$var_id];
}
if ($codebase->taint) {
if ($codebase->taint
&& $codebase->config->trackTaintsInPath($statements_analyzer->getFilePath())
) {
if ($context->vars_in_scope[$var_id]->parent_nodes) {
$var_location = new CodeLocation($statements_analyzer->getSource(), $assign_var);
@ -1117,7 +1119,10 @@ class AssignmentAnalyzer
$context->vars_in_scope[$array_var_id] = $result_type;
$statements_analyzer->node_data->setType($stmt, clone $context->vars_in_scope[$array_var_id]);
if ($codebase->taint && $result_type) {
if ($codebase->taint
&& $result_type
&& $codebase->config->trackTaintsInPath($statements_analyzer->getFilePath())
) {
$stmt_left_type = $statements_analyzer->node_data->getType($stmt->var);
$stmt_right_type = $statements_analyzer->node_data->getType($stmt->expr);

View File

@ -106,7 +106,9 @@ class BinaryOpAnalyzer
$codebase = $statements_analyzer->getCodebase();
if ($codebase->taint) {
if ($codebase->taint
&& $codebase->config->trackTaintsInPath($statements_analyzer->getFilePath())
) {
$stmt_left_type = $statements_analyzer->node_data->getType($stmt->left);
$stmt_right_type = $statements_analyzer->node_data->getType($stmt->right);

View File

@ -1127,7 +1127,7 @@ class ArgumentAnalyzer
) : void {
$codebase = $statements_analyzer->getCodebase();
if (!$codebase->taint) {
if (!$codebase->taint || !$codebase->config->trackTaintsInPath($statements_analyzer->getFilePath())) {
return;
}

View File

@ -992,7 +992,12 @@ class FunctionCallAnalyzer extends CallAnalyzer
}
}
if ($codebase->taint && $function_storage && $function_storage->return_source_params && $stmt_type) {
if ($codebase->taint
&& $function_storage
&& $function_storage->return_source_params
&& $stmt_type
&& $codebase->config->trackTaintsInPath($statements_analyzer->getFilePath())
) {
foreach ($function_storage->return_source_params as $i) {
if (!isset($stmt->args[$i])) {
continue;

View File

@ -184,7 +184,10 @@ class MethodCallReturnTypeFetcher
$return_type_candidate = $method_name === '__tostring' ? Type::getString() : Type::getMixed();
}
if ($codebase->taint && $declaring_method_id) {
if ($codebase->taint
&& $declaring_method_id
&& $codebase->config->trackTaintsInPath($statements_analyzer->getFilePath())
) {
$method_storage = $codebase->methods->getStorage(
$declaring_method_id
);

View File

@ -1152,7 +1152,9 @@ class StaticCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
}
if ($return_type_candidate) {
if ($codebase->taint) {
if ($codebase->taint
&& $codebase->config->trackTaintsInPath($statements_analyzer->getFilePath())
) {
$code_location = new CodeLocation($statements_analyzer->getSource(), $stmt);
if ($method_storage && $method_storage->pure) {

View File

@ -25,7 +25,10 @@ class EvalAnalyzer
if ($expr_type) {
$codebase = $statements_analyzer->getCodebase();
if ($codebase->taint && $expr_type->parent_nodes) {
if ($codebase->taint
&& $expr_type->parent_nodes
&& $codebase->config->trackTaintsInPath($statements_analyzer->getFilePath())
) {
$arg_location = new CodeLocation($statements_analyzer->getSource(), $stmt->expr);
$eval_param_sink = Sink::getForMethodArgument(

View File

@ -1593,7 +1593,7 @@ class ArrayFetchAnalyzer
Type\Union $stmt_type,
string $array_var_id
) : void {
if ($codebase->taint) {
if ($codebase->taint && $codebase->config->trackTaintsInPath($statements_analyzer->getFilePath())) {
if ($array_var_id === '$_GET' || $array_var_id === '$_POST' || $array_var_id === '$_COOKIE') {
$taint_location = new CodeLocation($statements_analyzer->getSource(), $stmt);

View File

@ -1046,7 +1046,7 @@ class PropertyFetchAnalyzer
) : void {
$codebase = $statements_analyzer->getCodebase();
if ($codebase->taint) {
if ($codebase->taint && $codebase->config->trackTaintsInPath($statements_analyzer->getFilePath())) {
$code_location = new CodeLocation($statements_analyzer, $stmt->name);
$localized_property_node = new TaintNode(

View File

@ -263,7 +263,10 @@ class IncludeAnalyzer
if ($stmt_type && $statements_analyzer) {
$codebase = $statements_analyzer->getCodebase();
if ($codebase->taint && $stmt_type->parent_nodes) {
if ($codebase->taint
&& $stmt_type->parent_nodes
&& $codebase->config->trackTaintsInPath($statements_analyzer->getFilePath())
) {
$arg_location = new CodeLocation($statements_analyzer->getSource(), $stmt);
$include_param_sink = Sink::getForMethodArgument(

View File

@ -192,13 +192,17 @@ class ReturnAnalyzer
$source->getParentFQCLN()
);
self::handleTaints(
$codebase,
$stmt,
$cased_method_id,
$inferred_type,
$storage
);
if ($codebase->taint
&& $codebase->config->trackTaintsInPath($statements_analyzer->getFilePath())
) {
self::handleTaints(
$codebase,
$stmt,
$cased_method_id,
$inferred_type,
$storage
);
}
if ($storage instanceof \Psalm\Storage\MethodStorage && $context->self) {
$self_class = $context->self;
@ -493,10 +497,6 @@ class ReturnAnalyzer
$codebase->taint->addTaintNode($method_node);
if ($storage->specialize_call) {
//$codebase->taint->addSpecializedCall($cased_method_id);
}
if ($inferred_type->parent_nodes) {
foreach ($inferred_type->parent_nodes as $parent_node) {
$codebase->taint->addPath(