Skip to content

Fix phpstan/phpstan#14241: Cannot re-assign auto-global variable in parameters#5153

Merged
ondrejmirtes merged 3 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-lgqy7io
Mar 23, 2026
Merged

Fix phpstan/phpstan#14241: Cannot re-assign auto-global variable in parameters#5153
ondrejmirtes merged 3 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-lgqy7io

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

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

  • Added src/Rules/Functions/SuperGlobalParameterRule.php — a new level-0 rule that checks all FunctionLike nodes for parameters named after superglobal variables
  • Added tests/PHPStan/Rules/Functions/SuperGlobalParameterRuleTest.php with test covering all superglobal variables across functions, methods, closures, and arrow functions
  • Added tests/PHPStan/Rules/Functions/data/bug-14241.php — test data file
  • Updated Makefile to 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 $GLOBALS when used as parameters in functions, methods, closures, and arrow functions. Regular parameter names like $ok produce no error.

Fixes phpstan/phpstan#14241

@clxmstaab clxmstaab force-pushed the create-pull-request/patch-lgqy7io branch from a2ae368 to ba7f36d Compare March 9, 2026 10:23
@staabm staabm requested a review from ondrejmirtes March 9, 2026 10:28
@staabm
Copy link
Copy Markdown
Contributor

staabm commented Mar 9, 2026

(requesting ondrejs review, as we are adding a new rule)

@VincentLanglet VincentLanglet force-pushed the create-pull-request/patch-lgqy7io branch from ba7f36d to e7b86ab Compare March 19, 2026 22:29
@VincentLanglet VincentLanglet requested a review from staabm March 20, 2026 08:31
@phpstan-bot
Copy link
Copy Markdown
Collaborator Author

Tests pass. The review from staabm is just an approval — no changes were requested. The PR is ready to merge as-is.

@staabm staabm force-pushed the create-pull-request/patch-lgqy7io branch from e7b86ab to dff450d Compare March 20, 2026 09:16
Copy link
Copy Markdown
Contributor

@staabm staabm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does auto-global mean? I've never heard that phrase. Are there non-auto-global variables as well?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already handled — make tests passed (11625 tests, 78861 assertions), and all changes have been committed and pushed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've always used and only heard superglobals

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not hook the rule onto Param?

Copy link
Copy Markdown
Member

@ondrejmirtes ondrejmirtes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no Param in that code so the rule won't trigger at all.

phpstan-bot and others added 3 commits March 23, 2026 09:58
…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>
@ondrejmirtes ondrejmirtes force-pushed the create-pull-request/patch-lgqy7io branch from ed952fa to 6eb1bb1 Compare March 23, 2026 08:58
@ondrejmirtes ondrejmirtes merged commit e71c437 into phpstan:2.1.x Mar 23, 2026
125 checks passed
@ondrejmirtes ondrejmirtes deleted the create-pull-request/patch-lgqy7io branch March 23, 2026 08:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants