Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
83.33% |
75 / 90 |
|
72.00% |
18 / 25 |
CRAP | |
0.00% |
0 / 1 |
TaintednessBackpropVisitor | |
83.33% |
75 / 90 |
|
72.00% |
18 / 25 |
63.04 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
visitProp | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
visitNullsafeProp | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
visitStaticProp | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
visitVar | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
visitEncapsList | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
3 | |||
visitArray | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
3 | |||
visitArrayElem | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
5 | |||
visitCast | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
visitDim | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
4 | |||
visitUnaryOp | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
visitBinaryOp | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
visitConditional | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
visitCall | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
visitMethodCall | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
visitStaticCall | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
visitNullsafeMethodCall | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
handleCall | |
55.56% |
10 / 18 |
|
0.00% |
0 / 1 |
9.16 | |||
visitPreDec | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
visitPreInc | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
visitPostDec | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
visitPostInc | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
handleIncOrDec | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
recurse | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
2 | |||
doBackpropElements | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace SecurityCheckPlugin; |
4 | |
5 | use ast\Node; |
6 | use Exception; |
7 | use Phan\CodeBase; |
8 | use Phan\Exception\CodeBaseException; |
9 | use Phan\Exception\FQSENException; |
10 | use Phan\Exception\IssueException; |
11 | use Phan\Exception\NodeException; |
12 | use Phan\Language\Context; |
13 | use Phan\Language\Element\TypedElementInterface; |
14 | use Phan\Language\Element\Variable; |
15 | use Phan\PluginV3\PluginAwareBaseAnalysisVisitor; |
16 | |
17 | class TaintednessBackpropVisitor extends PluginAwareBaseAnalysisVisitor { |
18 | use TaintednessBaseVisitor; |
19 | |
20 | /** @var Taintedness */ |
21 | private $taintedness; |
22 | |
23 | /** @var CausedByLines|null */ |
24 | private $additionalError; |
25 | |
26 | /** |
27 | * @inheritDoc |
28 | * @param Taintedness $taintedness |
29 | * @param CausedByLines|null $additionalError |
30 | */ |
31 | public function __construct( |
32 | CodeBase $code_base, |
33 | Context $context, |
34 | Taintedness $taintedness, |
35 | ?CausedByLines $additionalError = null |
36 | ) { |
37 | parent::__construct( $code_base, $context ); |
38 | $this->taintedness = $taintedness; |
39 | $this->additionalError = $additionalError; |
40 | } |
41 | |
42 | /** |
43 | * @inheritDoc |
44 | */ |
45 | public function visitProp( Node $node ): void { |
46 | $this->doBackpropElements( $this->getPropFromNode( $node ) ); |
47 | } |
48 | |
49 | /** |
50 | * @inheritDoc |
51 | */ |
52 | public function visitNullsafeProp( Node $node ): void { |
53 | $this->doBackpropElements( $this->getPropFromNode( $node ) ); |
54 | } |
55 | |
56 | /** |
57 | * @inheritDoc |
58 | */ |
59 | public function visitStaticProp( Node $node ): void { |
60 | $this->doBackpropElements( $this->getPropFromNode( $node ) ); |
61 | } |
62 | |
63 | /** |
64 | * @inheritDoc |
65 | */ |
66 | public function visitVar( Node $node ): void { |
67 | $cn = $this->getCtxN( $node ); |
68 | if ( Variable::isHardcodedGlobalVariableWithName( $cn->getVariableName() ) ) { |
69 | return; |
70 | } |
71 | try { |
72 | $this->doBackpropElements( $cn->getVariable() ); |
73 | } catch ( NodeException | IssueException $e ) { |
74 | $this->debug( __METHOD__, "variable not in scope?? " . $this->getDebugInfo( $e ) ); |
75 | } |
76 | } |
77 | |
78 | /** |
79 | * @inheritDoc |
80 | */ |
81 | public function visitEncapsList( Node $node ): void { |
82 | foreach ( $node->children as $child ) { |
83 | if ( $child instanceof Node ) { |
84 | $this->recurse( $child ); |
85 | } |
86 | } |
87 | } |
88 | |
89 | /** |
90 | * @inheritDoc |
91 | */ |
92 | public function visitArray( Node $node ): void { |
93 | foreach ( $node->children as $child ) { |
94 | if ( $child instanceof Node ) { |
95 | $this->recurse( $child ); |
96 | } |
97 | } |
98 | } |
99 | |
100 | /** |
101 | * @inheritDoc |
102 | */ |
103 | public function visitArrayElem( Node $node ): void { |
104 | $key = $node->children['key']; |
105 | if ( $key instanceof Node ) { |
106 | $this->recurse( |
107 | $key, |
108 | $this->taintedness->asKeyForForeach(), |
109 | $this->additionalError ? $this->additionalError->asAllKeyForForeach() : null |
110 | ); |
111 | } |
112 | $value = $node->children['value']; |
113 | if ( $value instanceof Node ) { |
114 | $this->recurse( |
115 | $value, |
116 | $this->taintedness->getTaintednessForOffsetOrWhole( $key ), |
117 | $this->additionalError ? $this->additionalError->getForDim( $key ) : null |
118 | ); |
119 | } |
120 | } |
121 | |
122 | /** |
123 | * @inheritDoc |
124 | */ |
125 | public function visitCast( Node $node ): void { |
126 | // Future todo might be to ignore casts to ints, since |
127 | // such things should be safe. Unclear if that makes |
128 | // sense in all circumstances. |
129 | if ( $node->children['expr'] instanceof Node ) { |
130 | $this->recurse( $node->children['expr'] ); |
131 | } |
132 | } |
133 | |
134 | /** |
135 | * @inheritDoc |
136 | */ |
137 | public function visitDim( Node $node ): void { |
138 | if ( $node->children['expr'] instanceof Node ) { |
139 | // For now just consider the outermost array. |
140 | // FIXME. doesn't handle tainted array keys! |
141 | $offs = $node->children['dim']; |
142 | $realOffs = $offs !== null ? $this->resolveOffset( $offs ) : null; |
143 | $this->recurse( |
144 | $node->children['expr'], |
145 | $this->taintedness->asMaybeMovedAtOffset( $realOffs ), |
146 | $this->additionalError ? $this->additionalError->asAllMaybeMovedAtOffset( $realOffs ) : null |