Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
95.28% |
121 / 127 |
|
55.56% |
5 / 9 |
CRAP | |
0.00% |
0 / 1 |
TaintednessAssignVisitor | |
95.28% |
121 / 127 |
|
55.56% |
5 / 9 |
43 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
2 | |||
isRHSArray | |
75.00% |
3 / 4 |
|
0.00% |
0 / 1 |
2.06 | |||
visitArray | |
100.00% |
23 / 23 |
|
100.00% |
1 / 1 |
7 | |||
visitVar | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
visitProp | |
50.00% |
2 / 4 |
|
0.00% |
0 / 1 |
2.50 | |||
visitStaticProp | |
50.00% |
2 / 4 |
|
0.00% |
0 / 1 |
2.50 | |||
maybeAddNumkeyOnAssignmentLHS | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
6 | |||
visitDim | |
93.33% |
14 / 15 |
|
0.00% |
0 / 1 |
3.00 | |||
doAssignmentSingleElement | |
100.00% |
55 / 55 |
|
100.00% |
1 / 1 |
17 |
1 | <?php |
2 | |
3 | namespace SecurityCheckPlugin; |
4 | |
5 | use ast\Node; |
6 | use Closure; |
7 | use Phan\CodeBase; |
8 | use Phan\Exception\IssueException; |
9 | use Phan\Exception\NodeException; |
10 | use Phan\Exception\UnanalyzableException; |
11 | use Phan\Language\Context; |
12 | use Phan\Language\Element\GlobalVariable; |
13 | use Phan\Language\Element\Property; |
14 | use Phan\Language\Element\TypedElementInterface; |
15 | use Phan\PluginV3\PluginAwareBaseAnalysisVisitor; |
16 | |
17 | /** |
18 | * @see \Phan\Analysis\AssignmentVisitor |
19 | */ |
20 | class 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 { |