From ce331a929425e0d0996b54da0e35511b3dc49e06 Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Tue, 10 Mar 2026 14:58:07 +0100 Subject: [PATCH] Fix phpstan/phpstan#14231: Fatal error when `path` has array value in ignoreErrors When a user accidentally writes `path:` with an array value (intending `paths:`), ValidateIgnoredErrorsExtension crashes with a TypeError because FileExcluder::isAbsolutePath() receives an array instead of a string. The schema validation that would catch this runs after the DI extension, so it never gets a chance to report the misconfiguration. Added type checks for `path` (must be string) and `paths` (must be array) with helpful error messages suggesting the correct key name. --- .../ValidateIgnoredErrorsExtension.php | 10 ++++++++++ .../InvalidIgnoredErrorExceptionTest.php | 8 ++++++++ .../invalidIgnoreErrors/path-with-array-value.neon | 6 ++++++ .../invalidIgnoreErrors/paths-with-string-value.neon | 5 +++++ 4 files changed, 29 insertions(+) create mode 100644 tests/PHPStan/DependencyInjection/invalidIgnoreErrors/path-with-array-value.neon create mode 100644 tests/PHPStan/DependencyInjection/invalidIgnoreErrors/paths-with-string-value.neon diff --git a/src/DependencyInjection/ValidateIgnoredErrorsExtension.php b/src/DependencyInjection/ValidateIgnoredErrorsExtension.php index c01cc4c94e..de1342eaba 100644 --- a/src/DependencyInjection/ValidateIgnoredErrorsExtension.php +++ b/src/DependencyInjection/ValidateIgnoredErrorsExtension.php @@ -38,10 +38,12 @@ use function array_keys; use function array_map; use function count; +use function gettype; use function implode; use function is_array; use function is_dir; use function is_file; +use function is_string; use function sprintf; use const PHP_VERSION_ID; @@ -167,8 +169,16 @@ public function getRegistry(): OperatorTypeSpecifyingExtensionRegistry } if (isset($ignoreError['path'])) { + if (!is_string($ignoreError['path'])) { + $errors[] = sprintf("Key 'path' of ignoreErrors expects a string, %s given. Did you mean 'paths'?", gettype($ignoreError['path'])); + continue; + } $ignorePaths = [$ignoreError['path']]; } elseif (isset($ignoreError['paths'])) { + if (!is_array($ignoreError['paths'])) { + $errors[] = sprintf("Key 'paths' of ignoreErrors expects an array, %s given. Did you mean 'path'?", gettype($ignoreError['paths'])); + continue; + } $ignorePaths = $ignoreError['paths']; } else { continue; diff --git a/tests/PHPStan/DependencyInjection/InvalidIgnoredErrorExceptionTest.php b/tests/PHPStan/DependencyInjection/InvalidIgnoredErrorExceptionTest.php index a4d6dc2a72..5432fb9835 100644 --- a/tests/PHPStan/DependencyInjection/InvalidIgnoredErrorExceptionTest.php +++ b/tests/PHPStan/DependencyInjection/InvalidIgnoredErrorExceptionTest.php @@ -55,6 +55,14 @@ public static function dataValidateIgnoreErrors(): iterable __DIR__ . '/invalidIgnoreErrors/count-without-path.neon', 'An ignoreErrors entry with count field must also contain path field.', ]; + yield [ + __DIR__ . '/invalidIgnoreErrors/path-with-array-value.neon', + "Key 'path' of ignoreErrors expects a string, array given. Did you mean 'paths'?", + ]; + yield [ + __DIR__ . '/invalidIgnoreErrors/paths-with-string-value.neon', + "Key 'paths' of ignoreErrors expects an array, string given. Did you mean 'path'?", + ]; } #[DataProvider('dataValidateIgnoreErrors')] diff --git a/tests/PHPStan/DependencyInjection/invalidIgnoreErrors/path-with-array-value.neon b/tests/PHPStan/DependencyInjection/invalidIgnoreErrors/path-with-array-value.neon new file mode 100644 index 0000000000..7f7d8af615 --- /dev/null +++ b/tests/PHPStan/DependencyInjection/invalidIgnoreErrors/path-with-array-value.neon @@ -0,0 +1,6 @@ +parameters: + ignoreErrors: + - + identifier: some.identifier + path: + - tests/some-file.php diff --git a/tests/PHPStan/DependencyInjection/invalidIgnoreErrors/paths-with-string-value.neon b/tests/PHPStan/DependencyInjection/invalidIgnoreErrors/paths-with-string-value.neon new file mode 100644 index 0000000000..ec79f45d83 --- /dev/null +++ b/tests/PHPStan/DependencyInjection/invalidIgnoreErrors/paths-with-string-value.neon @@ -0,0 +1,5 @@ +parameters: + ignoreErrors: + - + identifier: some.identifier + paths: tests/some-file.php