From 8f192801c1f380641db5053d433f6037b37c86ce Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Wed, 16 Dec 2020 08:18:18 -0500 Subject: [PATCH] Prevent mixed array offset in array creation Fixes #4846 --- .../Statements/Expression/ArrayAnalyzer.php | 48 ++++++++++++++----- tests/ArrayAssignmentTest.php | 18 ++++--- 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/ArrayAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/ArrayAnalyzer.php index d8a11d59c..69f5d2729 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/ArrayAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/ArrayAnalyzer.php @@ -8,6 +8,7 @@ use Psalm\CodeLocation; use Psalm\Context; use Psalm\Issue\DuplicateArrayKey; use Psalm\Issue\InvalidArrayOffset; +use Psalm\Issue\MixedArrayOffset; use Psalm\IssueBuffer; use Psalm\Type; use Psalm\Internal\Type\TypeCombiner; @@ -130,6 +131,25 @@ class ArrayAnalyzer $good_types = []; foreach ($item_key_type->getAtomicTypes() as $atomic_key_type) { + if ($atomic_key_type instanceof Type\Atomic\TMixed) { + if (IssueBuffer::accepts( + new MixedArrayOffset( + 'Cannot create mixed offset – expecting array-key', + new CodeLocation($statements_analyzer->getSource(), $stmt) + ), + $statements_analyzer->getSuppressedIssues() + )) { + // do nothing + } + + $bad_types[] = $atomic_key_type; + + $good_types[] = new Type\Atomic\TArrayKey; + + + continue; + } + if (!$atomic_key_type instanceof Type\Atomic\TString && !$atomic_key_type instanceof Type\Atomic\TInt && !$atomic_key_type instanceof Type\Atomic\TArrayKey @@ -146,20 +166,22 @@ class ArrayAnalyzer ), $statements_analyzer->getSuppressedIssues() )) { - $bad_types[] = $atomic_key_type; + // do nothing + } - if ($atomic_key_type instanceof Type\Atomic\TFalse) { - $good_types[] = new Type\Atomic\TLiteralInt(0); - } elseif ($atomic_key_type instanceof Type\Atomic\TTrue) { - $good_types[] = new Type\Atomic\TLiteralInt(1); - } elseif ($atomic_key_type instanceof Type\Atomic\TBool) { - $good_types[] = new Type\Atomic\TLiteralInt(0); - $good_types[] = new Type\Atomic\TLiteralInt(1); - } elseif ($atomic_key_type instanceof Type\Atomic\TFloat) { - $good_types[] = new Type\Atomic\TInt; - } else { - $good_types[] = new Type\Atomic\TArrayKey; - } + $bad_types[] = $atomic_key_type; + + if ($atomic_key_type instanceof Type\Atomic\TFalse) { + $good_types[] = new Type\Atomic\TLiteralInt(0); + } elseif ($atomic_key_type instanceof Type\Atomic\TTrue) { + $good_types[] = new Type\Atomic\TLiteralInt(1); + } elseif ($atomic_key_type instanceof Type\Atomic\TBool) { + $good_types[] = new Type\Atomic\TLiteralInt(0); + $good_types[] = new Type\Atomic\TLiteralInt(1); + } elseif ($atomic_key_type instanceof Type\Atomic\TFloat) { + $good_types[] = new Type\Atomic\TInt; + } else { + $good_types[] = new Type\Atomic\TArrayKey; } } } diff --git a/tests/ArrayAssignmentTest.php b/tests/ArrayAssignmentTest.php index 9b0e5125b..0d348f28c 100644 --- a/tests/ArrayAssignmentTest.php +++ b/tests/ArrayAssignmentTest.php @@ -1494,13 +1494,6 @@ class ArrayAssignmentTest extends TestCase return [...$data]; }' ], - 'ArrayCreateOffsetMixed' => [ - ' "a"]; - ', - ], 'ArrayOffsetNumericSupPHPINTMAX' => [ ' 'LessSpecificReturnStatement', ], + 'createArrayWithMixedOffset' => [ + ' 5]; + return $arr; + }', + 'error_message' => 'MixedArrayOffset' + ] ]; } }