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

Exit early when encountering complicated conditionals

This commit is contained in:
Matthew Brown 2019-01-08 09:02:41 -05:00
parent 370874d9b6
commit fb83da94bd
3 changed files with 88 additions and 6 deletions

View File

@ -0,0 +1,6 @@
<?php
namespace Psalm\Exception;
class ComplicatedExpressionException extends \Exception
{
}

View File

@ -3,6 +3,7 @@ namespace Psalm\Type;
use PhpParser;
use Psalm\Codebase;
use Psalm\Exception\ComplicatedExpressionException;
use Psalm\Internal\Analyzer\Statements\Expression\AssertionFinder;
use Psalm\Internal\Clause;
use Psalm\CodeLocation;
@ -12,6 +13,9 @@ use Psalm\Type\Algebra;
class Algebra
{
/** @var int */
private static $clause_count = 0;
/**
* @param array<string, array<int, array<int, string>>> $all_types
*
@ -342,8 +346,8 @@ class Algebra
*/
private static function groupImpossibilities(array $clauses)
{
if (count($clauses) > 5000) {
return [];
if (static::$clause_count > 500) {
throw new ComplicatedExpressionException();
}
$clause = array_shift($clauses);
@ -353,8 +357,8 @@ class Algebra
if ($clauses) {
$grouped_clauses = self::groupImpossibilities($clauses);
if (count($grouped_clauses) > 5000) {
return [];
if (static::$clause_count > 500) {
throw new ComplicatedExpressionException();
}
foreach ($grouped_clauses as $grouped_clause) {
@ -375,6 +379,8 @@ class Algebra
$new_clause = new Clause($new_clause_possibilities, false, true, true);
$new_clauses[] = $new_clause;
self::$clause_count++;
}
}
}
@ -388,6 +394,8 @@ class Algebra
$new_clause = new Clause([$var => [$impossible_type]]);
$new_clauses[] = $new_clause;
self::$clause_count++;
}
}
}
@ -500,12 +508,22 @@ class Algebra
*/
public static function negateFormula(array $clauses)
{
if (count($clauses) > 1000) {
return [];
}
self::$clause_count = 0;
foreach ($clauses as $clause) {
self::calculateNegation($clause);
}
$negated = self::simplifyCNF(self::groupImpossibilities($clauses));
return $negated;
try {
$negated = self::simplifyCNF(self::groupImpossibilities($clauses));
return $negated;
} catch (ComplicatedExpressionException $e) {
return [];
}
}
/**

View File

@ -826,6 +826,64 @@ class TypeAlgebraTest extends TestCase
$array = [$x => 2];
echo $array["_a"];',
],
'noMemoryIssueWithLongConditional' => [
'<?php
function foo(int $c) : string {
if (!($c >= 0x5be && $c <= 0x10b7f)) {
return "LTR";
}
if ($c <= 0x85e) {
if ($c === 0x5be ||
$c === 0x5c0 ||
$c === 0x5c3 ||
$c === 0x5c6 ||
($c >= 0x5d0 && $c <= 0x5ea) ||
($c >= 0x5f0 && $c <= 0x5f4) ||
$c === 0x608 ||
($c >= 0x712 && $c <= 0x72f) ||
($c >= 0x74d && $c <= 0x7a5) ||
$c === 0x7b1 ||
($c >= 0x7c0 && $c <= 0x7ea) ||
($c >= 0x7f4 && $c <= 0x7f5) ||
$c === 0x7fa ||
($c >= 0x800 && $c <= 0x815) ||
$c === 0x81a ||
$c === 0x824 ||
$c === 0x828 ||
($c >= 0x830 && $c <= 0x83e) ||
($c >= 0x840 && $c <= 0x858) ||
$c === 0x85e
) {
return "RTL";
}
} elseif ($c === 0x200f) {
return "RTL";
} elseif ($c >= 0xfb1d) {
if ($c === 0xfb1d ||
($c >= 0xfb1f && $c <= 0xfb28) ||
($c >= 0xfb2a && $c <= 0xfb36) ||
($c >= 0xfb38 && $c <= 0xfb3c) ||
$c === 0xfb3e ||
($c >= 0x10a10 && $c <= 0x10a13) ||
($c >= 0x10a15 && $c <= 0x10a17) ||
($c >= 0x10a19 && $c <= 0x10a33) ||
($c >= 0x10a40 && $c <= 0x10a47) ||
($c >= 0x10a50 && $c <= 0x10a58) ||
($c >= 0x10a60 && $c <= 0x10a7f) ||
($c >= 0x10b00 && $c <= 0x10b35) ||
($c >= 0x10b40 && $c <= 0x10b55) ||
($c >= 0x10b58 && $c <= 0x10b72) ||
($c >= 0x10b78 && $c <= 0x10b7f)
) {
return "RTL";
}
}
return "LTR";
}'
],
];
}