Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
83.33% covered (warning)
83.33%
75 / 90
72.00% covered (warning)
72.00%
18 / 25
CRAP
0.00% covered (danger)
0.00%
0 / 1
TaintednessBackpropVisitor
83.33% covered (warning)
83.33%
75 / 90
72.00% covered (warning)
72.00%
18 / 25
63.04
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 visitProp
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 visitNullsafeProp
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 visitStaticProp
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 visitVar
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 visitEncapsList
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 visitArray
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 visitArrayElem
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
5
 visitCast
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 visitDim
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 visitUnaryOp
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 visitBinaryOp
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 visitConditional
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 visitCall
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 visitMethodCall
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 visitStaticCall
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 visitNullsafeMethodCall
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 handleCall
55.56% covered (warning)
55.56%
10 / 18
0.00% covered (danger)
0.00%
0 / 1
9.16
 visitPreDec
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 visitPreInc
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 visitPostDec
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 visitPostInc
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 handleIncOrDec
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 recurse
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
 doBackpropElements
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3namespace SecurityCheckPlugin;
4
5use ast\Node;
6use Exception;
7use Phan\CodeBase;
8use Phan\Exception\CodeBaseException;
9use Phan\Exception\FQSENException;
10use Phan\Exception\IssueException;
11use Phan\Exception\NodeException;
12use Phan\Language\Context;
13use Phan\Language\Element\TypedElementInterface;
14use Phan\Language\Element\Variable;
15use Phan\PluginV3\PluginAwareBaseAnalysisVisitor;
16
17class 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