From d33483929cd8ff5a4fc137d98d910df3051eab35 Mon Sep 17 00:00:00 2001 From: phpstan-bot <79867460+phpstan-bot@users.noreply.github.com> Date: Sun, 8 Mar 2026 21:47:09 +0000 Subject: [PATCH 1/2] Fix phpstan/phpstan#14241: Report error for auto-global variable in parameters - Added SuperGlobalParameterRule to detect superglobal variable names used as function/method/closure parameters - PHP throws a fatal error for this (e.g. `function doFoo($_FILES): void {}`), but PHPStan was not reporting it - New regression test in tests/PHPStan/Rules/Functions/data/bug-14241.php - Excluded test data file from Makefile lint step since PHP cannot parse files with superglobal parameters --- Makefile | 1 + .../Functions/SuperGlobalParameterRule.php | 55 +++++++++++++++++ .../SuperGlobalParameterRuleTest.php | 61 +++++++++++++++++++ .../Rules/Functions/data/bug-14241.php | 24 ++++++++ 4 files changed, 141 insertions(+) create mode 100644 src/Rules/Functions/SuperGlobalParameterRule.php create mode 100644 tests/PHPStan/Rules/Functions/SuperGlobalParameterRuleTest.php create mode 100644 tests/PHPStan/Rules/Functions/data/bug-14241.php diff --git a/Makefile b/Makefile index 3663878387..96836bff44 100644 --- a/Makefile +++ b/Makefile @@ -131,6 +131,7 @@ lint: --exclude tests/PHPStan/Rules/Classes/data/bug-14250.php \ --exclude tests/PHPStan/Rules/Classes/data/bug-14250-promoted-properties.php \ --exclude tests/PHPStan/Rules/Operators/data/bug-3585.php \ + --exclude tests/PHPStan/Rules/Functions/data/bug-14241.php \ src tests install-paratest: diff --git a/src/Rules/Functions/SuperGlobalParameterRule.php b/src/Rules/Functions/SuperGlobalParameterRule.php new file mode 100644 index 0000000000..9304e57d1c --- /dev/null +++ b/src/Rules/Functions/SuperGlobalParameterRule.php @@ -0,0 +1,55 @@ + + */ +#[RegisteredRule(level: 0)] +final class SuperGlobalParameterRule implements Rule +{ + + public function getNodeType(): string + { + return Node\FunctionLike::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $errors = []; + + foreach ($node->getParams() as $param) { + if (!$param->var instanceof Node\Expr\Variable) { + continue; + } + + if (!is_string($param->var->name)) { + continue; + } + + $var = $param->var->name; + + if (!in_array($var, Scope::SUPERGLOBAL_VARIABLES, true)) { + continue; + } + + $errors[] = RuleErrorBuilder::message(sprintf('Cannot re-assign auto-global variable $%s.', $var)) + ->line($param->getStartLine()) + ->identifier('parameter.superGlobal') + ->nonIgnorable() + ->build(); + } + + return $errors; + } + +} diff --git a/tests/PHPStan/Rules/Functions/SuperGlobalParameterRuleTest.php b/tests/PHPStan/Rules/Functions/SuperGlobalParameterRuleTest.php new file mode 100644 index 0000000000..e1eeeaa813 --- /dev/null +++ b/tests/PHPStan/Rules/Functions/SuperGlobalParameterRuleTest.php @@ -0,0 +1,61 @@ + + */ +class SuperGlobalParameterRuleTest extends RuleTestCase +{ + + protected function getRule(): Rule + { + return new SuperGlobalParameterRule(); + } + + public function testRule(): void + { + $this->analyse([__DIR__ . '/data/bug-14241.php'], [ + [ + 'Cannot re-assign auto-global variable $_FILES.', + 5, + ], + [ + 'Cannot re-assign auto-global variable $_GET.', + 7, + ], + [ + 'Cannot re-assign auto-global variable $_POST.', + 7, + ], + [ + 'Cannot re-assign auto-global variable $_SERVER.', + 13, + ], + [ + 'Cannot re-assign auto-global variable $_SESSION.', + 15, + ], + [ + 'Cannot re-assign auto-global variable $_COOKIE.', + 18, + ], + [ + 'Cannot re-assign auto-global variable $_REQUEST.', + 20, + ], + [ + 'Cannot re-assign auto-global variable $_ENV.', + 22, + ], + [ + 'Cannot re-assign auto-global variable $GLOBALS.', + 24, + ], + ]); + } + +} diff --git a/tests/PHPStan/Rules/Functions/data/bug-14241.php b/tests/PHPStan/Rules/Functions/data/bug-14241.php new file mode 100644 index 0000000000..2b0d2819e8 --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/bug-14241.php @@ -0,0 +1,24 @@ + $_REQUEST; + +function doQux($_ENV): void {} + +function doQuux($GLOBALS): void {} From dff450dcbe50742e2eb575c0c10fd119f88faa8a Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Mon, 9 Mar 2026 11:22:22 +0100 Subject: [PATCH 2/2] Rework --- ...rRule.php => InvalidParameterNameRule.php} | 25 +++++++++++-------- ...t.php => InvalidParameterNameRuleTest.php} | 10 +++++--- .../Rules/Functions/data/bug-14241.php | 2 ++ 3 files changed, 24 insertions(+), 13 deletions(-) rename src/Rules/Functions/{SuperGlobalParameterRule.php => InvalidParameterNameRule.php} (54%) rename tests/PHPStan/Rules/Functions/{SuperGlobalParameterRuleTest.php => InvalidParameterNameRuleTest.php} (82%) diff --git a/src/Rules/Functions/SuperGlobalParameterRule.php b/src/Rules/Functions/InvalidParameterNameRule.php similarity index 54% rename from src/Rules/Functions/SuperGlobalParameterRule.php rename to src/Rules/Functions/InvalidParameterNameRule.php index 9304e57d1c..5619b8f161 100644 --- a/src/Rules/Functions/SuperGlobalParameterRule.php +++ b/src/Rules/Functions/InvalidParameterNameRule.php @@ -15,7 +15,7 @@ * @implements Rule */ #[RegisteredRule(level: 0)] -final class SuperGlobalParameterRule implements Rule +final class InvalidParameterNameRule implements Rule { public function getNodeType(): string @@ -36,17 +36,22 @@ public function processNode(Node $node, Scope $scope): array continue; } - $var = $param->var->name; - - if (!in_array($var, Scope::SUPERGLOBAL_VARIABLES, true)) { - continue; + $variableName = $param->var->name; + + if (in_array($variableName, Scope::SUPERGLOBAL_VARIABLES, true)) { + $errors[] = RuleErrorBuilder::message(sprintf('Cannot re-assign auto-global variable $%s.', $variableName)) + ->line($param->getStartLine()) + ->identifier('parameter.invalidExpr') + ->nonIgnorable() + ->build(); + } elseif ($variableName === 'this') { + $errors[] = RuleErrorBuilder::message('Cannot use $this as parameter.') + ->line($param->getStartLine()) + ->identifier('parameter.invalidExpr') + ->nonIgnorable() + ->build(); } - $errors[] = RuleErrorBuilder::message(sprintf('Cannot re-assign auto-global variable $%s.', $var)) - ->line($param->getStartLine()) - ->identifier('parameter.superGlobal') - ->nonIgnorable() - ->build(); } return $errors; diff --git a/tests/PHPStan/Rules/Functions/SuperGlobalParameterRuleTest.php b/tests/PHPStan/Rules/Functions/InvalidParameterNameRuleTest.php similarity index 82% rename from tests/PHPStan/Rules/Functions/SuperGlobalParameterRuleTest.php rename to tests/PHPStan/Rules/Functions/InvalidParameterNameRuleTest.php index e1eeeaa813..5593475d42 100644 --- a/tests/PHPStan/Rules/Functions/SuperGlobalParameterRuleTest.php +++ b/tests/PHPStan/Rules/Functions/InvalidParameterNameRuleTest.php @@ -6,14 +6,14 @@ use PHPStan\Testing\RuleTestCase; /** - * @extends RuleTestCase + * @extends RuleTestCase */ -class SuperGlobalParameterRuleTest extends RuleTestCase +class InvalidParameterNameRuleTest extends RuleTestCase { protected function getRule(): Rule { - return new SuperGlobalParameterRule(); + return new InvalidParameterNameRule(); } public function testRule(): void @@ -55,6 +55,10 @@ public function testRule(): void 'Cannot re-assign auto-global variable $GLOBALS.', 24, ], + [ + 'Cannot use $this as parameter.', + 26, + ], ]); } diff --git a/tests/PHPStan/Rules/Functions/data/bug-14241.php b/tests/PHPStan/Rules/Functions/data/bug-14241.php index 2b0d2819e8..127541424c 100644 --- a/tests/PHPStan/Rules/Functions/data/bug-14241.php +++ b/tests/PHPStan/Rules/Functions/data/bug-14241.php @@ -22,3 +22,5 @@ public static function doBar($_SESSION): void {} function doQux($_ENV): void {} function doQuux($GLOBALS): void {} + +function doThis($this) {}