1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-22 05:41:20 +01:00

Illegal offset (#4865)

* Illegal offset access

* add tests

* fix tests
This commit is contained in:
orklah 2020-12-26 11:33:49 +01:00 committed by Daniil Gentili
parent 9405773882
commit 25e022e77e
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
2 changed files with 79 additions and 16 deletions

View File

@ -393,7 +393,8 @@ class ArrayFetchAnalyzer
$has_array_access = false; $has_array_access = false;
$non_array_types = []; $non_array_types = [];
$has_valid_offset = false; $has_valid_expected_offset = false;
$has_valid_absolute_offset = false;
$expected_offset_types = []; $expected_offset_types = [];
$key_values = []; $key_values = [];
@ -461,6 +462,39 @@ class ArrayFetchAnalyzer
} }
} }
if ($array_type->isArray()) {
foreach ($offset_type->getAtomicTypes() as $atomic_offset_type) {
if ($atomic_offset_type instanceof Type\Atomic\TFalse &&
$offset_type->ignore_falsable_issues === true
) {
//do nothing
} elseif ($atomic_offset_type instanceof Type\Atomic\TNull &&
$offset_type->ignore_nullable_issues === true
) {
//do nothing
} elseif ($atomic_offset_type instanceof Type\Atomic\TString ||
$atomic_offset_type instanceof Type\Atomic\TInt ||
$atomic_offset_type instanceof Type\Atomic\TArrayKey ||
$atomic_offset_type instanceof Type\Atomic\TMixed ||
$atomic_offset_type instanceof Type\Atomic\TTemplateParam ||
(
$atomic_offset_type instanceof Type\Atomic\TObjectWithProperties
&& isset($atomic_offset_type->methods['__toString'])
)
) {
$has_valid_absolute_offset = true;
}
}
if ($has_valid_absolute_offset === false) {
//we didn't find a single type that could be valid
$expected_offset_types[] = 'array-key';
}
} else {
//on not-arrays, the type is considered valid
$has_valid_absolute_offset = true;
}
foreach ($array_type->getAtomicTypes() as $type_string => $type) { foreach ($array_type->getAtomicTypes() as $type_string => $type) {
$original_type = $type; $original_type = $type;
@ -477,7 +511,7 @@ class ArrayFetchAnalyzer
$type $type
); );
$has_valid_offset = true; $has_valid_expected_offset = true;
continue; continue;
} }
@ -557,7 +591,7 @@ class ArrayFetchAnalyzer
$expected_offset_types, $expected_offset_types,
$array_access_type, $array_access_type,
$has_array_access, $has_array_access,
$has_valid_offset $has_valid_expected_offset
); );
continue; continue;
@ -575,7 +609,7 @@ class ArrayFetchAnalyzer
$offset_type, $offset_type,
$expected_offset_types, $expected_offset_types,
$array_access_type, $array_access_type,
$has_valid_offset $has_valid_expected_offset
); );
continue; continue;
@ -707,9 +741,9 @@ class ArrayFetchAnalyzer
$used_offset = 'using offset value of ' . implode('|', $key_values); $used_offset = 'using offset value of ' . implode('|', $key_values);
} }
if ($has_valid_offset && $context->inside_isset) { if ($has_valid_expected_offset && $has_valid_absolute_offset && $context->inside_isset) {
// do nothing // do nothing
} elseif ($has_valid_offset) { } elseif ($has_valid_expected_offset && $has_valid_absolute_offset) {
if (!$context->inside_unset) { if (!$context->inside_unset) {
if (IssueBuffer::accepts( if (IssueBuffer::accepts(
new PossiblyInvalidArrayOffset( new PossiblyInvalidArrayOffset(

View File

@ -1065,15 +1065,6 @@ class ArrayAssignmentTest extends TestCase
if (is_int($value["a"])) {} if (is_int($value["a"])) {}
}' }'
], ],
'falseArrayAssignment' => [
'<?php
function foo(): array {
$array = [];
$array[false] = "";
echo $array[0];
return $array;
}',
],
'coercePossiblyNullKeyToZero' => [ 'coercePossiblyNullKeyToZero' => [
'<?php '<?php
function int_or_null(): ?int { function int_or_null(): ?int {
@ -1799,24 +1790,52 @@ class ArrayAssignmentTest extends TestCase
', ',
'error_message' => 'InvalidArrayOffset' 'error_message' => 'InvalidArrayOffset'
], ],
'ArrayDimOffsetObject' => [
'<?php
$_a = [];
$_a[new stdClass] = "a";
',
'error_message' => 'InvalidArrayOffset'
],
'ArrayCreateOffsetResource' => [ 'ArrayCreateOffsetResource' => [
'<?php '<?php
$_a = [fopen("", "") => "a"]; $_a = [fopen("", "") => "a"];
', ',
'error_message' => 'InvalidArrayOffset' 'error_message' => 'InvalidArrayOffset'
], ],
'ArrayDimOffsetResource' => [
'<?php
$_a = [];
$_a[fopen("", "")] = "a";
',
'error_message' => 'InvalidArrayOffset'
],
'ArrayCreateOffsetBool' => [ 'ArrayCreateOffsetBool' => [
'<?php '<?php
$_a = [true => "a"]; $_a = [true => "a"];
', ',
'error_message' => 'InvalidArrayOffset' 'error_message' => 'InvalidArrayOffset'
], ],
'ArrayDimOffsetBool' => [
'<?php
$_a = [];
$_a[true] = "a";
',
'error_message' => 'InvalidArrayOffset'
],
'ArrayCreateOffsetStringable' => [ 'ArrayCreateOffsetStringable' => [
'<?php '<?php
$a = new class{public function __toString(){return "";}}; $a = new class{public function __toString(){return "";}};
$_a = [$a => "a"];', $_a = [$a => "a"];',
'error_message' => 'InvalidArrayOffset', 'error_message' => 'InvalidArrayOffset',
], ],
'ArrayDimOffsetStringable' => [
'<?php
$_a = [];
$a = new class{public function __toString(){return "";}};
$_a[$a] = "a";',
'error_message' => 'InvalidArrayOffset',
],
'coerceListToArray' => [ 'coerceListToArray' => [
'<?php '<?php
/** /**
@ -1876,7 +1895,17 @@ class ArrayAssignmentTest extends TestCase
return $arr; return $arr;
}', }',
'error_message' => 'MixedArrayOffset' 'error_message' => 'MixedArrayOffset'
] ],
'falseArrayAssignment' => [
'<?php
function foo(): array {
$array = [];
$array[false] = "";
echo $array[0];
return $array;
}',
'error_message' => 'InvalidArrayOffset'
],
]; ];
} }
} }