Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cover vsprintf() #1441

Merged
merged 2 commits into from Jun 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -31,7 +31,6 @@ public function isFunctionSupported(FunctionReflection $functionReflection): boo
'preg_quote',
'rawurlencode',
'rawurldecode',
'vsprintf',
], true);
}

Expand Down
11 changes: 8 additions & 3 deletions src/Type/Php/SprintfFunctionDynamicReturnTypeExtension.php
Expand Up @@ -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(
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand Down
10 changes: 10 additions & 0 deletions tests/PHPStan/Analyser/data/bug-7387.php
Expand Up @@ -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']));
}
}