1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 04:45:20 +01:00

Fix Uncaught TypeError with some shifts

This commit is contained in:
BafS 2021-06-11 19:49:05 +02:00
parent cf6a4e70c5
commit dde0f1fb06
No known key found for this signature in database
GPG Key ID: BDA2FEE6CBF7990A
2 changed files with 26 additions and 12 deletions

View File

@ -273,6 +273,19 @@ class NonDivArithmeticOpAnalyzer
}
}
/**
* @param int|float $result
*/
private static function getNumericalType($result): Type\Union
{
if ($result <= PHP_INT_MAX && $result >= PHP_INT_MIN) {
/** @var int $result */
return Type::getInt(false, $result);
}
return Type::getFloat($result);
}
/**
* @param string[] &$invalid_left_messages
* @param string[] &$invalid_right_messages
@ -309,25 +322,19 @@ class NonDivArithmeticOpAnalyzer
$calculated_type = null;
if ($parent instanceof PhpParser\Node\Expr\BinaryOp\Plus) {
$calculated_type = Type::getInt(false, $left_type_part->value + $right_type_part->value);
$result = $left_type_part->value + $right_type_part->value;
$calculated_type = self::getNumericalType($result);
} elseif ($parent instanceof PhpParser\Node\Expr\BinaryOp\Minus) {
$calculated_type = Type::getInt(false, $left_type_part->value - $right_type_part->value);
$result = $left_type_part->value - $right_type_part->value;
$calculated_type = self::getNumericalType($result);
} elseif ($parent instanceof PhpParser\Node\Expr\BinaryOp\Mod) {
$calculated_type = Type::getInt(false, $left_type_part->value % $right_type_part->value);
} elseif ($parent instanceof PhpParser\Node\Expr\BinaryOp\Mul) {
$result = $left_type_part->value * $right_type_part->value;
if ($result <= PHP_INT_MAX) {
$calculated_type = Type::getInt(false, $result);
} else {
$calculated_type = Type::getFloat($result);
}
$calculated_type = self::getNumericalType($result);
} elseif ($parent instanceof PhpParser\Node\Expr\BinaryOp\Pow) {
$result = $left_type_part->value ** $right_type_part->value;
if ($result <= PHP_INT_MAX) {
$calculated_type = Type::getInt(false, $result);
} else {
$calculated_type = Type::getFloat($result);
}
$calculated_type = self::getNumericalType($result);
} elseif ($parent instanceof PhpParser\Node\Expr\BinaryOp\BitwiseOr) {
$calculated_type = Type::getInt(false, $left_type_part->value | $right_type_part->value);
} elseif ($parent instanceof PhpParser\Node\Expr\BinaryOp\BitwiseAnd) {

View File

@ -532,6 +532,13 @@ class BinaryOperationTest extends TestCase
'$a' => 'float'
],
],
'IntOverflowSub' => [
'<?php
$a = (1 << 63) - (1 << 20);',
'assertions' => [
'$a' => 'float'
],
],
];
}