From 94395f18a4e2f97c1df5b9063866eaf280bdcc35 Mon Sep 17 00:00:00 2001 From: Bruce Weirdan Date: Wed, 5 Jan 2022 19:32:43 +0200 Subject: [PATCH] Applied JsonThrowOnErrorRector --- src/Psalm/Config.php | 10 +++++++++- src/Psalm/Config/Creator.php | 17 +++++++++++++++-- src/Psalm/Context.php | 4 +++- .../Statements/Expression/AssertionFinder.php | 4 +++- src/Psalm/Internal/Clause.php | 4 +++- src/Psalm/Internal/Cli/Psalm.php | 6 +++++- src/Psalm/Internal/CliUtils.php | 13 ++++++++++++- src/Psalm/Internal/Codebase/TaintFlowGraph.php | 6 ++++-- .../ExecutionEnvironment/BuildInfoCollector.php | 4 +++- .../PluginManager/PluginListFactory.php | 4 +++- .../Internal/Provider/ParserCacheProvider.php | 13 +++++++++++-- src/Psalm/Plugin/Shepherd.php | 3 ++- src/Psalm/Type/Reconciler.php | 6 ++++-- tests/ComposerLockTest.php | 4 +++- tests/ReportOutputTest.php | 10 ++++++---- 15 files changed, 86 insertions(+), 22 deletions(-) diff --git a/src/Psalm/Config.php b/src/Psalm/Config.php index 4e2978649cd..6f679023e83 100644 --- a/src/Psalm/Config.php +++ b/src/Psalm/Config.php @@ -9,6 +9,7 @@ use DOMDocument; use DomElement; use InvalidArgumentException; +use JsonException; use LogicException; use OutOfBoundsException; use Psalm\CodeLocation\Raw; @@ -102,6 +103,7 @@ use const DIRECTORY_SEPARATOR; use const E_USER_ERROR; use const GLOB_NOSORT; +use const JSON_THROW_ON_ERROR; use const LIBXML_ERR_ERROR; use const LIBXML_ERR_FATAL; use const LIBXML_NONET; @@ -2256,7 +2258,13 @@ public function getPHPVersionFromComposerJson(): ?string $composer_json_path = Composer::getJsonFilePath($this->base_dir); if (file_exists($composer_json_path)) { - if (!$composer_json = json_decode(file_get_contents($composer_json_path), true)) { + try { + $composer_json = json_decode(file_get_contents($composer_json_path), true, 512, JSON_THROW_ON_ERROR); + } catch (JsonException $e) { + $composer_json = null; + } + + if (!$composer_json) { throw new UnexpectedValueException('Invalid composer.json at ' . $composer_json_path); } $php_version = $composer_json['require']['php'] ?? null; diff --git a/src/Psalm/Config/Creator.php b/src/Psalm/Config/Creator.php index 36760726e1c..bf837b666e4 100644 --- a/src/Psalm/Config/Creator.php +++ b/src/Psalm/Config/Creator.php @@ -2,6 +2,7 @@ namespace Psalm\Config; +use JsonException; use Psalm\Config; use Psalm\Exception\ConfigCreationException; use Psalm\Internal\Analyzer\IssueData; @@ -32,6 +33,7 @@ use const DIRECTORY_SEPARATOR; use const GLOB_NOSORT; +use const JSON_THROW_ON_ERROR; class Creator { @@ -184,8 +186,19 @@ public static function getPaths(string $current_dir, ?string $suggested_dir): ar 'Problem during config autodiscovery - could not find composer.json during initialization.' ); } - - if (!$composer_json = json_decode(file_get_contents($composer_json_location), true)) { + try { + $composer_json = json_decode( + file_get_contents($composer_json_location), + true, + 512, + JSON_THROW_ON_ERROR + ); + } catch (JsonException $e) { + throw new ConfigCreationException( + 'Invalid composer.json at ' . $composer_json_location . ': ' . $e->getMessage() + ); + } + if (!$composer_json) { throw new ConfigCreationException('Invalid composer.json at ' . $composer_json_location); } diff --git a/src/Psalm/Context.php b/src/Psalm/Context.php index 3b9470d6f64..78b116ba034 100644 --- a/src/Psalm/Context.php +++ b/src/Psalm/Context.php @@ -27,6 +27,8 @@ use function strpos; use function strtolower; +use const JSON_THROW_ON_ERROR; + class Context { /** @@ -770,7 +772,7 @@ public function getScopeSummary(): string $summary[$k] = $v->getId(); } - return json_encode($summary); + return json_encode($summary, JSON_THROW_ON_ERROR); } public function defineGlobals(): void diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php b/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php index c5854130a2c..87706f98c96 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php @@ -71,6 +71,8 @@ use function strtolower; use function substr; +use const JSON_THROW_ON_ERROR; + /** * @internal * This class transform conditions in code into "assertions" that will be reconciled with the type already known of a @@ -149,7 +151,7 @@ public static function scrapeAssertions( if ($var_name) { if ($candidate_if_types) { - $if_types[$var_name] = [['@' . json_encode($candidate_if_types[0])]]; + $if_types[$var_name] = [['@' . json_encode($candidate_if_types[0], JSON_THROW_ON_ERROR)]]; } else { $if_types[$var_name] = [['!falsy']]; } diff --git a/src/Psalm/Internal/Clause.php b/src/Psalm/Internal/Clause.php index 5497f579b9b..a3c6e70232f 100644 --- a/src/Psalm/Internal/Clause.php +++ b/src/Psalm/Internal/Clause.php @@ -19,6 +19,8 @@ use function strpos; use function substr; +use const JSON_THROW_ON_ERROR; + /** * @internal * @@ -110,7 +112,7 @@ public function __construct( sort($possibilities[$i]); } - $this->hash = md5((string) json_encode($possibilities)); + $this->hash = md5(json_encode($possibilities, JSON_THROW_ON_ERROR)); } } diff --git a/src/Psalm/Internal/Cli/Psalm.php b/src/Psalm/Internal/Cli/Psalm.php index 2482dffd94a..7f46fafc157 100644 --- a/src/Psalm/Internal/Cli/Psalm.php +++ b/src/Psalm/Internal/Cli/Psalm.php @@ -73,6 +73,7 @@ use function version_compare; use const DIRECTORY_SEPARATOR; +use const JSON_THROW_ON_ERROR; use const LC_CTYPE; use const PHP_EOL; use const PHP_OS; @@ -742,7 +743,10 @@ private static function storeTypeMap(Providers $providers, Config $config, strin $expected_references ); - $type_map_string = json_encode(['files' => $name_file_map, 'references' => $reference_dictionary]); + $type_map_string = json_encode( + ['files' => $name_file_map, 'references' => $reference_dictionary], + JSON_THROW_ON_ERROR + ); $providers->file_provider->setContents( $type_map_location, diff --git a/src/Psalm/Internal/CliUtils.php b/src/Psalm/Internal/CliUtils.php index 37b7782be66..3c683f3895b 100644 --- a/src/Psalm/Internal/CliUtils.php +++ b/src/Psalm/Internal/CliUtils.php @@ -4,6 +4,7 @@ use Composer\Autoload\ClassLoader; use Composer\InstalledVersions; +use JsonException; use OutOfBoundsException; use Phar; use Psalm\Config; @@ -44,6 +45,7 @@ use function trim; use const DIRECTORY_SEPARATOR; +use const JSON_THROW_ON_ERROR; use const PHP_EOL; use const STDERR; use const STDIN; @@ -172,8 +174,17 @@ public static function getVendorDir(string $current_dir): string if (!file_exists($composer_json_path)) { return 'vendor'; } + try { + $composer_json = json_decode(file_get_contents($composer_json_path), true, 512, JSON_THROW_ON_ERROR); + } catch (JsonException $e) { + fwrite( + STDERR, + 'Invalid composer.json at ' . $composer_json_path . "\n" . $e->getMessage() . "\n" + ); + exit(1); + } - if (!$composer_json = json_decode(file_get_contents($composer_json_path), true)) { + if (!$composer_json) { fwrite( STDERR, 'Invalid composer.json at ' . $composer_json_path . "\n" diff --git a/src/Psalm/Internal/Codebase/TaintFlowGraph.php b/src/Psalm/Internal/Codebase/TaintFlowGraph.php index f24a20e4634..f493bfab21b 100644 --- a/src/Psalm/Internal/Codebase/TaintFlowGraph.php +++ b/src/Psalm/Internal/Codebase/TaintFlowGraph.php @@ -41,6 +41,8 @@ use function strlen; use function substr; +use const JSON_THROW_ON_ERROR; + /** * @internal */ @@ -468,8 +470,8 @@ private function getChildNodes( $new_destination->path_types = array_merge($generated_source->path_types, [$path_type]); $key = $to_id . - ' ' . json_encode($new_destination->specialized_calls) . - ' ' . json_encode($new_destination->taints); + ' ' . json_encode($new_destination->specialized_calls, JSON_THROW_ON_ERROR) . + ' ' . json_encode($new_destination->taints, JSON_THROW_ON_ERROR); $new_sources[$key] = $new_destination; } diff --git a/src/Psalm/Internal/ExecutionEnvironment/BuildInfoCollector.php b/src/Psalm/Internal/ExecutionEnvironment/BuildInfoCollector.php index 6d7ab705dab..25d731dcc96 100644 --- a/src/Psalm/Internal/ExecutionEnvironment/BuildInfoCollector.php +++ b/src/Psalm/Internal/ExecutionEnvironment/BuildInfoCollector.php @@ -12,6 +12,8 @@ use function strpos; use function strtotime; +use const JSON_THROW_ON_ERROR; + /** * Environment variables collector for CI environment. * @@ -284,7 +286,7 @@ protected function fillGithubActions(): BuildInfoCollector if (isset($this->env['GITHUB_EVENT_PATH'])) { $event_json = file_get_contents((string) $this->env['GITHUB_EVENT_PATH']); /** @var array */ - $event_data = json_decode($event_json, true); + $event_data = json_decode($event_json, true, 512, JSON_THROW_ON_ERROR); if (isset($event_data['head_commit'])) { /** diff --git a/src/Psalm/Internal/PluginManager/PluginListFactory.php b/src/Psalm/Internal/PluginManager/PluginListFactory.php index 727362fe46f..6ae81a32b8d 100644 --- a/src/Psalm/Internal/PluginManager/PluginListFactory.php +++ b/src/Psalm/Internal/PluginManager/PluginListFactory.php @@ -11,6 +11,7 @@ use function urlencode; use const DIRECTORY_SEPARATOR; +use const JSON_THROW_ON_ERROR; /** * @internal @@ -71,7 +72,8 @@ private function findLockFiles(): array 'packages' => [], 'packages-dev' => [], ]; - $composer_lock_filenames[] = 'data:application/json,' . urlencode(json_encode($stub_composer_lock)); + $composer_lock_filenames[] = 'data:application/json,' + . urlencode(json_encode($stub_composer_lock, JSON_THROW_ON_ERROR)); } return $composer_lock_filenames; diff --git a/src/Psalm/Internal/Provider/ParserCacheProvider.php b/src/Psalm/Internal/Provider/ParserCacheProvider.php index 85c0c06c42c..1918279554e 100644 --- a/src/Psalm/Internal/Provider/ParserCacheProvider.php +++ b/src/Psalm/Internal/Provider/ParserCacheProvider.php @@ -2,6 +2,7 @@ namespace Psalm\Internal\Provider; +use JsonException; use PhpParser; use PhpParser\Node\Stmt; use Psalm\Config; @@ -31,6 +32,7 @@ use const DIRECTORY_SEPARATOR; use const E_USER_ERROR; +use const JSON_THROW_ON_ERROR; use const SCANDIR_SORT_NONE; /** @@ -193,7 +195,14 @@ private function getExistingFileContentHashes(): array return []; } - $hashes_decoded = json_decode($hashes_encoded, true); + try { + $hashes_decoded = json_decode($hashes_encoded, true, 512, JSON_THROW_ON_ERROR); + } catch (JsonException $e) { + error_log('Failed to parse hashes: ' . $e->getMessage()); + $this->existing_file_content_hashes = []; + + return []; + } if (!is_array($hashes_decoded)) { error_log('Unexpected value ' . gettype($hashes_decoded)); @@ -281,7 +290,7 @@ public function saveFileContentHashes(): void file_put_contents( $file_hashes_path, - json_encode($file_content_hashes) + json_encode($file_content_hashes, JSON_THROW_ON_ERROR) ); } diff --git a/src/Psalm/Plugin/Shepherd.php b/src/Psalm/Plugin/Shepherd.php index 51748d5f61a..93192df66b6 100644 --- a/src/Psalm/Plugin/Shepherd.php +++ b/src/Psalm/Plugin/Shepherd.php @@ -29,6 +29,7 @@ use const CURLOPT_POST; use const CURLOPT_POSTFIELDS; use const CURLOPT_RETURNTRANSFER; +use const JSON_THROW_ON_ERROR; use const PHP_EOL; use const PHP_URL_SCHEME; use const STDERR; @@ -76,7 +77,7 @@ static function (IssueData $i): bool { 'level' => Config::getInstance()->level ]; - $payload = json_encode($data); + $payload = json_encode($data, JSON_THROW_ON_ERROR); $base_address = $codebase->config->shepherd_host; diff --git a/src/Psalm/Type/Reconciler.php b/src/Psalm/Type/Reconciler.php index be5e2e2e146..4a0bcdbf761 100644 --- a/src/Psalm/Type/Reconciler.php +++ b/src/Psalm/Type/Reconciler.php @@ -57,6 +57,8 @@ use function strtolower; use function substr; +use const JSON_THROW_ON_ERROR; + class Reconciler { public const RECONCILIATION_OK = 0; @@ -190,11 +192,11 @@ public static function reconcileKeyedTypes( $nested_negated = !$negated; /** @var array>> */ - $data = json_decode(substr($new_type_part_part, 2), true); + $data = json_decode(substr($new_type_part_part, 2), true, 512, JSON_THROW_ON_ERROR); } else { $nested_negated = $negated; /** @var array>> */ - $data = json_decode(substr($new_type_part_part, 1), true); + $data = json_decode(substr($new_type_part_part, 1), true, 512, JSON_THROW_ON_ERROR); } $existing_types = self::reconcileKeyedTypes( diff --git a/tests/ComposerLockTest.php b/tests/ComposerLockTest.php index cf856d4a206..fc46ccefe33 100644 --- a/tests/ComposerLockTest.php +++ b/tests/ComposerLockTest.php @@ -7,6 +7,8 @@ use function json_encode; +use const JSON_THROW_ON_ERROR; + /** @group PluginManager */ class ComposerLockTest extends TestCase { @@ -216,6 +218,6 @@ private function pluginEntry(string $package_name, string $package_class): array */ private function jsonFile($data): string { - return 'data:application/json,' . json_encode($data); + return 'data:application/json,' . json_encode($data, JSON_THROW_ON_ERROR); } } diff --git a/tests/ReportOutputTest.php b/tests/ReportOutputTest.php index 5fd7b59bc47..5fb82b594f4 100644 --- a/tests/ReportOutputTest.php +++ b/tests/ReportOutputTest.php @@ -24,6 +24,8 @@ use function preg_replace; use function unlink; +use const JSON_THROW_ON_ERROR; + class ReportOutputTest extends TestCase { public function setUp(): void @@ -666,7 +668,7 @@ public function testSarifReport(): void $this->assertSame( $issue_data, - json_decode(IssueBuffer::getOutput(IssueBuffer::getIssuesData(), $sarif_report_options), true) + json_decode(IssueBuffer::getOutput(IssueBuffer::getIssuesData(), $sarif_report_options), true, 512, JSON_THROW_ON_ERROR) ); } @@ -819,7 +821,7 @@ public function testJsonReport(): void $this->assertSame( $issue_data, - json_decode(IssueBuffer::getOutput(IssueBuffer::getIssuesData(), $json_report_options), true) + json_decode(IssueBuffer::getOutput(IssueBuffer::getIssuesData(), $json_report_options), true, 512, JSON_THROW_ON_ERROR) ); } @@ -853,7 +855,7 @@ public function testFilteredJsonReportIsStillArray(): void $fixable_issue_counts, $report_options ); - $this->assertIsArray(json_decode($report->create())); + $this->assertIsArray(json_decode($report->create(), null, 512, JSON_THROW_ON_ERROR)); } public function testSonarqubeReport(): void @@ -950,7 +952,7 @@ public function testSonarqubeReport(): void $this->assertSame( $issue_data, - json_decode(IssueBuffer::getOutput(IssueBuffer::getIssuesData(), $sonarqube_report_options), true) + json_decode(IssueBuffer::getOutput(IssueBuffer::getIssuesData(), $sonarqube_report_options), true, 512, JSON_THROW_ON_ERROR) ); }