5
5
namespace Psalm \SymfonyPsalmPlugin \Twig ;
6
6
7
7
use Psalm \CodeLocation ;
8
- use Psalm \Internal \Codebase \Taint ;
9
- use Psalm \Internal \Taint \ Sink ;
10
- use Psalm \Internal \Taint \ Taintable ;
11
- use Psalm \Internal \Taint \ TaintNode ;
8
+ use Psalm \Internal \Codebase \TaintFlowGraph ;
9
+ use Psalm \Internal \ControlFlow \ ControlFlowNode ;
10
+ use Psalm \Internal \ControlFlow \ TaintSink ;
11
+ use Psalm \Internal \ControlFlow \ TaintSource ;
12
12
use Psalm \Type \TaintKind ;
13
13
use Twig \Node \Expression \FilterExpression ;
14
14
use Twig \Node \Expression \NameExpression ;
18
18
19
19
class Context
20
20
{
21
- /** @var array<string, Taintable > */
21
+ /** @var array<string, ControlFlowNode > */
22
22
private $ unassignedVariables = [];
23
23
24
- /** @var array<string, Taintable > */
24
+ /** @var array<string, ControlFlowNode > */
25
25
private $ localVariables = [];
26
26
27
27
/** @var Source */
28
28
private $ sourceContext ;
29
29
30
- /** @var Taint */
30
+ /** @var TaintFlowGraph */
31
31
private $ taint ;
32
32
33
- public function __construct (Source $ sourceContext , Taint $ taint )
33
+ public function __construct (Source $ sourceContext , TaintFlowGraph $ taint )
34
34
{
35
35
$ this ->sourceContext = $ sourceContext ;
36
36
$ this ->taint = $ taint ;
37
37
}
38
38
39
- public function addSink (Node $ node , Taintable $ source ): void
39
+ public function addSink (Node $ node , ControlFlowNode $ source ): void
40
40
{
41
41
$ codeLocation = $ this ->getNodeLocation ($ node );
42
42
@@ -45,7 +45,7 @@ public function addSink(Node $node, Taintable $source): void
45
45
$ sinkName = 'twig_print ' ;
46
46
}
47
47
48
- $ sink = Sink ::getForMethodArgument (
48
+ $ sink = TaintSink ::getForMethodArgument (
49
49
$ sinkName , $ sinkName , 0 , null , $ codeLocation
50
50
);
51
51
@@ -59,28 +59,28 @@ public function addSink(Node $node, Taintable $source): void
59
59
$ this ->taint ->addPath ($ source , $ sink , 'arg ' );
60
60
}
61
61
62
- public function taintVariable (NameExpression $ expression ): Taintable
62
+ public function taintVariable (NameExpression $ expression ): ControlFlowNode
63
63
{
64
64
/** @var string $variableName */
65
65
$ variableName = $ expression ->getAttribute ('name ' );
66
66
67
- $ sinkNode = TaintNode ::getForAssignment ($ variableName , $ this ->getNodeLocation ($ expression ));
67
+ $ sinkNode = TaintSource ::getForAssignment ($ variableName , $ this ->getNodeLocation ($ expression ));
68
68
69
- $ this ->taint ->addTaintNode ($ sinkNode );
69
+ $ this ->taint ->addNode ($ sinkNode );
70
70
$ sinkNode = $ this ->addVariableTaintNode ($ expression );
71
71
72
72
return $ this ->addVariableUsage ($ variableName , $ sinkNode );
73
73
}
74
74
75
- public function getTaintDestination (Taintable $ taintSource , FilterExpression $ expression ): TaintNode
75
+ public function getTaintDestination (ControlFlowNode $ taintSource , FilterExpression $ expression ): ControlFlowNode
76
76
{
77
77
/** @var string $filterName */
78
78
$ filterName = $ expression ->getNode ('filter ' )->getAttribute ('value ' );
79
79
80
80
$ returnLocation = $ this ->getNodeLocation ($ expression );
81
- $ taintDestination = TaintNode ::getForMethodReturn ('filter_ ' .$ filterName , 'filter_ ' .$ filterName , $ returnLocation , $ returnLocation );
81
+ $ taintDestination = TaintSource ::getForMethodReturn ('filter_ ' .$ filterName , 'filter_ ' .$ filterName , $ returnLocation , $ returnLocation );
82
82
83
- $ this ->taint ->addTaintNode ($ taintDestination );
83
+ $ this ->taint ->addNode ($ taintDestination );
84
84
$ this ->taint ->addPath ($ taintSource , $ taintDestination , 'arg ' );
85
85
86
86
return $ taintDestination ;
@@ -110,25 +110,25 @@ public function taintUnassignedVariables(string $templateName): void
110
110
{
111
111
foreach ($ this ->unassignedVariables as $ variableName => $ taintable ) {
112
112
$ label = strtolower ($ templateName ).'# ' .strtolower ($ variableName );
113
- $ taintSource = new TaintNode ($ label , $ label , null , null );
113
+ $ taintSource = new TaintSource ($ label , $ label , null , null );
114
114
115
- $ this ->taint ->addTaintNode ($ taintSource );
115
+ $ this ->taint ->addNode ($ taintSource );
116
116
$ this ->taint ->addPath ($ taintSource , $ taintable , 'arg ' );
117
117
}
118
118
}
119
119
120
- private function addVariableTaintNode (NameExpression $ variableNode ): TaintNode
120
+ private function addVariableTaintNode (NameExpression $ variableNode ): ControlFlowNode
121
121
{
122
122
/** @var string $variableName */
123
123
$ variableName = $ variableNode ->getAttribute ('name ' );
124
- $ taintNode = TaintNode ::getForAssignment ($ variableName , $ this ->getNodeLocation ($ variableNode ));
124
+ $ taintNode = TaintSource ::getForAssignment ($ variableName , $ this ->getNodeLocation ($ variableNode ));
125
125
126
- $ this ->taint ->addTaintNode ($ taintNode );
126
+ $ this ->taint ->addNode ($ taintNode );
127
127
128
128
return $ taintNode ;
129
129
}
130
130
131
- private function addVariableUsage (string $ variableName , Taintable $ variableTaint ): Taintable
131
+ private function addVariableUsage (string $ variableName , ControlFlowNode $ variableTaint ): ControlFlowNode
132
132
{
133
133
if (!isset ($ this ->localVariables [$ variableName ])) {
134
134
return $ this ->unassignedVariables [$ variableName ] = $ variableTaint ;
@@ -139,10 +139,12 @@ private function addVariableUsage(string $variableName, Taintable $variableTaint
139
139
140
140
private function getNodeLocation (Node $ node ): CodeLocation
141
141
{
142
+ /** @psalm-var string $fileName */
142
143
$ fileName = $ this ->sourceContext ->getName ();
143
144
$ filePath = $ this ->sourceContext ->getPath ();
144
145
$ snippet = $ this ->sourceContext ->getCode (); // warning : the getCode method returns the whole template, not only the statement
145
146
$ fileCode = file_get_contents ($ filePath );
147
+ /** @psalm-var int $lineNumber */
146
148
$ lineNumber = $ node ->getTemplateLine ();
147
149
$ lines = explode ("\n" , $ fileCode );
148
150
0 commit comments