Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.28% covered (success)
95.28%
121 / 127
55.56% covered (warning)
55.56%
5 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
TaintednessAssignVisitor
95.28% covered (success)
95.28%
121 / 127
55.56% covered (warning)
55.56%
5 / 9
43
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
2
 isRHSArray
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
2.06
 visitArray
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
1 / 1
7
 visitVar
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 visitProp
50.00% covered (danger)
50.00%
2 / 4
0.00% covered (danger)
0.00%
0 / 1
2.50
 visitStaticProp
50.00% covered (danger)
50.00%
2 / 4
0.00% covered (danger)
0.00%
0 / 1
2.50
 maybeAddNumkeyOnAssignmentLHS
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
6
 visitDim
93.33% covered (success)
93.33%
14 / 15
0.00% covered (danger)
0.00%
0 / 1
3.00
 doAssignmentSingleElement
100.00% covered (success)
100.00%
55 / 55
100.00% covered (success)
100.00%
1 / 1
17
1<?php
2
3namespace SecurityCheckPlugin;
4
5use ast\Node;
6use Closure;
7use Phan\CodeBase;
8use Phan\Exception\IssueException;
9use Phan\Exception\NodeException;
10use Phan\Exception\UnanalyzableException;
11use Phan\Language\Context;
12use Phan\Language\Element\GlobalVariable;
13use Phan\Language\Element\Property;
14use Phan\Language\Element\TypedElementInterface;
15use Phan\PluginV3\PluginAwareBaseAnalysisVisitor;
16
17/**
18 * @see \Phan\Analysis\AssignmentVisitor
19 */
20class TaintednessAssignVisitor extends PluginAwareBaseAnalysisVisitor {
21    use TaintednessBaseVisitor;
22
23    /** @var Taintedness */
24    private $rightTaint;
25
26    /** @var Taintedness */
27    private $errorTaint;
28
29    /** @var MethodLinks */
30    private $errorLinks;
31
32    /** @var CausedByLines */
33    private $rightError;
34
35    /** @var MethodLinks */
36    private $rightLinks;
37
38    /** @var bool|null */
39    private $rhsIsArray;
40
41    /** @var Closure|null */
42    private $rhsIsArrayGetter;
43
44    /** @var int */
45    private $dimDepth;
46
47    /**
48     * @inheritDoc
49     * @param Taintedness $rightTaint
50     * @param CausedByLines $rightLines
51     * @param MethodLinks $rightLinks
52     * @param Taintedness $errorTaint
53     * @param MethodLinks $errorLinks
54     * @param Closure|bool $rhsIsArrayOrGetter
55     * @phan-param Closure():bool|bool $rhsIsArrayOrGetter
56     * @param int $depth
57     */
58    public function __construct(
59        CodeBase $code_base,
60        Context $context,
61        Taintedness $rightTaint,
62        CausedByLines $rightLines,
63        MethodLinks $rightLinks,
64        Taintedness $errorTaint,
65        MethodLinks $errorLinks,
66        $rhsIsArrayOrGetter,
67        int $depth = 0
68    ) {
69        parent::__construct( $code_base, $context );
70        $this->rightTaint = $rightTaint;
71        $this->rightError = $rightLines;
72        $this->rightLinks = $rightLinks;
73        $this->errorTaint = $errorTaint;
74        $this->errorLinks = $errorLinks;
75        if ( is_callable( $rhsIsArrayOrGetter ) ) {
76            $this->rhsIsArrayGetter = $rhsIsArrayOrGetter;
77        } else {
78            $this->rhsIsArray = $rhsIsArrayOrGetter;
79        }
80        $this->dimDepth = $depth;
81    }
82
83    private function isRHSArray(): bool {
84        if ( $this->rhsIsArray !== null ) {
85            return $this->rhsIsArray;
86        }
87        $this->rhsIsArray = ( $this->rhsIsArrayGetter )();
88        return $this->rhsIsArray;
89    }
90
91    /**
92     * @param Node $node
93     */
94    public function visitArray( Node $node ): void {
95        $numKey = 0;
96        foreach ( $node->children as $child ) {
97            if ( $child === null ) {
98                $numKey++;
99                continue;
100            }
101            if ( !$child instanceof Node || $child->kind !== \ast\AST_ARRAY_ELEM ) {
102                // Syntax error.
103                return;
104            }
105            $key = $child->children['key'] !== null ? $this->resolveOffset( $child->children['key'] ) : $numKey++;
106            $value = $child->children['value'];
107            if ( !$value instanceof Node ) {
108                // Syntax error, don't crash, and bail out immediately.
109                return;
110            }
111            $childVisitor = new self(
112                $this->code_base,
113                $this->context,
114                $this->rightTaint->getTaintednessForOffsetOrWhole( $key ),
115                $this->rightError,
116                $this->rightLinks,
117                $this->errorTaint->getTaintednessForOffsetOrWhole( $key ),
118                $this->errorLinks,
119                // @phan-suppress-next-line PhanTypeMismatchArgumentNullable
120                $this->rhsIsArray ?? $this->rhsIsArrayGetter,
121                $this->dimDepth
122            );
123            $childVisitor( $value );
124        }
125    }
126
127    /**
128     * @param Node $node
129     */
130    public function visitVar( Node $node ): void {
131        try {
132            $var = $this->getCtxN( $node )->getVariable();
133        } catch ( NodeException | IssueException $_ ) {
134            return;
135        }
136        $this->doAssignmentSingleElement( $var );
137    }
138
139    /**
140     * @param Node $node
141     */
142    public function visitProp( Node $node ): void {
143        try {