diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php index b3b99faee..2f23336ac 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php @@ -646,7 +646,7 @@ class ArrayFetchAnalyzer } elseif ($type instanceof TLiteralString) { $valid_offsets = []; - for ($i = 0, $l = strlen($type->value); $i < $l; $i++) { + for ($i = -strlen($type->value), $l = strlen($type->value); $i < $l; $i++) { $valid_offsets[] = new TLiteralInt($i); } diff --git a/tests/ArrayAccessTest.php b/tests/ArrayAccessTest.php index c58129df2..43243b346 100644 --- a/tests/ArrayAccessTest.php +++ b/tests/ArrayAccessTest.php @@ -319,6 +319,20 @@ class ArrayAccessTest extends TestCase 'assertions' => [], 'error_levels' => ['MixedTypeCoercion'], ], + 'allowNegativeStringOffset' => [ + ' 'TypeDoesNotContainType', ], + 'forbidNegativeStringOffsetOutOfRange' => [ + ' 'InvalidArrayOffset', + ], ]; } }