diff --git a/src/Type/Php/SprintfFunctionDynamicReturnTypeExtension.php b/src/Type/Php/SprintfFunctionDynamicReturnTypeExtension.php index ea068e19ae..79a1cf88e0 100644 --- a/src/Type/Php/SprintfFunctionDynamicReturnTypeExtension.php +++ b/src/Type/Php/SprintfFunctionDynamicReturnTypeExtension.php @@ -45,7 +45,7 @@ public function getTypeFromFunctionCall( 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) { + if (preg_match('/^%([0-9]*\$)?[0-9]*\.?[0-9]*[bdeEfFgGhHouxX]$/', $formatType->getValue(), $matches) === 1) { // invalid positional argument if (array_key_exists(1, $matches) && $matches[1] === '0$') { return null; diff --git a/tests/PHPStan/Analyser/data/bug-7387.php b/tests/PHPStan/Analyser/data/bug-7387.php index f13038a1ee..ddfa237ae4 100644 --- a/tests/PHPStan/Analyser/data/bug-7387.php +++ b/tests/PHPStan/Analyser/data/bug-7387.php @@ -25,6 +25,8 @@ public function specifiers(int $i) { // https://3v4l.org/fmVIg assertType('non-empty-string', sprintf('%14s', $i)); + assertType('numeric-string', sprintf('%d', $i)); + assertType('numeric-string', sprintf('%14b', $i)); assertType('non-empty-string', sprintf('%14c', $i)); // binary string assertType('numeric-string', sprintf('%14d', $i)); @@ -65,4 +67,9 @@ public function positionalArgs($mixed, int $i, float $f, string $s) { public function invalidPositionalArgFormat($mixed, string $s) { assertType('string', sprintf('%0$14F', $mixed, $s)); } + + public function escapedPercent(int $i) { + // https://3v4l.org/2m50L + assertType('non-empty-string', sprintf("%%d", $i)); + } }