diff --git a/src/Type/Php/NonEmptyStringFunctionsReturnTypeExtension.php b/src/Type/Php/NonEmptyStringFunctionsReturnTypeExtension.php index a2e61f194f..4c1c78ca2a 100644 --- a/src/Type/Php/NonEmptyStringFunctionsReturnTypeExtension.php +++ b/src/Type/Php/NonEmptyStringFunctionsReturnTypeExtension.php @@ -31,7 +31,6 @@ public function isFunctionSupported(FunctionReflection $functionReflection): boo 'preg_quote', 'rawurlencode', 'rawurldecode', - 'vsprintf', ], true); } diff --git a/src/Type/Php/SprintfFunctionDynamicReturnTypeExtension.php b/src/Type/Php/SprintfFunctionDynamicReturnTypeExtension.php index 79a1cf88e0..627759ab54 100644 --- a/src/Type/Php/SprintfFunctionDynamicReturnTypeExtension.php +++ b/src/Type/Php/SprintfFunctionDynamicReturnTypeExtension.php @@ -18,16 +18,18 @@ use function array_key_exists; use function array_shift; use function count; +use function in_array; use function is_string; use function preg_match; use function sprintf; +use function vsprintf; class SprintfFunctionDynamicReturnTypeExtension implements DynamicFunctionReturnTypeExtension { public function isFunctionSupported(FunctionReflection $functionReflection): bool { - return $functionReflection->getName() === 'sprintf'; + return in_array($functionReflection->getName(), ['sprintf', 'vsprintf'], true); } public function getTypeFromFunctionCall( @@ -42,7 +44,6 @@ public function getTypeFromFunctionCall( } $formatType = $scope->getType($args[0]->value); - if ($formatType instanceof ConstantStringType) { // The printf format is %[argnum$][flags][width][.precision] if (preg_match('/^%([0-9]*\$)?[0-9]*\.?[0-9]*[bdeEfFgGhHouxX]$/', $formatType->getValue(), $matches) === 1) { @@ -83,7 +84,11 @@ public function getTypeFromFunctionCall( } try { - $value = @sprintf($format, ...$values); + if ($functionReflection->getName() === 'sprintf') { + $value = @sprintf($format, ...$values); + } else { + $value = @vsprintf($format, $values); + } } catch (Throwable) { return $returnType; } diff --git a/tests/PHPStan/Analyser/data/bug-7387.php b/tests/PHPStan/Analyser/data/bug-7387.php index ddfa237ae4..411bef4f87 100644 --- a/tests/PHPStan/Analyser/data/bug-7387.php +++ b/tests/PHPStan/Analyser/data/bug-7387.php @@ -72,4 +72,14 @@ public function escapedPercent(int $i) { // https://3v4l.org/2m50L assertType('non-empty-string', sprintf("%%d", $i)); } + + public function vsprintf(array $array) + { + assertType('numeric-string', vsprintf("%4d", explode('-', '1988-8-1'))); + assertType('numeric-string', vsprintf("%4d", $array)); + assertType('numeric-string', vsprintf("%4d", ['123'])); + assertType('non-empty-string', vsprintf("%s", ['123'])); + // too many arguments.. php silently allows it + assertType('numeric-string', vsprintf("%4d", ['123', '456'])); + } }