mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
Fix #4910 - don’t allow array_merge to create massive keyed arrays
This commit is contained in:
parent
78ed9404cb
commit
2ebf97b4cb
@ -38,6 +38,8 @@ class ArrayMergeReturnTypeProvider implements \Psalm\Plugin\EventHandler\Functio
|
||||
$all_nonempty_lists = true;
|
||||
$any_nonempty = false;
|
||||
|
||||
$max_keyed_array_size = 0;
|
||||
|
||||
foreach ($call_args as $call_arg) {
|
||||
if (!($call_arg_type = $statements_source->node_data->getType($call_arg->value))) {
|
||||
return Type::getArray();
|
||||
@ -77,6 +79,11 @@ class ArrayMergeReturnTypeProvider implements \Psalm\Plugin\EventHandler\Functio
|
||||
}
|
||||
|
||||
if ($unpacked_type_part instanceof Type\Atomic\TKeyedArray) {
|
||||
$max_keyed_array_size = \max(
|
||||
$max_keyed_array_size,
|
||||
count($unpacked_type_part->properties)
|
||||
);
|
||||
|
||||
foreach ($unpacked_type_part->properties as $key => $type) {
|
||||
if (!\is_string($key)) {
|
||||
$generic_properties[] = $type;
|
||||
@ -185,7 +192,13 @@ class ArrayMergeReturnTypeProvider implements \Psalm\Plugin\EventHandler\Functio
|
||||
$inner_value_type = TypeCombiner::combine($inner_value_types, $codebase, true);
|
||||
}
|
||||
|
||||
if ($generic_properties) {
|
||||
$generic_property_count = count($generic_properties);
|
||||
|
||||
if ($generic_properties
|
||||
&& $generic_property_count < 64
|
||||
&& ($generic_property_count < $max_keyed_array_size * 2
|
||||
|| $generic_property_count < 16)
|
||||
) {
|
||||
$objectlike = new Type\Atomic\TKeyedArray($generic_properties);
|
||||
|
||||
if ($all_nonempty_lists || $all_int_offsets) {
|
||||
|
@ -134,6 +134,27 @@ class ForTest extends \Psalm\Tests\TestCase
|
||||
for ($i = 20; $arr[$i] === 5 && $i > 0; $i--) {}
|
||||
}'
|
||||
],
|
||||
'noCrashOnLongThing' => [
|
||||
'<?php
|
||||
/**
|
||||
* @param list<array{a: array{int, int}}> $data
|
||||
*/
|
||||
function makeData(array $data) : array {
|
||||
while (rand(0, 1)) {
|
||||
while (rand(0, 1)) {
|
||||
while (rand(0, 1)) {
|
||||
if (rand(0, 1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data[0]["a"] = array_merge($data[0]["a"], $data[0]["a"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user