Skip to content

Commit 660195b

Browse files
committed
fix: use utils function, return point, allow numeric-string
1 parent fb30cd7 commit 660195b

File tree

1 file changed

+31
-13
lines changed

1 file changed

+31
-13
lines changed

src/Type/Php/PregSplitDynamicReturnTypeExtension.php

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace PHPStan\Type\Php;
44

5+
use Nette\Utils\RegexpException;
6+
use Nette\Utils\Strings;
57
use PhpParser\Node\Expr\FuncCall;
68
use PHPStan\Analyser\Scope;
79
use PHPStan\Reflection\FunctionReflection;
@@ -27,7 +29,6 @@
2729
use function count;
2830
use function is_array;
2931
use function is_int;
30-
use function preg_match;
3132
use function preg_split;
3233
use function strtolower;
3334

@@ -57,23 +58,29 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
5758
$flagArg = $args[3] ?? null;
5859
$patternType = $scope->getType($patternArg->value);
5960
$patternConstantTypes = $patternType->getConstantStrings();
61+
if (count($patternConstantTypes) > 0) {
62+
foreach ($patternConstantTypes as $patternConstantType) {
63+
try {
64+
Strings::match('', $patternConstantType->getValue());
65+
} catch (RegexpException $e) {
66+
return new ErrorType();
67+
}
68+
}
69+
}
70+
6071
$subjectType = $scope->getType($subjectArg->value);
6172
$subjectConstantTypes = $subjectType->getConstantStrings();
6273

63-
if (
64-
count($patternConstantTypes) > 0
65-
&& @preg_match($patternConstantTypes[0]->getValue(), '') === false
66-
) {
67-
return new ErrorType();
68-
}
69-
7074
$limits = [];
7175
if ($limitArg === null) {
7276
$limits = [-1];
7377
} else {
7478
$limitType = $scope->getType($limitArg->value);
79+
if (!$limitType->isInteger()->yes() && !$limitType->isString()->yes()) {
80+
return new ErrorType();
81+
}
7582
foreach ($limitType->getConstantScalarValues() as $limit) {
76-
if (!is_int($limit)) {
83+
if (!is_int($limit) && !is_numeric($limit)) {
7784
return new ErrorType();
7885
}
7986
$limits[] = $limit;
@@ -85,15 +92,18 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
8592
$flags = [0];
8693
} else {
8794
$flagType = $scope->getType($flagArg->value);
95+
if (!$flagType->isInteger()->yes() && !$flagType->isString()->yes()) {
96+
return new ErrorType();
97+
}
8898
foreach ($flagType->getConstantScalarValues() as $flag) {
89-
if (!is_int($flag)) {
99+
if (!is_int($flag) && !is_numeric($flag)) {
90100
return new ErrorType();
91101
}
92102
$flags[] = $flag;
93103
}
94104
}
95105

96-
if (count($patternConstantTypes) === 0 || count($subjectConstantTypes) === 0) {
106+
if ($this->isPatternOrSubjectEmpty($patternConstantTypes, $subjectConstantTypes)) {
97107
$returnNonEmptyStrings = $flagArg !== null && $this->bitwiseFlagAnalyser->bitwiseOrContainsConstant($flagArg->value, $scope, 'PREG_SPLIT_NO_EMPTY')->yes();
98108
if ($returnNonEmptyStrings) {
99109
$returnStringType = TypeCombinator::intersect(
@@ -148,9 +158,9 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
148158
foreach ($subjectConstantTypes as $subjectConstantType) {
149159
foreach ($limits as $limit) {
150160
foreach ($flags as $flag) {
151-
$result = @preg_split($patternConstantType->getValue(), $subjectConstantType->getValue(), $limit, $flag);
161+
$result = @preg_split($patternConstantType->getValue(), $subjectConstantType->getValue(), (int)$limit, (int)$flag);
152162
if ($result === false) {
153-
continue;
163+
return new ErrorType();
154164
}
155165
$constantArray = ConstantArrayTypeBuilder::createEmpty();
156166
foreach ($result as $key => $value) {
@@ -174,4 +184,12 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
174184
return TypeCombinator::union(...$resultTypes);
175185
}
176186

187+
/**
188+
* @param ConstantStringType[] $patternConstantArray
189+
* @param ConstantStringType[] $subjectConstantArray
190+
* @return bool
191+
*/
192+
private function isPatternOrSubjectEmpty(array $patternConstantArray, array $subjectConstantArray): bool {
193+
return count($patternConstantArray) === 0 || count($subjectConstantArray) === 0;
194+
}
177195
}

0 commit comments

Comments
 (0)