Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
88.06% covered (warning)
88.06%
1210 / 1374
68.33% covered (warning)
68.33%
41 / 60
CRAP
0.00% covered (danger)
0.00%
0 / 1
TaintednessBaseVisitor
88.06% covered (warning)
88.06%
1210 / 1374
68.33% covered (warning)
68.33%
41 / 60
941.38
0.00% covered (danger)
0.00%
0 / 1
 addFuncTaint
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 ensureFuncTaintIsSet
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 maybeAddFuncError
100.00% covered (success)
100.00%
40 / 40
100.00% covered (success)
100.00%
1 / 1
22
 mergeFuncError
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 addTaintError
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getCausedByLinesToAdd
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
7.23
 ensureTaintednessIsSet
50.00% covered (danger)
50.00%
3 / 6
0.00% covered (danger)
0.00%
0 / 1
6.00
 setTaintedness
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
5
 getDefiningFuncIfDifferent
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 getPossibleFuncDefinitions
87.50% covered (warning)
87.50%
21 / 24
0.00% covered (danger)
0.00%
0 / 1
9.16
 getTaintOfFunction
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
1 / 1
11
 getSetKnownTaintOfFunctionWithoutAnalysis
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
1 / 1
8
 analyzeFunc
86.36% covered (warning)
86.36%
19 / 22
0.00% covered (danger)
0.00%
0 / 1
10.25
 getDocBlockTaintOfFunc
100.00% covered (success)
100.00%
93 / 93
100.00% covered (success)
100.00%
1 / 1
22
 getTaintByType
91.94% covered (success)
91.94%
57 / 62
0.00% covered (danger)
0.00%
0 / 1
33.57
 getTaintMaskForTypedElement
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getTaintMaskForType
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getPossibleFutureTaintOfElement
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCurrentMethod
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 getTaintedness
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 getTaintednessNode
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 getTaintednessPhanObj
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 resolveOffset
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 resolveValue
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getPropInCurrentScopeByName
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getCtxN
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 getObjsForNodeForNumkeyBackprop
67.53% covered (warning)
67.53%
52 / 77
0.00% covered (danger)
0.00%
0 / 1
153.80
 getPropFromNode
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 getDebugInfo
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 dbgInfo
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 linkParamAndFunc
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 mergeTaintDependencies
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
6
 markAllDependentMethodsExec
100.00% covered (success)
100.00%
54 / 54
100.00% covered (success)
100.00%
1 / 1
17
 markAllDependentMethodsExecForNode
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
3
 markAllDependentVarsYes
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
1 / 1
5
 getCausedByLinesForFunc
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getActualFuncWithCausedBy
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 debug
n/a
0 / 0
n/a
0 / 0
8
 getCallableFromNode
88.89% covered (warning)
88.89%
16 / 18
0.00% covered (danger)
0.00%
0 / 1
10.14
 getFirstElmFromArrayOrGenerator
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
4.59
 taintToIssuesAndSeverities
92.06% covered (success)
92.06%
58 / 63
0.00% covered (danger)
0.00%
0 / 1
11.06
 maybeEmitIssueSimplified
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 maybeEmitIssue
97.78% covered (success)
97.78%
44 / 45
0.00% covered (danger)
0.00%
0 / 1
14
 isIssueSuppressedOrFalsePositive
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
4
 handleMethodCall
100.00% covered (success)
100.00%
114 / 114
100.00% covered (success)
100.00%
1 / 1
24
 maybeHandleSpecialCall
92.86% covered (success)
92.86%
39 / 42
0.00% covered (danger)
0.00%
0 / 1
17.11
 extractArrayArgs
75.00% covered (warning)
75.00%
6 / 8
0.00% covered (danger)
0.00%
0 / 1
5.39
 translateNamedArg
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 backpropagateArgTaint
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 handlePassByRef
100.00% covered (success)
100.00%
53 / 53
100.00% covered (success)
100.00%
1 / 1
14
 getPassByRefObjFromNode
54.55% covered (warning)
54.55%
6 / 11
0.00% covered (danger)
0.00%
0 / 1
14.01
 getHardcodedPreservedTaintForFunc
69.01% covered (warning)
69.01%
216 / 313
0.00% covered (danger)
0.00%
0 / 1
294.01
 getBinOpTaintMask
90.00% covered (success)
90.00%
36 / 40
0.00% covered (danger)
0.00%
0 / 1
6.04
 getNodeType
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
2
 nodeIsArray
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
6.10
 nodeCanBeArray
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
5
 nodeCanBeString
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
3.14
 elementCanBeNumkey
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
5
 nodeCanBeIntKey
90.00% covered (success)
90.00%
9 / 10
0.00% covered (danger)
0.00%
0 / 1
7.05
 getReturnObjsOfFunc
91.67% covered (success)
91.67%
11 / 12
0.00% covered (danger)
0.00%
0 / 1
3.01
 isSubclassOf
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php declare( strict_types=1 );
2
3namespace SecurityCheckPlugin;
4
5use ast\Node;
6use Closure;
7use Exception;
8use Generator;
9use Phan\AST\ASTReverter;
10use Phan\AST\ContextNode;
11use Phan\AST\UnionTypeVisitor;
12use Phan\BlockAnalysisVisitor;
13use Phan\CodeBase;
14use Phan\Debug;
15use Phan\Exception\CodeBaseException;
16use Phan\Exception\FQSENException;
17use Phan\Exception\IssueException;
18use Phan\Exception\NodeException;
19use Phan\Exception\UnanalyzableException;
20use Phan\Issue;
21use Phan\Language\Context;
22use Phan\Language\Element\FunctionInterface;
23use Phan\Language\Element\GlobalVariable;
24use Phan\Language\Element\Method;
25use Phan\Language\Element\Property;
26use Phan\Language\Element\TypedElementInterface;
27use Phan\Language\Element\Variable;
28use Phan\Language\FQSEN\FullyQualifiedClassName;
29use Phan\Language\FQSEN\FullyQualifiedFunctionLikeName;
30use Phan\Language\FQSEN\FullyQualifiedFunctionName;
31use Phan\Language\FQSEN\FullyQualifiedMethodName;
32use Phan\Language\Type\FunctionLikeDeclarationType;
33use Phan\Language\Type\GenericArrayType;
34use Phan\Language\Type\LiteralTypeInterface;
35use Phan\Language\UnionType;
36use Phan\Library\Set;
37
38/**
39 * Trait for the Tainedness visitor subclasses. Mostly contains
40 * utility methods.
41 *
42 * Copyright (C) 2017  Brian Wolff <bawolff@gmail.com>
43 *
44 * This program is free software; you can redistribute it and/or modify
45 * it under the terms of the GNU General Public License as published by
46 * the Free Software Foundation; either version 2 of the License, or
47 * (at your option) any later version.
48 *
49 * This program is distributed in the hope that it will be useful,
50 * but WITHOUT ANY WARRANTY; without even the implied warranty of
51 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
52 * GNU General Public License for more details.
53 *
54 * You should have received a copy of the GNU General Public License along
55 * with this program; if not, write to the Free Software Foundation, Inc.,
56 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
57 */
58/**
59 * @property-read Context $context
60 * @property-read \Phan\CodeBase $code_base
61 */
62trait TaintednessBaseVisitor {
63    use TaintednessAccessorsTrait;
64
65    /** @var null|string|bool|resource filehandle to output debug messages */
66    private $debugOutput;
67
68    /** @var Context|null Override the file/line number to emit issues */
69    protected $overrideContext;
70
71    /**
72     * @var bool[] FQSENs of classes without __toString, map of [ (string)FQSEN => true ]
73     */
74    protected static $fqsensWithoutToStringCache = [];
75
76    /**
77     * @var array<string,bool> FQSENs of functions currently being analyzed by us, map of [ (string)FQSEN => true ]
78     */
79    private static $funcAnalysisStack = [];
80
81    /**
82     * Merge taintedness of a function/method
83     *
84     * @param FunctionInterface $func
85     * @param FunctionTaintedness $taint
86     */
87    protected function addFuncTaint( FunctionInterface $func, FunctionTaintedness $taint ): void {
88        $curTaint = self::getFuncTaint( $func );
89        if ( $curTaint ) {
90            $newTaint = $curTaint->asMergedWith( $taint );
91        } else {
92            $newTaint = $taint;
93        }
94        self::doSetFuncTaint( $func, $newTaint );
95    }
96
97    /**
98     * Ensure a function-like has its taintedness set and not unknown
99     *
100     * @param FunctionInterface $func
101     */
102    protected function ensureFuncTaintIsSet( FunctionInterface $func ): void {
103        if ( !self::getFuncTaint( $func ) ) {
104            self::doSetFuncTaint( $func, FunctionTaintedness::emptySingleton() );
105        }
106    }
107
108    /**
109     * @param FunctionInterface $func
110     * @param Context|string|null $reason To override the caused-by line
111     * @param FunctionTaintedness $addedTaint
112     * @param FunctionTaintedness $allNewTaint
113     * @param MethodLinks|null $returnLinks NOTE: These are only used for preserved params, since for sink params
114     * we're already adding a Taintedness with the expected EXEC bits.
115     */
116    private function maybeAddFuncError(
117        FunctionInterface $func,
118        $reason,
119        FunctionTaintedness $addedTaint,
120        FunctionTaintedness $allNewTaint,
121        ?MethodLinks $returnLinks = null
122    ): void {
123        if ( !is_string( $reason ) ) {
124            $newErrors = [ $this->dbgInfo( $reason ?? $this->context ) ];
125        } else {
126            $newErrors = [ $reason ];
127        }
128        if ( $this->overrideContext && !( $this->isHook ?? false ) ) {
129            // @phan-suppress-previous-line PhanUndeclaredProperty
130            $newErrors[] = $this->dbgInfo( $this->overrideContext );
131        }
132
133        $hasReturnLinks = $returnLinks && !$returnLinks->isEmpty();
134
135        // Future TODO: we might consider using PreservedTaintedness from the funcs instead of MethodLinks, but using
136        // links is more consistent with what we do for non-function causedby lines.
137
138        $newErr = self::getFuncCausedByRaw( $func ) ?? FunctionCausedByLines::emptySingleton();
139
140        foreach ( $addedTaint->getSinkParamKeysNoVariadic() as $key ) {
141            if ( $reason || $allNewTaint->canOverrideNonVariadicParam( $key ) ) {
142                $curTaint = $addedTaint->getParamSinkTaint( $key );