Skip to content

Commit e71c437

Browse files
phpstan-botstaabmclaude
authored
Fix phpstan/phpstan#14241: Cannot re-assign auto-global variable in parameters
Co-authored-by: Markus Staab <markus.staab@redaxo.de> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent bc73c0a commit e71c437

File tree

4 files changed

+151
-0
lines changed

4 files changed

+151
-0
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ lint:
132132
--exclude tests/PHPStan/Rules/Classes/data/bug-14250-promoted-properties.php \
133133
--exclude tests/PHPStan/Rules/Operators/data/bug-3585.php \
134134
--exclude tests/PHPStan/Rules/EnumCases/data/bug-14252.php \
135+
--exclude tests/PHPStan/Rules/Functions/data/bug-14241.php \
135136
src tests
136137

137138
install-paratest:
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Functions;
4+
5+
use PhpParser\Node;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\DependencyInjection\RegisteredRule;
8+
use PHPStan\Rules\Rule;
9+
use PHPStan\Rules\RuleErrorBuilder;
10+
use function in_array;
11+
use function is_string;
12+
use function sprintf;
13+
14+
/**
15+
* @implements Rule<Node\Param>
16+
*/
17+
#[RegisteredRule(level: 0)]
18+
final class InvalidParameterNameRule implements Rule
19+
{
20+
21+
public function getNodeType(): string
22+
{
23+
return Node\Param::class;
24+
}
25+
26+
public function processNode(Node $node, Scope $scope): array
27+
{
28+
if (!$node->var instanceof Node\Expr\Variable) {
29+
return [];
30+
}
31+
32+
if (!is_string($node->var->name)) {
33+
return [];
34+
}
35+
36+
$variableName = $node->var->name;
37+
38+
if (in_array($variableName, Scope::SUPERGLOBAL_VARIABLES, true)) {
39+
return [
40+
RuleErrorBuilder::message(sprintf('Superglobal variable $%s cannot be used as a parameter.', $variableName))
41+
->identifier('parameter.superglobal')
42+
->nonIgnorable()
43+
->build(),
44+
];
45+
}
46+
47+
if ($variableName === 'this') {
48+
return [
49+
RuleErrorBuilder::message('Cannot use $this as parameter.')
50+
->identifier('parameter.this')
51+
->nonIgnorable()
52+
->build(),
53+
];
54+
}
55+
56+
return [];
57+
}
58+
59+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Functions;
4+
5+
use PHPStan\Rules\Rule;
6+
use PHPStan\Testing\RuleTestCase;
7+
8+
/**
9+
* @extends RuleTestCase<InvalidParameterNameRule>
10+
*/
11+
class InvalidParameterNameRuleTest extends RuleTestCase
12+
{
13+
14+
protected function getRule(): Rule
15+
{
16+
return new InvalidParameterNameRule();
17+
}
18+
19+
public function testRule(): void
20+
{
21+
$this->analyse([__DIR__ . '/data/bug-14241.php'], [
22+
[
23+
'Superglobal variable $_FILES cannot be used as a parameter.',
24+
5,
25+
],
26+
[
27+
'Superglobal variable $_GET cannot be used as a parameter.',
28+
7,
29+
],
30+
[
31+
'Superglobal variable $_POST cannot be used as a parameter.',
32+
7,
33+
],
34+
[
35+
'Superglobal variable $_SERVER cannot be used as a parameter.',
36+
13,
37+
],
38+
[
39+
'Superglobal variable $_SESSION cannot be used as a parameter.',
40+
15,
41+
],
42+
[
43+
'Superglobal variable $_COOKIE cannot be used as a parameter.',
44+
18,
45+
],
46+
[
47+
'Superglobal variable $_REQUEST cannot be used as a parameter.',
48+
20,
49+
],
50+
[
51+
'Superglobal variable $_ENV cannot be used as a parameter.',
52+
22,
53+
],
54+
[
55+
'Superglobal variable $GLOBALS cannot be used as a parameter.',
56+
24,
57+
],
58+
[
59+
'Cannot use $this as parameter.',
60+
26,
61+
],
62+
]);
63+
}
64+
65+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug14241;
4+
5+
function doFoo($_FILES): void {}
6+
7+
function doBar($_GET, $_POST): void {}
8+
9+
function doBaz($ok): void {}
10+
11+
class Foo
12+
{
13+
public function doFoo($_SERVER): void {}
14+
15+
public static function doBar($_SESSION): void {}
16+
}
17+
18+
$f = function ($_COOKIE): void {};
19+
20+
$g = fn ($_REQUEST) => $_REQUEST;
21+
22+
function doQux($_ENV): void {}
23+
24+
function doQuux($GLOBALS): void {}
25+
26+
function doThis($this) {}

0 commit comments

Comments
 (0)