1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-22 05:41:20 +01:00

Allow Psalm to run in taint analysis mode without a config

This commit is contained in:
Matt Brown 2020-11-20 19:02:44 -05:00
parent 67478949c2
commit 23ab0f1ddb
6 changed files with 54 additions and 18 deletions

View File

@ -10,6 +10,7 @@ use Psalm\Config\IssueHandler;
use Psalm\Config\ProjectFileFilter;
use Psalm\Config\TaintAnalysisFileFilter;
use Psalm\Exception\ConfigException;
use Psalm\Exception\ConfigNotFoundException;
use Psalm\Internal\Analyzer\ClassLikeAnalyzer;
use Psalm\Internal\Analyzer\FileAnalyzer;
use Psalm\Internal\Analyzer\ProjectAnalyzer;
@ -651,17 +652,12 @@ class Config
* @throws ConfigException if a config path is not found
*
*/
public static function getConfigForPath(string $path, string $current_dir, string $output_format): Config
public static function getConfigForPath(string $path, string $current_dir): Config
{
$config_path = self::locateConfigFile($path);
if (!$config_path) {
if (in_array($output_format, [\Psalm\Report::TYPE_CONSOLE, \Psalm\Report::TYPE_PHP_STORM])) {
echo 'Could not locate a config XML file in path ' . $path
. '. Have you run \'psalm --init\' ?' . PHP_EOL;
exit(1);
}
throw new ConfigException('Config not found for path ' . $path);
throw new ConfigNotFoundException('Config not found for path ' . $path);
}
return self::loadFromXMLFile($config_path, $current_dir);
@ -678,7 +674,7 @@ class Config
$dir_path = realpath($path);
if ($dir_path === false) {
throw new ConfigException('Config not found for path ' . $path);
throw new ConfigNotFoundException('Config not found for path ' . $path);
}
if (!is_dir($dir_path)) {

View File

@ -87,10 +87,10 @@ class Creator
string $current_dir,
?string $suggested_dir,
string $vendor_dir
) : void {
) : \Psalm\Config {
$config_contents = self::getContents($current_dir, $suggested_dir, 1, $vendor_dir);
\Psalm\Config::loadFromXML($current_dir, $config_contents);
return \Psalm\Config::loadFromXML($current_dir, $config_contents);
}
/**

View File

@ -0,0 +1,6 @@
<?php
namespace Psalm\Exception;
class ConfigNotFoundException extends ConfigException
{
}

View File

@ -455,16 +455,41 @@ function initialiseConfig(
?string $path_to_config,
string $current_dir,
string $output_format,
?ClassLoader $first_autoloader
?ClassLoader $first_autoloader,
bool $create_if_non_existent = false
): Config {
try {
if ($path_to_config) {
$config = Config::loadFromXMLFile($path_to_config, $current_dir);
} else {
$config = Config::getConfigForPath($current_dir, $current_dir, $output_format);
try {
$config = Config::getConfigForPath($current_dir, $current_dir);
} catch (\Psalm\Exception\ConfigNotFoundException $e) {
if (!$create_if_non_existent) {
if (in_array($output_format, [\Psalm\Report::TYPE_CONSOLE, \Psalm\Report::TYPE_PHP_STORM])) {
fwrite(
STDERR,
'Could not locate a config XML file in path ' . $current_dir
. '. Have you run \'psalm --init\' ?' . PHP_EOL
);
exit(1);
}
throw $e;
}
$config = \Psalm\Config\Creator::createBareConfig(
$current_dir,
null,
\Psalm\getVendorDir($current_dir)
);
}
}
} catch (\Psalm\Exception\ConfigException $e) {
fwrite(STDERR, $e->getMessage() . PHP_EOL);
fwrite(
STDERR,
$e->getMessage() . PHP_EOL
);
exit(1);
}

View File

@ -278,6 +278,9 @@ $first_autoloader = $include_collector->runAndCollect(
}
);
$run_taint_analysis = (isset($options['track-tainted-input'])
|| isset($options['security-analysis'])
|| isset($options['taint-analysis']));
if (array_key_exists('v', $options)) {
echo 'Psalm ' . PSALM_VERSION . PHP_EOL;
@ -353,7 +356,7 @@ if (isset($options['i'])) {
exit('Config file created successfully. Please re-run psalm.' . PHP_EOL);
}
} else {
$config = initialiseConfig($path_to_config, $current_dir, $output_format, $first_autoloader);
$config = initialiseConfig($path_to_config, $current_dir, $output_format, $first_autoloader, $run_taint_analysis);
if (isset($options['error-level'])
&& is_numeric($options['error-level'])
@ -655,10 +658,7 @@ if ($config->find_unused_variables || $find_unused_variables) {
$project_analyzer->getCodebase()->reportUnusedVariables();
}
if ($config->run_taint_analysis || (isset($options['track-tainted-input'])
|| isset($options['security-analysis'])
|| isset($options['taint-analysis']))
) {
if ($config->run_taint_analysis || $run_taint_analysis) {
$is_diff = false;
$project_analyzer->trackTaintedInputs();
}

View File

@ -160,6 +160,15 @@ class PsalmEndToEndTest extends TestCase
$this->assertSame(1, $result['CODE']);
}
public function testTaintingWithoutInit(): void
{
$result = $this->runPsalm(['--taint-analysis'], self::$tmpDir, true);
$this->assertStringContainsString('TaintedHtml', $result['STDOUT']);
$this->assertStringContainsString('1 errors', $result['STDOUT']);
$this->assertSame(1, $result['CODE']);
}
public function testLegacyConfigWithoutresolveFromConfigFile(): void
{
$this->runPsalmInit(1);