Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
91.40% covered (success)
91.40%
85 / 93
87.50% covered (warning)
87.50%
14 / 16
CRAP
0.00% covered (danger)
0.00%
0 / 1
FunctionCausedByLines
91.40% covered (success)
91.40%
85 / 93
87.50% covered (warning)
87.50%
14 / 16
53.72
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
 emptySingleton
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getGenericLines
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 withAddedGenericLines
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 withGenericLines
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 withAddedParamSinkLines
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 withAddedParamPreservedLines
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 withParamSinkLines
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 withParamPreservedLines
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 withVariadicParamSinkLines
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 withVariadicParamPreservedLines
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 withAddedVariadicParamSinkLines
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 withAddedVariadicParamPreservedLines
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 getParamSinkLines
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
 getParamPreservedLines
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
 asMergedWith
87.10% covered (warning)
87.10%
27 / 31
0.00% covered (danger)
0.00%
0 / 1
16.55
 toString
n/a
0 / 0
n/a
0 / 0
5
 __toString
n/a
0 / 0
n/a
0 / 0
1
1<?php declare( strict_types=1 );
2
3namespace SecurityCheckPlugin;
4
5/**
6 * This class represents caused-by lines for a function-like:
7 * - Lines in genericLines are for taintedness that is added inside the function, regardless of parameters; these
8 *   have a Taintedness object associated, while the associated links are always empty.
9 * - Lines in (variadic)paramSinkLines are those inside a function that EXEC the arguments. These also have a
10 *   Taintedness object associated, and no links.
11 * - Lines in (variadic)paramPreservedLines are responsible for putting a parameter inside the return value. These have
12 *   a safe Taintedness associated, and usually non-empty links.
13 */
14class FunctionCausedByLines {
15    /** @var CausedByLines */
16    private $genericLines;
17    /** @var CausedByLines[] */
18    private $paramSinkLines = [];
19    /** @var CausedByLines[] */
20    private $paramPreservedLines = [];
21    /** @var int|null Index of a variadic parameter, if any */
22    private $variadicParamIndex;
23    /** @var CausedByLines|null */
24    private $variadicParamSinkLines;
25    /** @var CausedByLines|null */
26    private $variadicParamPreservedLines;
27
28    public function __construct() {
29        $this->genericLines = CausedByLines::emptySingleton();
30    }
31
32    public static function emptySingleton(): self {
33        static $singleton;
34        if ( !$singleton ) {
35            $singleton = new self();
36        }
37        return $singleton;
38    }
39
40    /**
41     * @return CausedByLines
42     * @suppress PhanUnreferencedPublicMethod
43     */
44    public function getGenericLines(): CausedByLines {
45        return $this->genericLines;
46    }
47
48    /**
49     * @param string[] $lines
50     * @param Taintedness $taint
51     * @param ?MethodLinks $links
52     * @return self
53     */
54    public function withAddedGenericLines( array $lines, Taintedness $taint, ?MethodLinks $links = null ): self {
55        $ret = clone $this;
56        $ret->genericLines = $this->genericLines->withAddedLines( $lines, $taint, $links );
57        return $ret;
58    }
59
60    public function withGenericLines( CausedByLines $lines ): self {
61        $ret = clone $this;
62        $ret->genericLines = $lines;
63        return $ret;
64    }
65
66    /**
67     * @param int $param
68     * @param string[] $lines
69     * @param Taintedness $taint
70     * @return self
71     */
72    public function withAddedParamSinkLines( int $param, array $lines, Taintedness $taint ): self {
73        assert( $param !== $this->variadicParamIndex );
74        $ret = clone $this;
75        if ( !isset( $ret->paramSinkLines[$param] ) ) {
76            $ret->paramSinkLines[$param] = CausedByLines::emptySingleton();
77        }
78        $ret->paramSinkLines[$param] = $ret->paramSinkLines[$param]->withAddedLines( $lines, $taint );
79        return $ret;
80    }
81
82    /**
83     * @param int $param
84     * @param string[] $lines
85     * @param Taintedness $taint
86     * @param ?MethodLinks $links
87     * @return self
88     */
89    public function withAddedParamPreservedLines(
90        int $param,
91        array $lines,
92        Taintedness $taint,
93        ?MethodLinks $links = null
94    ): self {
95        assert( $param !== $this->variadicParamIndex );
96        $ret = clone $this;
97        if ( !isset( $ret->paramPreservedLines[$param] ) ) {
98            $ret->paramPreservedLines[$param] = CausedByLines::emptySingleton();
99        }
100        $ret->paramPreservedLines[$param] = $ret->paramPreservedLines[$param]
101            ->withAddedLines( $lines, $taint, $links );
102        return $ret;
103    }
104
105    public function withParamSinkLines( int $param, CausedByLines $lines ): self {
106        $ret = clone $this;
107        $ret->paramSinkLines[$param] = $lines;
108        return $ret;
109    }
110
111    public function withParamPreservedLines( int $param, CausedByLines $lines ): self {
112        $ret = clone $this;
113        $ret->paramPreservedLines[$param] = $lines;
114        return $ret;
115    }
116
117    public function withVariadicParamSinkLines( int $param, CausedByLines $lines ): self {
118        $ret = clone $this;
119        $ret->variadicParamIndex = $param;
120        $ret->variadicParamSinkLines = $lines;
121        return $ret;
122    }
123
124    public function withVariadicParamPreservedLines( int $param, CausedByLines $lines ): self {
125        $ret = clone $this;
126        $ret->variadicParamIndex = $param;
127        $ret->variadicParamPreservedLines = $lines;
128        return $ret;
129    }
130
131    /**
132     * @param int $param
133     * @param string[] $lines
134     * @param Taintedness $taint
135     * @return self
136     */
137    public function withAddedVariadicParamSinkLines(
138        int $param,
139        array $lines,
140        Taintedness $taint
141    ): self {
142        assert( !isset( $this->paramSinkLines[$param] ) && !isset( $this->paramPreservedLines[$param] ) );
143        $ret = clone $this;
144        $ret->variadicParamIndex = $param;
145        if ( !$ret->variadicParamSinkLines ) {
146            $ret->variadicParamSinkLines = CausedByLines::emptySingleton();
147        }
148        $ret->variadicParamSinkLines = $ret->variadicParamSinkLines->withAddedLines( $lines, $taint );
149        return $ret;
150    }
151
152    /**
153     * @param int $param
154     * @param string[] $lines
155     * @param Taintedness $taint
156     * @param ?MethodLinks $links
157     * @return self
158     */
159    public function withAddedVariadicParamPreservedLines(
160        int $param,
161        array $lines,
162        Taintedness $taint,
163        ?MethodLinks $links = null
164    ): self {
165        assert( !isset( $this->paramSinkLines[$param] ) && !isset( $this->paramPreservedLines[$param] ) );
166        $ret = clone $this;
167        $ret->variadicParamIndex = $param;
168        if ( !$ret->variadicParamPreservedLines ) {
169            $ret->variadicParamPreservedLines = CausedByLines::emptySingleton();
170        }
171        $ret->variadicParamPreservedLines = $ret->variadicParamPreservedLines
172            ->withAddedLines( $lines, $taint, $links );
173        return $ret;
174    }
175
176    /**
177     * @param int $param
178     * @return CausedByLines
179     */
180    public function getParamSinkLines( int $param ): CausedByLines {