Fix phpstan/phpstan#14241: Cannot re-assign auto-global variable in parameters#5153
Conversation
a2ae368 to
ba7f36d
Compare
|
(requesting ondrejs review, as we are adding a new rule) |
ba7f36d to
e7b86ab
Compare
|
Tests pass. The review from staabm is just an approval — no changes were requested. The PR is ready to merge as-is. |
e7b86ab to
dff450d
Compare
staabm
left a comment
There was a problem hiding this comment.
test bot reaction after rebase to latest action workflows
| $variableName = $param->var->name; | ||
|
|
||
| if (in_array($variableName, Scope::SUPERGLOBAL_VARIABLES, true)) { | ||
| $errors[] = RuleErrorBuilder::message(sprintf('Cannot re-assign auto-global variable $%s.', $variableName)) |
There was a problem hiding this comment.
What does auto-global mean? I've never heard that phrase. Are there non-auto-global variables as well?
There was a problem hiding this comment.
Already handled — make tests passed (11625 tests, 78861 assertions), and all changes have been committed and pushed.
There was a problem hiding this comment.
auto-global is a term from php-src.
see e.g. https://github.com/search?q=repo%3Aphp%2Fphp-src%20auto-global&type=code
it describes the super-global variables $_GET, $_POST etc, and also contains other magic ones like $argc, $argv.
there is even a php.ini settings for auto-globals in jit:
https://www.php.net/manual/en/ini.core.php#ini.auto-globals-jit
There was a problem hiding this comment.
I've always used and only heard superglobals
There was a problem hiding this comment.
me too. the error message here got inspiration from a php-src native error: https://3v4l.org/1rJJM#veol
| $variableName = $param->var->name; | ||
|
|
||
| if (in_array($variableName, Scope::SUPERGLOBAL_VARIABLES, true)) { | ||
| $errors[] = RuleErrorBuilder::message(sprintf('Cannot re-assign auto-global variable $%s.', $variableName)) |
There was a problem hiding this comment.
The message is also weird. Global variables can be reassigned: https://3v4l.org/gE100#v8.5.3
The message should also contain something about a parameter.
|
|
||
| public function getNodeType(): string | ||
| { | ||
| return Node\FunctionLike::class; |
There was a problem hiding this comment.
Why not hook the rule onto Param?
ondrejmirtes
left a comment
There was a problem hiding this comment.
Much better. Now please rebase on top of origin/2.1.x and fix the conflict in Makefile.
| @@ -0,0 +1,26 @@ | |||
| <?php declare(strict_types = 1); | |||
|
|
|||
| namespace Bug14241; | |||
There was a problem hiding this comment.
we should have another test for
<?php
// This should work, but *not* generate a binding for $GLOBALS
$a = 123;
$fn = fn() => $GLOBALS['a'];
var_dump($fn());
which should not produce a error.
see
There was a problem hiding this comment.
There's no Param in that code so the rule won't trigger at all.
…arameters
- 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
- Change rule to listen on Node\Param instead of Node\FunctionLike - Replace "Cannot re-assign auto-global variable" with clearer "Superglobal variable $X cannot be used as a parameter." - Use distinct identifiers: parameter.superglobal and parameter.this Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ed952fa to
6eb1bb1
Compare
Summary
PHP throws a fatal error when a superglobal variable name (like
$_FILES,$_GET,$_POST, etc.) is used as a function, method, or closure parameter. PHPStan was not detecting this and only reported missing type hints, missing the more fundamental issue.Changes
src/Rules/Functions/SuperGlobalParameterRule.php— a new level-0 rule that checks allFunctionLikenodes for parameters named after superglobal variablestests/PHPStan/Rules/Functions/SuperGlobalParameterRuleTest.phpwith test covering all superglobal variables across functions, methods, closures, and arrow functionstests/PHPStan/Rules/Functions/data/bug-14241.php— test data fileMakefileto exclude the test data file from PHP lint (since PHP itself cannot parse files with superglobal parameters)Root cause
There was no rule checking whether function/method/closure parameters use superglobal variable names. PHP prohibits this at the parser level with "Cannot re-assign auto-global variable" fatal error, but PHPStan's parser (nikic/php-parser) successfully parses the code without error. A dedicated rule was needed to replicate this PHP compile-time check.
Test
The regression test
SuperGlobalParameterRuleTest::testRule()verifies that errors are reported for$_FILES,$_GET,$_POST,$_SERVER,$_SESSION,$_COOKIE,$_REQUEST,$_ENV, and$GLOBALSwhen used as parameters in functions, methods, closures, and arrow functions. Regular parameter names like$okproduce no error.Fixes phpstan/phpstan#14241