Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
35 / 35
100.00% covered (success)
100.00%
21 / 21
CRAP
100.00% covered (success)
100.00%
1 / 1
TaintednessAccessorsTrait
100.00% covered (success)
100.00%
35 / 35
100.00% covered (success)
100.00%
21 / 21
27
100.00% covered (success)
100.00%
1 / 1
 getTaintednessRaw
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setTaintednessRaw
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getCausedByRaw
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCausedByRef
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFuncCausedByRaw
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setCausedByRaw
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 setCausedByRef
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setFuncCausedByRaw
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMethodLinks
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setMethodLinks
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getMethodLinksRef
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getVarLinks
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 ensureVarLinksForArgExist
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getTaintednessRef
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setTaintednessRef
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 clearRefData
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFuncTaint
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 doSetFuncTaint
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRetObjs
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 addRetObjs
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 initRetObjs
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
1<?php declare( strict_types=1 );
2
3namespace SecurityCheckPlugin;
4
5use Phan\Language\Element\FunctionInterface;
6use Phan\Language\Element\PassByReferenceVariable;
7use Phan\Language\Element\TypedElementInterface;
8
9/**
10 * Accessors to read and write taintedness props stored inside phan objects. This trait exists to avoid duplicating
11 * dynamic property names, to have better type inference, to enable phan checks for undeclared props on the other
12 * files, to keep track of props usage etc.
13 * @phan-file-suppress PhanUndeclaredProperty
14 */
15trait TaintednessAccessorsTrait {
16    /**
17     * @param TypedElementInterface $element
18     * @return Taintedness|null
19     */
20    protected static function getTaintednessRaw( TypedElementInterface $element ): ?Taintedness {
21        return $element->taintedness ?? null;
22    }
23
24    /**
25     * @param TypedElementInterface $element
26     * @param Taintedness $taintedness
27     */
28    protected static function setTaintednessRaw( TypedElementInterface $element, Taintedness $taintedness ): void {
29        $element->taintedness = $taintedness;
30        if ( $element instanceof PassByReferenceVariable ) {
31            self::setTaintednessRef( $element->getElement(), $taintedness );
32        }
33    }
34
35    /**
36     * @param TypedElementInterface $element
37     * @return CausedByLines|null
38     */
39    protected static function getCausedByRaw( TypedElementInterface $element ): ?CausedByLines {
40        return $element->taintedOriginalError ?? null;
41    }
42
43    /**
44     * @param TypedElementInterface $element
45     * @return CausedByLines|null
46     */
47    protected static function getCausedByRef( TypedElementInterface $element ): ?CausedByLines {
48        return $element->taintedOriginalErrorRef ?? null;
49    }
50
51    /**
52     * @param FunctionInterface $func
53     * @return FunctionCausedByLines|null
54     */
55    protected static function getFuncCausedByRaw( FunctionInterface $func ): ?FunctionCausedByLines {
56        return $func->funcTaintedOriginalError ?? null;
57    }
58
59    /**
60     * @param TypedElementInterface $element
61     * @param CausedByLines $lines
62     */
63    protected static function setCausedByRaw( TypedElementInterface $element, CausedByLines $lines ): void {
64        $element->taintedOriginalError = $lines;
65        if ( $element instanceof PassByReferenceVariable ) {
66            self::setCausedByRef( $element->getElement(), $lines );
67        }
68    }
69
70    /**
71     * @param TypedElementInterface $element
72     * @param CausedByLines $lines
73     */
74    protected static function setCausedByRef( TypedElementInterface $element, CausedByLines $lines ): void {
75        $element->taintedOriginalErrorRef = $lines;
76    }
77
78    /**
79     * @param FunctionInterface $func
80     * @param FunctionCausedByLines $lines
81     */
82    protected static function setFuncCausedByRaw( FunctionInterface $func, FunctionCausedByLines $lines ): void {
83        $func->funcTaintedOriginalError = $lines;
84    }
85
86    /**
87     * @param TypedElementInterface $element
88     * @return MethodLinks|null
89     */
90    protected static function getMethodLinks( TypedElementInterface $element ): ?MethodLinks {
91        return $element->taintedMethodLinks ?? null;
92    }
93
94    /**
95     * @param TypedElementInterface $element
96     * @param MethodLinks $links
97     */
98    protected static function setMethodLinks( TypedElementInterface $element, MethodLinks $links ): void {
99        $element->taintedMethodLinks = $links;
100        if ( $element instanceof PassByReferenceVariable ) {
101            $element->getElement()->taintedMethodLinksRef = $links;
102        }
103    }
104
105    /**
106     * @param TypedElementInterface $element
107     * @return MethodLinks|null
108     */
109    protected static function getMethodLinksRef( TypedElementInterface $element ): ?MethodLinks {
110        return $element->taintedMethodLinksRef ?? null;
111    }
112
113    /**
114     * @param FunctionInterface $func
115     * @param int $index
116     * @return VarLinksSet|null
117     */
118    protected static function getVarLinks( FunctionInterface $func, int $index ): ?VarLinksSet {
119        return $func->taintedVarLinks[$index] ?? null;
120    }
121
122    /**
123     * @param TypedElementInterface $element
124     * @param int $arg
125     */
126    protected static function ensureVarLinksForArgExist( TypedElementInterface $element, int $arg ): void {
127        $element->taintedVarLinks ??= [];
128        $element->taintedVarLinks[$arg] ??= new VarLinksSet;
129    }
130
131    /**
132     * @param TypedElementInterface $element
133     * @return Taintedness|null
134     */
135    protected static function getTaintednessRef( TypedElementInterface $element ): ?Taintedness {
136        return $element->taintednessRef ?? null;
137    }
138
139    /**
140     * @param TypedElementInterface $element
141     * @param Taintedness $taintedness
142     */
143    protected static function setTaintednessRef( TypedElementInterface $element, Taintedness $taintedness ): void {
144        $element->taintednessRef = $taintedness;
145    }
146
147    /**
148     * @param TypedElementInterface $element
149     */
150    protected static function clearRefData( TypedElementInterface $element ): void {
151        unset( $element->taintednessRef, $element->taintedMethodLinksRef, $element->taintedOriginalErrorRef );
152    }
153
154    /**
155     * Get $func's taint, or null if not set.
156     *
157     * @param FunctionInterface $func
158     * @return FunctionTaintedness|null
159     */
160    protected static function getFuncTaint( FunctionInterface $func ): ?FunctionTaintedness {
161        return $func->funcTaint ?? null;
162    }
163
164    /**
165     * @param FunctionInterface $func
166     * @param FunctionTaintedness $funcTaint
167     */
168    protected static function doSetFuncTaint( FunctionInterface $func, FunctionTaintedness $funcTaint ): void {
169        $func->funcTaint = $funcTaint;
170    }
171
172    /**
173     * @param FunctionInterface $func
174     * @return TypedElementInterface[]|null
175     */
176    protected static function getRetObjs( FunctionInterface $func ): ?array {
177        $funcNode = $func->getNode();
178        if ( !$funcNode ) {
179            // If it has no node, it won't have any returned object, so don't return null, to avoid
180            // potential recursive analysis attempts.
181            return [];
182        }
183        return $funcNode->retObjs ?? null;
184    }
185
186    /**
187     * @note These are saved in the function node so that they can be shared by all implementations, without
188     * having to check the defining FQSEN of a method and canonicalize $func for lookup.
189     * @param FunctionInterface $func
190     * @param TypedElementInterface[] $retObjs
191     * @suppress PhanUnreferencedProtectedMethod Used in TaintednessVisitor
192     */
193    protected static function addRetObjs( FunctionInterface $func, array $retObjs ): void {
194        $funcNode = $func->getNode();
195        if ( $funcNode ) {
196            $funcNode->retObjs = array_merge( $funcNode->retObjs ?? [], $retObjs );
197        }
198    }
199
200    /**
201     * @param FunctionInterface $func
202     */
203    protected static function initRetObjs( FunctionInterface $func ): void {
204        $funcNode = $func->getNode();
205        if ( $funcNode ) {
206            $funcNode->retObjs ??= [];
207        }
208    }
209
210}