2
2
3
3
namespace PHPStan \Type \Php ;
4
4
5
+ use Nette \Utils \RegexpException ;
6
+ use Nette \Utils \Strings ;
5
7
use PhpParser \Node \Expr \FuncCall ;
6
8
use PHPStan \Analyser \Scope ;
7
9
use PHPStan \Reflection \FunctionReflection ;
27
29
use function count ;
28
30
use function is_array ;
29
31
use function is_int ;
30
- use function preg_match ;
31
32
use function preg_split ;
32
33
use function strtolower ;
33
34
@@ -57,23 +58,29 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
57
58
$ flagArg = $ args [3 ] ?? null ;
58
59
$ patternType = $ scope ->getType ($ patternArg ->value );
59
60
$ 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
+
60
71
$ subjectType = $ scope ->getType ($ subjectArg ->value );
61
72
$ subjectConstantTypes = $ subjectType ->getConstantStrings ();
62
73
63
- if (
64
- count ($ patternConstantTypes ) > 0
65
- && @preg_match ($ patternConstantTypes [0 ]->getValue (), '' ) === false
66
- ) {
67
- return new ErrorType ();
68
- }
69
-
70
74
$ limits = [];
71
75
if ($ limitArg === null ) {
72
76
$ limits = [-1 ];
73
77
} else {
74
78
$ limitType = $ scope ->getType ($ limitArg ->value );
79
+ if (!$ limitType ->isInteger ()->yes () && !$ limitType ->isString ()->yes ()) {
80
+ return new ErrorType ();
81
+ }
75
82
foreach ($ limitType ->getConstantScalarValues () as $ limit ) {
76
- if (!is_int ($ limit )) {
83
+ if (!is_int ($ limit ) && ! is_numeric ( $ limit ) ) {
77
84
return new ErrorType ();
78
85
}
79
86
$ limits [] = $ limit ;
@@ -85,15 +92,18 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
85
92
$ flags = [0 ];
86
93
} else {
87
94
$ flagType = $ scope ->getType ($ flagArg ->value );
95
+ if (!$ flagType ->isInteger ()->yes () && !$ flagType ->isString ()->yes ()) {
96
+ return new ErrorType ();
97
+ }
88
98
foreach ($ flagType ->getConstantScalarValues () as $ flag ) {
89
- if (!is_int ($ flag )) {
99
+ if (!is_int ($ flag ) && ! is_numeric ( $ flag ) ) {
90
100
return new ErrorType ();
91
101
}
92
102
$ flags [] = $ flag ;
93
103
}
94
104
}
95
105
96
- if (count ($ patternConstantTypes) === 0 || count ( $ subjectConstantTypes ) === 0 ) {
106
+ if ($ this -> isPatternOrSubjectEmpty ($ patternConstantTypes, $ subjectConstantTypes )) {
97
107
$ returnNonEmptyStrings = $ flagArg !== null && $ this ->bitwiseFlagAnalyser ->bitwiseOrContainsConstant ($ flagArg ->value , $ scope , 'PREG_SPLIT_NO_EMPTY ' )->yes ();
98
108
if ($ returnNonEmptyStrings ) {
99
109
$ returnStringType = TypeCombinator::intersect (
@@ -148,9 +158,9 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
148
158
foreach ($ subjectConstantTypes as $ subjectConstantType ) {
149
159
foreach ($ limits as $ limit ) {
150
160
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 );
152
162
if ($ result === false ) {
153
- continue ;
163
+ return new ErrorType () ;
154
164
}
155
165
$ constantArray = ConstantArrayTypeBuilder::createEmpty ();
156
166
foreach ($ result as $ key => $ value ) {
@@ -174,4 +184,12 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
174
184
return TypeCombinator::union (...$ resultTypes );
175
185
}
176
186
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
+ }
177
195
}
0 commit comments