Skip to content

Commit fa75094

Browse files
Fix phpstan/phpstan#14397: FILTER_FLAG_GLOBAL_RANGE false positive on PHP 8.3/8.4
- FILTER_FLAG_GLOBAL_RANGE (268435456) has the same numeric value as FILTER_THROW_ON_FAILURE on PHP 8.3/8.4 - This caused PHPStan to incorrectly think filter_var would throw, removing false from the return type - Gate all FILTER_THROW_ON_FAILURE checks behind PHP >= 8.5 (where the constant was introduced) - Applied fix to FilterFunctionReturnTypeHelper, FilterVarThrowTypeExtension, and FilterVarRule - Updated FilterVarRuleTest to pass new PhpVersion constructor parameter - New regression test in tests/PHPStan/Analyser/nsrt/bug-14397.php
1 parent 8b36ae3 commit fa75094

File tree

5 files changed

+24
-2
lines changed

5 files changed

+24
-2
lines changed

src/Rules/Functions/FilterVarRule.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PhpParser\Node\Name;
88
use PHPStan\Analyser\Scope;
99
use PHPStan\DependencyInjection\RegisteredRule;
10+
use PHPStan\Php\PhpVersion;
1011
use PHPStan\Reflection\ReflectionProvider;
1112
use PHPStan\Rules\Rule;
1213
use PHPStan\Rules\RuleErrorBuilder;
@@ -23,6 +24,7 @@ final class FilterVarRule implements Rule
2324
public function __construct(
2425
private ReflectionProvider $reflectionProvider,
2526
private FilterFunctionReturnTypeHelper $filterFunctionReturnTypeHelper,
27+
private PhpVersion $phpVersion,
2628
)
2729
{
2830
}
@@ -44,7 +46,7 @@ public function processNode(Node $node, Scope $scope): array
4446

4547
$args = $node->getArgs();
4648

47-
if ($this->reflectionProvider->hasConstant(new Name\FullyQualified('FILTER_THROW_ON_FAILURE'), null)) {
49+
if ($this->phpVersion->getVersionId() >= 80500 && $this->reflectionProvider->hasConstant(new Name\FullyQualified('FILTER_THROW_ON_FAILURE'), null)) {
4850
if (count($args) < 3) {
4951
return [];
5052
}

src/Type/Php/FilterFunctionReturnTypeHelper.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,9 @@ public function getType(Type $inputType, ?Type $filterType, ?Type $flagsType): T
151151

152152
$inputIsArray = $inputType->isArray();
153153
$hasRequireArrayFlag = $this->hasFlag('FILTER_REQUIRE_ARRAY', $flagsType);
154-
$hasThrowOnFailureFlag = $this->hasFlag('FILTER_THROW_ON_FAILURE', $flagsType);
154+
$hasThrowOnFailureFlag = $this->phpVersion->getVersionId() >= 80500
155+
? $this->hasFlag('FILTER_THROW_ON_FAILURE', $flagsType)
156+
: TrinaryLogic::createNo();
155157
if ($inputIsArray->no() && $hasRequireArrayFlag->yes()) {
156158
if ($hasThrowOnFailureFlag->yes()) {
157159
return new ErrorType();

src/Type/Php/FilterVarThrowTypeExtension.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use PhpParser\Node\Name;
77
use PHPStan\Analyser\Scope;
88
use PHPStan\DependencyInjection\AutowiredService;
9+
use PHPStan\Php\PhpVersion;
910
use PHPStan\Reflection\FunctionReflection;
1011
use PHPStan\Reflection\ReflectionProvider;
1112
use PHPStan\Type\Constant\ConstantIntegerType;
@@ -20,6 +21,7 @@ final class FilterVarThrowTypeExtension implements DynamicFunctionThrowTypeExten
2021

2122
public function __construct(
2223
private ReflectionProvider $reflectionProvider,
24+
private PhpVersion $phpVersion,
2325
)
2426
{
2527
}
@@ -29,6 +31,7 @@ public function isFunctionSupported(
2931
): bool
3032
{
3133
return $functionReflection->getName() === 'filter_var'
34+
&& $this->phpVersion->getVersionId() >= 80500
3235
&& $this->reflectionProvider->hasConstant(new Name\FullyQualified('FILTER_THROW_ON_FAILURE'), null);
3336
}
3437

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php // lint >= 8.2
2+
3+
declare(strict_types = 1);
4+
5+
namespace Bug14397;
6+
7+
use function filter_var;
8+
use function PHPStan\Testing\assertType;
9+
10+
function test(string $ipAddress): void
11+
{
12+
assertType('non-falsy-string|false', filter_var($ipAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_GLOBAL_RANGE));
13+
}

tests/PHPStan/Rules/Functions/FilterVarRuleTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Rules\Functions;
44

5+
use PHPStan\Php\PhpVersion;
56
use PHPStan\Rules\Rule;
67
use PHPStan\Testing\RuleTestCase;
78
use PHPStan\Type\Php\FilterFunctionReturnTypeHelper;
@@ -16,6 +17,7 @@ protected function getRule(): Rule
1617
return new FilterVarRule(
1718
self::createReflectionProvider(),
1819
self::getContainer()->getByType(FilterFunctionReturnTypeHelper::class),
20+
self::getContainer()->getByType(PhpVersion::class),
1921
);
2022
}
2123

0 commit comments

Comments
 (0)