Skip to content

Commit

Permalink
Non-numeric strings in pow() lead to error
Browse files Browse the repository at this point in the history
  • Loading branch information
staabm committed Dec 4, 2023
1 parent 4898ffd commit cb3d887
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 10 deletions.
13 changes: 10 additions & 3 deletions src/Type/ExponentiateHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Type;

use PHPStan\Type\Accessory\AccessoryNumericStringType;
use PHPStan\Type\Constant\ConstantFloatType;
use PHPStan\Type\Constant\ConstantIntegerType;
use function is_float;
Expand All @@ -24,14 +25,20 @@ public static function exponentiate(Type $base, Type $exponent): Type
return new NeverType();
}

$allowedExponentTypes = new UnionType([
$allowedOperandTypes = new UnionType([
new IntegerType(),
new FloatType(),
new StringType(),
new IntersectionType([
new StringType(),
new AccessoryNumericStringType(),
]),
new BooleanType(),
new NullType(),
]);
if (!$allowedExponentTypes->isSuperTypeOf($exponent)->yes()) {
if (!$allowedOperandTypes->isSuperTypeOf($exponent)->yes()) {
return new ErrorType();
}
if (!$allowedOperandTypes->isSuperTypeOf($base)->yes()) {
return new ErrorType();
}

Expand Down
34 changes: 27 additions & 7 deletions tests/PHPStan/Analyser/data/pow.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ function doFoo(int $intA, int $intB, string $s, bool $bool, $numericS, float $fl
assertType('int', pow($intA, 1));
assertType('int', $intA ** '1');

assertType('(float|int)', pow($intA, $s));
assertType('(float|int)', $intA ** $s);
assertType('*ERROR*', pow($intA, $s));
assertType('*ERROR*', $intA ** $s);

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

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

assertType('1', pow($s, 0));
assertType('1', $s ** '0');
assertType('1', $s ** false);
assertType('(float|int)', pow($s, 1));
assertType('(float|int)', $s ** '1');
assertType('*ERROR*', pow($s, 0));
assertType('*ERROR*', $s ** '0');
assertType('*ERROR*', $s ** false);
assertType('*ERROR*', pow($s, 1));
assertType('*ERROR*', $s ** '1');
assertType('*ERROR*', $s ** $arr);
assertType('*ERROR*', $s ** []);

Expand All @@ -177,3 +177,23 @@ function doFoo(int $intA, int $intB, string $s, bool $bool, $numericS, float $fl
assertType('*ERROR*', $bool ** $arr);
assertType('*ERROR*', $bool ** []);
};

function invalidConstantOperands(): void {
assertType('*ERROR*', 'a' ** 1);
assertType('*ERROR*', 1 ** 'a');

assertType('*ERROR*', [] ** 1);
assertType('*ERROR*', 1 ** []);

assertType('*ERROR*', (new \stdClass()) ** 1);
assertType('*ERROR*', 1 ** (new \stdClass()));
}

function validConstantOperands(): void {
assertType('1', '1' ** 1);
assertType('1', 1 ** '1');
assertType('1', '1' ** '1');

assertType('1', true ** 1);
assertType('1', 1 ** false);
}

0 comments on commit cb3d887

Please sign in to comment.