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

Fix minor taint analysis bug with nested array assignment

This commit is contained in:
Matt Brown 2022-06-21 12:42:26 -04:00
parent 10ea05a5a3
commit 6fa0da9e37
2 changed files with 82 additions and 25 deletions

View File

@ -850,30 +850,7 @@ class ArrayAssignmentAnalyzer
throw new InvalidArgumentException('Should never get here');
}
$key_values = [];
if ($current_dim instanceof PhpParser\Node\Scalar\String_) {
$key_values[] = new TLiteralString($current_dim->value);
} elseif ($current_dim instanceof PhpParser\Node\Scalar\LNumber) {
$key_values[] = new TLiteralInt($current_dim->value);
} elseif ($current_dim
&& ($key_type = $statements_analyzer->node_data->getType($current_dim))
) {
$string_literals = $key_type->getLiteralStrings();
$int_literals = $key_type->getLiteralInts();
$all_atomic_types = $key_type->getAtomicTypes();
if (count($string_literals) + count($int_literals) === count($all_atomic_types)) {
foreach ($string_literals as $string_literal) {
$key_values[] = clone $string_literal;
}
foreach ($int_literals as $int_literal) {
$key_values[] = clone $int_literal;
}
}
}
$key_values = $current_dim ? self::getDimKeyValues($statements_analyzer, $current_dim) : [];
if ($key_values) {
$new_child_type = self::updateTypeWithKeyValues(
@ -938,12 +915,49 @@ class ArrayAssignmentAnalyzer
$statements_analyzer->node_data->getType($child_stmt->var) ?? Type::getMixed(),
$new_child_type,
$parent_array_var_id,
$key_values
$child_stmt->dim ? self::getDimKeyValues($statements_analyzer, $child_stmt->dim) : [],
);
}
}
}
/**
* @return list<TLiteralInt|TLiteralString>
*/
private static function getDimKeyValues(
StatementsAnalyzer $statements_analyzer,
PhpParser\Node\Expr $dim,
): array {
$key_values = [];
if ($dim instanceof PhpParser\Node\Scalar\String_) {
$key_values[] = new TLiteralString($dim->value);
} elseif ($dim instanceof PhpParser\Node\Scalar\LNumber) {
$key_values[] = new TLiteralInt($dim->value);
} else {
$key_type = $statements_analyzer->node_data->getType($dim);
if ($key_type) {
$string_literals = $key_type->getLiteralStrings();
$int_literals = $key_type->getLiteralInts();
$all_atomic_types = $key_type->getAtomicTypes();
if (count($string_literals) + count($int_literals) === count($all_atomic_types)) {
foreach ($string_literals as $string_literal) {
$key_values[] = clone $string_literal;
}
foreach ($int_literals as $int_literal) {
$key_values[] = clone $int_literal;
}
}
}
}
return $key_values;
}
/**
* @return array{TLiteralInt|TLiteralString|null, string, bool}
*/

View File

@ -708,6 +708,27 @@ class TaintTest extends TestCase
$value = $_GET["value"];
$result = fetch($value);'
],
'dontTaintArrayWithDifferentOffsetUpdated' => [
'code' => '<?php
function foo() {
$foo = [
"a" => [["c" => "hello"]],
"b" => [],
];
$foo["b"][] = [
"c" => $_GET["bad"],
];
bar($foo["a"]);
}
function bar(array $arr): void {
foreach ($arr as $s) {
echo $s["c"];
}
}'
],
];
}
@ -2306,6 +2327,28 @@ class TaintTest extends TestCase
',
'error_message' => 'TaintedHtml',
],
'taintArrayWithOffsetUpdated' => [
'code' => '<?php
function foo() {
$foo = [
"a" => [["c" => "hello"]],
"b" => [],
];
$foo["b"][] = [
"c" => $_GET["bad"],
];
bar($foo["b"]);
}
function bar(array $arr): void {
foreach ($arr as $s) {
echo $s["c"];
}
}',
'error_message' => 'TaintedHtml',
],
];
}