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:
parent
10ea05a5a3
commit
6fa0da9e37
@ -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}
|
||||
*/
|
||||
|
@ -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',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user