Skip to content

Commit 924f173

Browse files
authored
Non-numeric strings in pow() lead to error
1 parent e1f64f2 commit 924f173

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

src/Type/ExponentiateHelper.php

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
use PHPStan\Type\Constant\ConstantIntegerType;
77
use function is_float;
88
use function is_int;
9+
use function is_numeric;
10+
use function is_string;
11+
use function pow;
912

1013
final class ExponentiateHelper
1114
{
@@ -83,10 +86,16 @@ private static function exponentiateConstantScalar(ConstantScalarType $base, Typ
8386
$min = null;
8487
$max = null;
8588
if ($exponent->getMin() !== null) {
86-
$min = $base->getValue() ** $exponent->getMin();
89+
$min = self::pow($base->getValue(), $exponent->getMin());
90+
if ($min === null) {
91+
return new ErrorType();
92+
}
8793
}
8894
if ($exponent->getMax() !== null) {
89-
$max = $base->getValue() ** $exponent->getMax();
95+
$max = self::pow($base->getValue(), $exponent->getMax());
96+
if ($max === null) {
97+
return new ErrorType();
98+
}
9099
}
91100

92101
if (!is_float($min) && !is_float($max)) {
@@ -95,7 +104,11 @@ private static function exponentiateConstantScalar(ConstantScalarType $base, Typ
95104
}
96105

97106
if ($exponent instanceof ConstantScalarType) {
98-
$result = $base->getValue() ** $exponent->getValue();
107+
$result = self::pow($base->getValue(), $exponent->getValue());
108+
if ($result === null) {
109+
return new ErrorType();
110+
}
111+
99112
if (is_int($result)) {
100113
return new ConstantIntegerType($result);
101114
}
@@ -105,4 +118,15 @@ private static function exponentiateConstantScalar(ConstantScalarType $base, Typ
105118
return null;
106119
}
107120

121+
private static function pow(mixed $base, mixed $exp): float|int|null
122+
{
123+
if (is_string($base) && !is_numeric($base)) {
124+
return null;
125+
}
126+
if (is_string($exp) && !is_numeric($exp)) {
127+
return null;
128+
}
129+
return pow($base, $exp);
130+
}
131+
108132
}

tests/PHPStan/Analyser/nsrt/pow.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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)