diff --git a/src/Type/Php/FilterVarThrowTypeExtension.php b/src/Type/Php/FilterVarThrowTypeExtension.php index bcd8ed1a092..0ace100db83 100644 --- a/src/Type/Php/FilterVarThrowTypeExtension.php +++ b/src/Type/Php/FilterVarThrowTypeExtension.php @@ -9,8 +9,6 @@ use PHPStan\Php\PhpVersion; use PHPStan\Reflection\FunctionReflection; use PHPStan\Reflection\ReflectionProvider; -use PHPStan\Type\Constant\ConstantIntegerType; -use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\DynamicFunctionThrowTypeExtension; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; @@ -22,6 +20,7 @@ final class FilterVarThrowTypeExtension implements DynamicFunctionThrowTypeExten public function __construct( private ReflectionProvider $reflectionProvider, private PhpVersion $phpVersion, + private FilterFunctionReturnTypeHelper $filterFunctionReturnTypeHelper, ) { } @@ -39,7 +38,7 @@ public function getThrowTypeFromFunctionCall( Scope $scope, ): ?Type { - if (!isset($funcCall->getArgs()[3])) { + if (!isset($funcCall->getArgs()[2])) { return null; } @@ -50,31 +49,14 @@ public function getThrowTypeFromFunctionCall( return null; } - $flagsExpr = $funcCall->getArgs()[3]->value; + $flagsExpr = $funcCall->getArgs()[2]->value; $flagsType = $scope->getType($flagsExpr); - if ($flagsType->isConstantArray()->yes()) { - $flagsType = $flagsType->getOffsetValueType(new ConstantStringType('flags')); - } - - $flag = $this->getConstant(); - - if ($flag !== null && $flagsType instanceof ConstantIntegerType && ($flagsType->getValue() & $flag) === $flag) { + if (!$this->filterFunctionReturnTypeHelper->hasFlag('FILTER_THROW_ON_FAILURE', $flagsType)->no()) { return new ObjectType('Filter\FilterFailedException'); } return null; } - private function getConstant(): ?int - { - $constant = $this->reflectionProvider->getConstant(new Name('FILTER_THROW_ON_FAILURE'), null); - $valueType = $constant->getValueType(); - if (!$valueType instanceof ConstantIntegerType) { - return null; - } - - return $valueType->getValue(); - } - } diff --git a/tests/PHPStan/Rules/Exceptions/CatchWithUnthrownExceptionRuleTest.php b/tests/PHPStan/Rules/Exceptions/CatchWithUnthrownExceptionRuleTest.php index b72065feddf..ab1b28a8f26 100644 --- a/tests/PHPStan/Rules/Exceptions/CatchWithUnthrownExceptionRuleTest.php +++ b/tests/PHPStan/Rules/Exceptions/CatchWithUnthrownExceptionRuleTest.php @@ -299,6 +299,12 @@ public function testBug4863(): void $this->analyse([__DIR__ . '/data/bug-4863.php'], []); } + #[RequiresPhp('>= 8.5.0')] + public function testFilterVarThrowOnFailure(): void + { + $this->analyse([__DIR__ . '/data/filter-var-throw-on-failure.php'], []); + } + #[RequiresPhp('>= 8.0.0')] public function testBug5866(): void { diff --git a/tests/PHPStan/Rules/Exceptions/data/filter-var-throw-on-failure.php b/tests/PHPStan/Rules/Exceptions/data/filter-var-throw-on-failure.php new file mode 100644 index 00000000000..e34f5d5f01b --- /dev/null +++ b/tests/PHPStan/Rules/Exceptions/data/filter-var-throw-on-failure.php @@ -0,0 +1,29 @@ += 8.5 + +declare(strict_types = 1); + +namespace FilterVarThrowOnFailure; + +function validateMac(mixed $value): void +{ + try { + filter_var($value, FILTER_VALIDATE_MAC, FILTER_THROW_ON_FAILURE); + } catch (\Filter\FilterFailedException) { + } +} + +function validateMacWithFlagsArray(mixed $value): void +{ + try { + filter_var($value, FILTER_VALIDATE_MAC, ['flags' => FILTER_THROW_ON_FAILURE]); + } catch (\Filter\FilterFailedException) { + } +} + +function validateInt(mixed $value): void +{ + try { + filter_var($value, FILTER_VALIDATE_INT, FILTER_THROW_ON_FAILURE); + } catch (\Filter\FilterFailedException) { + } +}