mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
Taint arrays in creation
This commit is contained in:
parent
5918278af3
commit
4478d31593
@ -57,6 +57,9 @@ class ArrayAnalyzer
|
||||
|
||||
$all_list = true;
|
||||
|
||||
$taint_sources = [];
|
||||
$either_tainted = 0;
|
||||
|
||||
foreach ($stmt->items as $int_offset => $item) {
|
||||
if ($item === null) {
|
||||
continue;
|
||||
@ -126,6 +129,18 @@ class ArrayAnalyzer
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($codebase->taint) {
|
||||
if (isset($item->value->inferredType)) {
|
||||
$taint_sources = array_merge($taint_sources, $item->value->inferredType->sources ?: []);
|
||||
$either_tainted = $either_tainted | $item->value->inferredType->tainted;
|
||||
}
|
||||
|
||||
if (isset($item->key->inferredType)) {
|
||||
$taint_sources = array_merge($taint_sources, $item->key->inferredType->sources ?: []);
|
||||
$either_tainted = $either_tainted | $item->key->inferredType->tainted;
|
||||
}
|
||||
}
|
||||
|
||||
if ($item->byRef) {
|
||||
$var_id = ExpressionAnalyzer::getArrayVarId(
|
||||
$item->value,
|
||||
@ -207,6 +222,14 @@ class ArrayAnalyzer
|
||||
|
||||
$stmt->inferredType = new Type\Union([$object_like]);
|
||||
|
||||
if ($taint_sources) {
|
||||
$stmt->inferredType->sources = $taint_sources;
|
||||
}
|
||||
|
||||
if ($either_tainted) {
|
||||
$stmt->inferredType->tainted = $either_tainted;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -218,6 +241,14 @@ class ArrayAnalyzer
|
||||
$array_type,
|
||||
]);
|
||||
|
||||
if ($taint_sources) {
|
||||
$stmt->inferredType->sources = $taint_sources;
|
||||
}
|
||||
|
||||
if ($either_tainted) {
|
||||
$stmt->inferredType->tainted = $either_tainted;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -232,6 +263,14 @@ class ArrayAnalyzer
|
||||
$array_type,
|
||||
]);
|
||||
|
||||
if ($taint_sources) {
|
||||
$stmt->inferredType->sources = $taint_sources;
|
||||
}
|
||||
|
||||
if ($either_tainted) {
|
||||
$stmt->inferredType->tainted = $either_tainted;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -264,6 +264,24 @@ class ArrayFetchAnalyzer
|
||||
$context->hasVariable($keyed_array_var_id, $statements_analyzer);
|
||||
}
|
||||
|
||||
if ($codebase->taint && isset($stmt->var->inferredType)) {
|
||||
$sources = [];
|
||||
$either_tainted = 0;
|
||||
|
||||
if (isset($stmt->var->inferredType)) {
|
||||
$sources = array_merge($sources, $stmt->var->inferredType->sources ?: []);
|
||||
$either_tainted = $either_tainted | $stmt->var->inferredType->tainted;
|
||||
}
|
||||
|
||||
if ($sources) {
|
||||
$stmt->inferredType->sources = $sources;
|
||||
}
|
||||
|
||||
if ($either_tainted) {
|
||||
$stmt->inferredType->tainted = $either_tainted;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -770,4 +770,67 @@ class TaintTest extends TestCase
|
||||
|
||||
$this->analyzeFile('somefile.php', new Context());
|
||||
}
|
||||
|
||||
public function testTaintIntoExecMultipleConcat() : void
|
||||
{
|
||||
$this->expectException(\Psalm\Exception\CodeException::class);
|
||||
$this->expectExceptionMessage('TaintedInput');
|
||||
|
||||
$this->project_analyzer->trackTaintedInputs();
|
||||
|
||||
$this->addFile(
|
||||
'somefile.php',
|
||||
'<?php
|
||||
function foo() : void {
|
||||
$a = "9" . "a" . "b" . "c" . ((string) $_GET["bad"]) . "d" . "e" . "f";
|
||||
exec($a);
|
||||
}'
|
||||
);
|
||||
|
||||
$this->analyzeFile('somefile.php', new Context());
|
||||
}
|
||||
|
||||
public function testTaintIntoNestedArrayUnnestedSeparately() : void
|
||||
{
|
||||
$this->expectException(\Psalm\Exception\CodeException::class);
|
||||
$this->expectExceptionMessage('TaintedInput');
|
||||
|
||||
$this->project_analyzer->trackTaintedInputs();
|
||||
|
||||
$this->addFile(
|
||||
'somefile.php',
|
||||
'<?php
|
||||
function foo() : void {
|
||||
$a = [[(string) $_GET["bad"]]];
|
||||
exec($a[0][0]);
|
||||
}'
|
||||
);
|
||||
|
||||
$this->analyzeFile('somefile.php', new Context());
|
||||
}
|
||||
|
||||
public function testTaintIntoArrayAndThenOutAgain() : void
|
||||
{
|
||||
$this->expectException(\Psalm\Exception\CodeException::class);
|
||||
$this->expectExceptionMessage('TaintedInput');
|
||||
|
||||
$this->project_analyzer->trackTaintedInputs();
|
||||
|
||||
$this->addFile(
|
||||
'somefile.php',
|
||||
'<?php
|
||||
class C {
|
||||
public static function foo() : array {
|
||||
$a = (string) $_GET["bad"];
|
||||
return [$a];
|
||||
}
|
||||
|
||||
public static function bar() {
|
||||
exec(self::foo()[0]);
|
||||
}
|
||||
}'
|
||||
);
|
||||
|
||||
$this->analyzeFile('somefile.php', new Context());
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user