Skip to content

Commit ba5bdb9

Browse files
committed
Non-numeric strings in pow() lead to error
1 parent e1f64f2 commit ba5bdb9

File tree

2 files changed

+37
-10
lines changed

2 files changed

+37
-10
lines changed

src/Type/ExponentiateHelper.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Type;
44

5+
use PHPStan\Type\Accessory\AccessoryNumericStringType;
56
use PHPStan\Type\Constant\ConstantFloatType;
67
use PHPStan\Type\Constant\ConstantIntegerType;
78
use function is_float;
@@ -24,14 +25,20 @@ public static function exponentiate(Type $base, Type $exponent): Type
2425
return new NeverType();
2526
}
2627

27-
$allowedExponentTypes = new UnionType([
28+
$allowedOperandTypes = new UnionType([
2829
new IntegerType(),
2930
new FloatType(),
30-
new StringType(),
31+
new IntersectionType([
32+
new StringType(),
33+
new AccessoryNumericStringType(),
34+
]),
3135
new BooleanType(),
3236
new NullType(),
3337
]);
34-
if (!$allowedExponentTypes->isSuperTypeOf($exponent)->yes()) {
38+
if (!$allowedOperandTypes->isSuperTypeOf($exponent)->yes()) {
39+
return new ErrorType();
40+
}
41+
if (!$allowedOperandTypes->isSuperTypeOf($base)->yes()) {
3542
return new ErrorType();
3643
}
3744

tests/PHPStan/Analyser/nsrt/pow.php

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ function doFoo(int $intA, int $intB, string $s, bool $bool, $numericS, float $fl
112112
assertType('int', pow($intA, 1));
113113
assertType('int', $intA ** '1');
114114

115-
assertType('(float|int)', pow($intA, $s));
116-
assertType('(float|int)', $intA ** $s);
115+
assertType('*ERROR*', pow($intA, $s));
116+
assertType('*ERROR*', $intA ** $s);
117117

118118
assertType('(float|int)', pow($intA, $bool)); // could be int
119119
assertType('(float|int)', $intA ** $bool); // could be int
@@ -161,11 +161,11 @@ function doFoo(int $intA, int $intB, string $s, bool $bool, $numericS, float $fl
161161

162162
assertType('NAN', pow(-1,5.5));
163163

164-
assertType('1', pow($s, 0));
165-
assertType('1', $s ** '0');
166-
assertType('1', $s ** false);
167-
assertType('(float|int)', pow($s, 1));
168-
assertType('(float|int)', $s ** '1');
164+
assertType('*ERROR*', pow($s, 0));
165+
assertType('*ERROR*', $s ** '0');
166+
assertType('*ERROR*', $s ** false);
167+
assertType('*ERROR*', pow($s, 1));
168+
assertType('*ERROR*', $s ** '1');
169169
assertType('*ERROR*', $s ** $arr);
170170
assertType('*ERROR*', $s ** []);
171171

@@ -177,3 +177,23 @@ function doFoo(int $intA, int $intB, string $s, bool $bool, $numericS, float $fl
177177
assertType('*ERROR*', $bool ** $arr);
178178
assertType('*ERROR*', $bool ** []);
179179
};
180+
181+
function invalidConstantOperands(): void {
182+
assertType('*ERROR*', 'a' ** 1);
183+
assertType('*ERROR*', 1 ** 'a');
184+
185+
assertType('*ERROR*', [] ** 1);
186+
assertType('*ERROR*', 1 ** []);
187+
188+
assertType('*ERROR*', (new \stdClass()) ** 1);
189+
assertType('*ERROR*', 1 ** (new \stdClass()));
190+
}
191+
192+
function validConstantOperands(): void {
193+
assertType('1', '1' ** 1);
194+
assertType('1', 1 ** '1');
195+
assertType('1', '1' ** '1');
196+
197+
assertType('1', true ** 1);
198+
assertType('1', 1 ** false);
199+
}

0 commit comments

Comments
 (0)