Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
70.80% covered (warning)
70.80%
80 / 113
78.57% covered (warning)
78.57%
22 / 28
CRAP
0.00% covered (danger)
0.00%
0 / 1
FunctionTaintedness
70.80% covered (warning)
70.80%
80 / 113
78.57% covered (warning)
78.57%
22 / 28
192.04
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setOverall
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addOverallFlags
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getOverall
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 canOverrideOverall
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setParamSinkTaint
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setParamPreservedTaint
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addParamFlags
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setVariadicParamSinkTaint
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 setVariadicParamPreservedTaint
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 addVariadicParamFlags
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getParamSinkTaint
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
 getParamPreservedTaint
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
5.12
 getParamFlags
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 canOverrideNonVariadicParam
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getVariadicParamSinkTaint
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getVariadicParamPreservedTaint
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getVariadicParamIndex
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 canOverrideVariadicParam
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSinkParamKeysNoVariadic
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPreserveParamKeysNoVariadic
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasParamPreserve
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 mergeWith
90.32% covered (success)
90.32%
28 / 31
0.00% covered (danger)
0.00%
0 / 1
14.18
 asMergedWith
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 __clone
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
5
 toString
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
56
 flagsToString
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
20
 __toString
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php declare( strict_types=1 );
2
3namespace SecurityCheckPlugin;
4
5/**
6 * Value object used to store taintedness of functions.
7 * The $overall prop specifies what taint the function returns
8 *   irrespective of its arguments.
9 *
10 *   For 'overall': only TAINT flags, what taint the output has
11 *   For param keys: EXEC flags for what taints are unsafe here
12 *                     TAINT flags for what taint gets passed through func.
13 * As a special case, if the overall key has self::PRESERVE_TAINT
14 * then any unspecified keys behave like they are self::YES_TAINT
15 *
16 * If func has no info for a parameter, the UnionType will be used to determine its taintedness.
17 * The $overall taintedness must always be set.
18 */
19class FunctionTaintedness {
20    /** @var Taintedness Overall taintedness of the func */
21    private $overall;
22    /** @var Taintedness[] EXEC taintedness for each param */
23    private $paramSinkTaints = [];
24    /** @var PreservedTaintedness[] Preserved taintedness for each param */
25    private $paramPreserveTaints = [];
26    /** @var int|null Index of a variadic parameter, if any */
27    private $variadicParamIndex;
28    /** @var Taintedness|null EXEC taintedness for a variadic parameter, if any */
29    private $variadicParamSinkTaint;
30    /** @var PreservedTaintedness|null Preserved taintedness for a variadic parameter, if any */
31    private $variadicParamPreserveTaint;
32    /** @var int Special overall flags */
33    private $overallFlags = 0;
34    /** @var int[] Special flags for parameters */
35    private $paramFlags = [];
36    /** @var int */
37    private $variadicParamFlags = 0;
38
39    /**
40     * @param Taintedness $overall
41     */
42    public function __construct( Taintedness $overall ) {
43        $this->overall = $overall;
44    }
45
46    /**
47     * @param Taintedness $val
48     */
49    public function setOverall( Taintedness $val ): void {
50        $this->overall = $val;
51    }
52
53    /**
54     * @param int $flags
55     */
56    public function addOverallFlags( int $flags ): void {
57        $this->overallFlags |= $flags;
58    }
59
60    /**
61     * Get the overall taint (NOT a clone)
62     *
63     * @return Taintedness
64     */
65    public function getOverall(): Taintedness {
66        return $this->overall;
67    }
68
69    /**
70     * @return bool
71     */
72    public function canOverrideOverall(): bool {
73        return ( $this->overallFlags & SecurityCheckPlugin::NO_OVERRIDE ) === 0;
74    }
75
76    /**
77     * Set the sink taint for a given param
78     *
79     * @param int $param
80     * @param Taintedness $taint
81     */
82    public function setParamSinkTaint( int $param, Taintedness $taint ): void {
83        assert( $param !== $this->variadicParamIndex );
84        $this->paramSinkTaints[$param] = $taint;
85    }
86
87    /**
88     * Set the preserved taint for a given param
89     *
90     * @param int $param
91     * @param PreservedTaintedness $taint
92     */
93    public function setParamPreservedTaint( int $param, PreservedTaintedness $taint ): void {
94        assert( $param !== $this->variadicParamIndex );
95        $this->paramPreserveTaints[$param] = $taint;
96    }
97
98    /**
99     * @param int $param
100     * @param int $flags
101     */
102    public function addParamFlags( int $param, int $flags ): void {
103        $this->paramFlags[$param] = ( $this->paramFlags[$param] ?? 0 ) | $flags;
104    }
105
106    /**
107     * @param int $index
108     * @param Taintedness $taint
109     */
110    public function setVariadicParamSinkTaint( int $index, Taintedness $taint ): void {
111        assert( !isset( $this->paramPreserveTaints[$index] ) && !isset( $this->paramSinkTaints[$index] ) );
112        $this->variadicParamIndex = $index;
113        $this->variadicParamSinkTaint = $taint;
114    }
115
116    /**
117     * @param int $index
118     * @param PreservedTaintedness $taint
119     */
120    public function setVariadicParamPreservedTaint( int $index, PreservedTaintedness $taint ): void {
121        assert( !isset( $this->paramPreserveTaints[$index] ) && !isset( $this->paramSinkTaints[$index] ) );
122        $this->variadicParamIndex = $index;
123        $this->variadicParamPreserveTaint = $taint;
124    }
125
126    /**
127     * @param int $flags
128     */
129    public function addVariadicParamFlags( int $flags ): void {
130        $this->variadicParamFlags |= $flags;
131    }
132
133    /**
134     * Get the sink taintedness of the given param (NOT a clone), and NO_TAINT if not set.
135     *
136     * @param int $param
137     * @return Taintedness
138     */
139    public function getParamSinkTaint( int $param ): Taintedness {
140        if ( isset( $this->paramSinkTaints[$param] ) ) {
141            return $this->paramSinkTaints[$param];
142        }
143        if (
144            $this->variadicParamIndex !== null && $param >= $this->variadicParamIndex &&
145            $this->variadicParamSinkTaint
146        ) {
147            return $this->variadicParamSinkTaint;
148        }
149        return Taintedness::newSafe();
150    }
151
152    /**
153     * Get the preserved taintedness of the given param (NOT a clone), and NO_TAINT if not set.
154     *
155     * @param int $param
156     * @return PreservedTaintedness
157     */
158    public function getParamPreservedTaint( int $param ): PreservedTaintedness {
159        if ( isset( $this->paramPreserveTaints[$param] ) ) {
160            return $this->paramPreserveTaints[$param];
161        }
162        if (
163            $this->variadicParamIndex !== null && $param >= $this->variadicParamIndex &&
164            $this->variadicParamPreserveTaint
165        ) {
166            return $this->variadicParamPreserveTaint;
167        }
168        return PreservedTaintedness::newEmpty();
169    }
170
171    /**
172     * @param int $param
173     * @return int
174     */
175    public function getParamFlags( int $param ): int {
176        if ( isset( $this->paramFlags[$param] ) ) {
177            return $this->paramFlags[$param];
178        }
179        if ( $this->variadicParamIndex !== null && $param