Skip to content

Commit e0f2c89

Browse files
authored
fix sscanf() inference with regex format patterns
1 parent 5a69ee2 commit e0f2c89

File tree

4 files changed

+55
-1
lines changed

4 files changed

+55
-1
lines changed

src/Type/Php/SscanfFunctionDynamicReturnTypeExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public function getTypeFromFunctionCall(
4545
return null;
4646
}
4747

48-
if (preg_match_all('/%(\d*)([cdeEfosux]{1})/', $formatType->getValue(), $matches) > 0) {
48+
if (preg_match_all('/%(\d*)(\[[^\]]+\]|[cdeEfosux]{1})/', $formatType->getValue(), $matches) > 0) {
4949
$arrayBuilder = ConstantArrayTypeBuilder::createEmpty();
5050

5151
for ($i = 0; $i < count($matches[0]); $i++) {

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,8 @@ public function dataFileAsserts(): iterable
992992
yield from $this->gatherAssertTypes(__DIR__ . '/data/loose-comparisons-php8.php');
993993
}
994994
yield from $this->gatherAssertTypes(__DIR__ . '/data/loose-comparisons.php');
995+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7563.php');
996+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7764.php');
995997
}
996998

997999
/**
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace Bug7563;
4+
5+
declare(strict_types=1);
6+
7+
use function PHPStan\Testing\assertType;
8+
9+
class HelloWorld
10+
{
11+
public static function sayHello(string $dimension): void
12+
{
13+
$result = sscanf($dimension, '%[1234567890.]%s');
14+
assertType('array{string|null, string|null}|null', $result);
15+
}
16+
17+
public static function sayFoo() {
18+
$error = 'TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException [1423347324] at /var/www/html/app/web/typo3/sysext/core/Classes/Resource/ResourceStorage.php:2496: Folder "1203-0110-0008" already exists.';
19+
$exceptionComponents = sscanf($error, '%s [%d] at %[^:]:%d: %[^[]]');
20+
21+
if (null === $exceptionComponents) {
22+
throw new Exception($error);
23+
}
24+
25+
assertType('array{string|null, int|null, string|null, int|null, string|null}', $exceptionComponents);
26+
}
27+
28+
// see https://3v4l.org/Y5T2R
29+
public static function edgeCase(string $dimension): void
30+
{
31+
$result = sscanf($dimension, '%[%[]');
32+
assertType('array{string|null}|null', $result);
33+
}
34+
35+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace Bug7764;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
function doFoo() {
8+
$split = sscanf('hello/world', '%[^/]/%[^/]/%s');
9+
assertType('array{string|null, string|null, string|null}|null', $split);
10+
if (!is_array($split)) {
11+
echo 'Not array', "\n";
12+
} elseif (count($split) > 1) {
13+
echo 'Success', "\n";
14+
}
15+
print_r($split);
16+
}
17+

0 commit comments

Comments
 (0)