1
1
private import codeql.actions.ast.internal.Actions
2
2
private import codeql.Locations
3
3
4
+ /**
5
+ * Base class for the AST tree.
6
+ * Based on YamlNode from the Yaml library but making mapping values children of the mapping keys:
7
+ * eg: top:
8
+ * key: value
9
+ * According to the Yaml library, both `key` and `value` are direct children of `top`
10
+ * This Tree implementation makes `key` child od `top` and `value` child of `key`
11
+ */
4
12
class AstNode instanceof YamlNode {
5
- AstNode getParentNode ( ) {
6
- if exists ( YamlMapping m | m .maps ( _, this ) )
7
- then exists ( YamlMapping m | m .maps ( result , this ) )
8
- else result = super .getParentNode ( )
9
- }
10
-
11
- AstNode getAChildNode ( ) {
12
- if this instanceof YamlMapping
13
- then this .( YamlMapping ) .maps ( result , _)
14
- else
15
- if this instanceof YamlCollection
16
- then result = super .getChildNode ( _)
17
- else
18
- if this instanceof YamlScalar and exists ( YamlMapping m | m .maps ( this , _) )
19
- then exists ( YamlMapping m | m .maps ( this , result ) )
20
- else none ( )
21
- }
22
-
23
- AstNode getChildNodeByOrder ( int i ) {
24
- result =
25
- rank [ i ] ( Expression child , Location l |
26
- child = this .getAChildNode ( ) and
27
- child .getLocation ( ) = l
28
- |
29
- child
30
- order by
31
- l .getStartLine ( ) , l .getStartColumn ( ) , l .getEndColumn ( ) , l .getEndLine ( ) , child .toString ( )
32
- )
33
- }
34
-
13
+ AstNode getParentNode ( ) { result = super .getParentNode ( ) }
14
+
15
+ // AstNode getParentNode() {
16
+ // if exists(YamlMapping m | m.maps(_, this))
17
+ // then exists(YamlMapping m | m.maps(result, this))
18
+ // else result = super.getParentNode()
19
+ // }
20
+ AstNode getAChildNode ( ) { result = super .getAChildNode ( ) }
21
+
22
+ // AstNode getAChildNode() {
23
+ // if this instanceof YamlMapping
24
+ // then this.(YamlMapping).maps(result, _)
25
+ // else
26
+ // if this instanceof YamlCollection
27
+ // then result = super.getChildNode(_)
28
+ // else
29
+ // if this instanceof YamlScalar and exists(YamlMapping m | m.maps(this, _))
30
+ // then exists(YamlMapping m | m.maps(this, result))
31
+ // else none()
32
+ // }
33
+ // /**
34
+ // * This should be getAChildNode(int i)
35
+ // */
36
+ // AstNode getChildNodeByOrder(int i) {
37
+ // result =
38
+ // rank[i](Expression child, Location l |
39
+ // child = this.getAChildNode() and
40
+ // child.getLocation() = l
41
+ // |
42
+ // child
43
+ // order by
44
+ // l.getStartLine(), l.getStartColumn(), l.getEndColumn(), l.getEndLine(), child.toString()
45
+ // )
46
+ // }
35
47
string toString ( ) { result = super .toString ( ) }
36
48
37
49
string getAPrimaryQlClass ( ) { result = super .getAPrimaryQlClass ( ) }
38
50
39
51
Location getLocation ( ) { result = super .getLocation ( ) }
40
52
}
41
53
42
- class Statement extends AstNode {
43
- // narrow down to something that is a statement
44
- // A statement is a group of expressions and/or statements that you design to carry out a task or an action.
45
- // Any statement that can return a value is automatically qualified to be used as an expression.
46
- }
54
+ /**
55
+ * A statement is a group of expressions and/or statements that you design to carry out a task or an action.
56
+ * Any statement that can return a value is automatically qualified to be used as an expression.
57
+ */
58
+ class Statement extends AstNode { }
59
+
60
+ /**
61
+ * An expression is any word or group of words or symbols that is a value. In programming, an expression is a value, or anything that executes and ends up being a value.
62
+ */
63
+ class Expression extends Statement { }
64
+
65
+ /**
66
+ * A Github Actions Workflow
67
+ */
68
+ class WorkflowStmt extends Statement instanceof Actions:: Workflow {
69
+ JobStmt getAJob ( ) { result = super .getJob ( _) }
47
70
48
- class Expression extends Statement {
49
- // narrow down to something that is an expression
50
- // An expression is any word or group of words or symbols that is a value. In programming, an expression is a value, or anything that executes and ends up being a value.
71
+ JobStmt getJob ( string id ) { result = super .getJob ( id ) }
51
72
}
52
73
53
74
/**
@@ -60,54 +81,53 @@ class JobStmt extends Statement instanceof Actions::Job {
60
81
*/
61
82
string getId ( ) { result = super .getId ( ) }
62
83
63
- /** Gets the human-readable name of this job, if any, as a string. */
64
- string getName ( ) {
65
- result = super .getId ( )
66
- or
67
- not exists ( string s | s = super .getId ( ) ) and result = "unknown"
68
- }
69
-
70
84
/** Gets the step at the given index within this job. */
71
85
StepStmt getStep ( int index ) { result = super .getStep ( index ) }
72
86
73
87
/** Gets any steps that are defined within this job. */
74
88
StepStmt getAStep ( ) { result = super .getStep ( _) }
75
89
90
+ /**
91
+ * Gets a needed job.
92
+ * eg:
93
+ * - needs: [job1, job2]
94
+ */
76
95
JobStmt getNeededJob ( ) {
77
96
exists ( Actions:: Needs needs |
78
97
needs .getJob ( ) = this and
79
98
result = needs .getANeededJob ( ) .( JobStmt )
80
99
)
81
100
}
82
101
83
- Expression getJobOutputExpr ( string varName ) {
84
- this .( Actions:: Job )
85
- .lookup ( "outputs" )
86
- .( YamlMapping )
87
- .maps ( any ( YamlScalar a | a .getValue ( ) = varName ) , result )
88
- }
89
-
90
- JobOutputStmt getJobOutputStmt ( ) { result = this .( Actions:: Job ) .lookup ( "outputs" ) }
91
-
92
- Statement getSuccNode ( int i ) {
93
- result =
94
- rank [ i ] ( Expression child , Location l |
95
- ( child = this .getAStep ( ) or child = this .getJobOutputStmt ( ) ) and
96
- l = child .getLocation ( )
97
- |
98
- child
99
- order by
100
- l .getStartLine ( ) , l .getStartColumn ( ) , l .getEndColumn ( ) , l .getEndLine ( ) , child .toString ( )
101
- )
102
- }
102
+ /**
103
+ * Gets the declaration of the outputs for the job.
104
+ * eg:
105
+ * out1: ${steps.foo.bar}
106
+ * out2: ${steps.foo.baz}
107
+ */
108
+ JobOutputStmt getOutputStmt ( ) { result = this .( Actions:: Job ) .lookup ( "outputs" ) }
103
109
}
104
110
111
+ /**
112
+ * Declaration of the outputs for the job.
113
+ * eg:
114
+ * out1: ${steps.foo.bar}
115
+ * out2: ${steps.foo.baz}
116
+ */
105
117
class JobOutputStmt extends Statement instanceof YamlMapping {
106
118
JobStmt job ;
107
119
108
120
JobOutputStmt ( ) { job .( YamlMapping ) .lookup ( "outputs" ) = this }
109
121
110
- StepOutputAccessExpr getSuccNode ( int i ) { result = this .( YamlMapping ) .getValueNode ( i ) }
122
+ YamlMapping asYamlMapping ( ) { result = this }
123
+
124
+ /**
125
+ * Gets a specific value expression
126
+ * eg: ${steps.foo.bar}
127
+ */
128
+ Expression getOutputExpr ( string id ) {
129
+ this .( YamlMapping ) .maps ( any ( YamlScalar s | s .getValue ( ) = id ) , result )
130
+ }
111
131
}
112
132
113
133
/**
@@ -116,15 +136,7 @@ class JobOutputStmt extends Statement instanceof YamlMapping {
116
136
class StepStmt extends Statement instanceof Actions:: Step {
117
137
string getId ( ) { result = super .getId ( ) }
118
138
119
- string getName ( ) {
120
- result = super .getId ( )
121
- or
122
- not exists ( string s | s = super .getId ( ) ) and result = "unknown"
123
- }
124
-
125
139
JobStmt getJob ( ) { result = super .getJob ( ) }
126
-
127
- abstract AstNode getSuccNode ( int i ) ;
128
140
}
129
141
130
142
/**
@@ -145,57 +157,23 @@ class UsesExpr extends StepStmt, Expression {
145
157
result = with .lookup ( key )
146
158
)
147
159
}
148
-
149
- Expression getArgumentByOrder ( int i ) {
150
- exists ( Actions:: With with |
151
- with .getStep ( ) = uses .getStep ( ) and
152
- result =
153
- rank [ i ] ( Expression child , Location l |
154
- child = with .lookup ( _) and l = child .getLocation ( )
155
- |
156
- child
157
- order by
158
- l .getStartLine ( ) , l .getStartColumn ( ) , l .getEndColumn ( ) , l .getEndLine ( ) , child .toString ( )
159
- )
160
- )
161
- }
162
-
163
- Expression getAnArgument ( ) {
164
- exists ( Actions:: With with |
165
- with .getStep ( ) = this and
166
- result = with .lookup ( _)
167
- )
168
- }
169
-
170
- override AstNode getSuccNode ( int i ) { result = this .getArgumentByOrder ( i ) }
171
160
}
172
161
173
162
/**
174
- * An argument passed to a UsesExpr.
163
+ * A Run step represents the evaluation of a provided script
175
164
*/
176
- class ArgumentExpr extends Expression {
177
- UsesExpr uses ;
178
-
179
- ArgumentExpr ( ) { this = uses .getAnArgument ( ) }
180
- }
181
-
182
- /**
183
- * A Run step represents a call to an inline script or executable on the runner machine.
184
- */
185
- class RunExpr extends StepStmt {
165
+ class RunExpr extends StepStmt , Expression {
186
166
Actions:: Run scriptExpr ;
187
167
188
168
RunExpr ( ) { scriptExpr .getStep ( ) = this }
189
169
190
170
Expression getScriptExpr ( ) { result = scriptExpr }
191
171
192
172
string getScript ( ) { result = scriptExpr .getValue ( ) }
193
-
194
- override AstNode getSuccNode ( int i ) { result = this .getScriptExpr ( ) and i = 0 }
195
173
}
196
174
197
175
/**
198
- * A YAML string containing a workflow expression.
176
+ * Evaluation of a workflow expression ${{}} .
199
177
*/
200
178
class ExprAccessExpr extends Expression instanceof YamlString {
201
179
string expr ;
@@ -208,7 +186,7 @@ class ExprAccessExpr extends Expression instanceof YamlString {
208
186
}
209
187
210
188
/**
211
- * A ExprAccessExpr where the expression references a step output.
189
+ * A ExprAccessExpr where the expression evaluated is a step output read .
212
190
* eg: `${{ steps.changed-files.outputs.all_changed_files }}`
213
191
*/
214
192
class StepOutputAccessExpr extends ExprAccessExpr {
@@ -230,7 +208,7 @@ class StepOutputAccessExpr extends ExprAccessExpr {
230
208
}
231
209
232
210
/**
233
- * A ExprAccessExpr where the expression references a job output.
211
+ * A ExprAccessExpr where the expression evaluated is a job output read .
234
212
* eg: `${{ needs.job1.outputs.foo}}`
235
213
*/
236
214
class JobOutputAccessExpr extends ExprAccessExpr {
@@ -250,7 +228,7 @@ class JobOutputAccessExpr extends ExprAccessExpr {
250
228
exists ( JobStmt job |
251
229
job .getId ( ) = jobId and
252
230
job .getLocation ( ) .getFile ( ) = this .getLocation ( ) .getFile ( ) and
253
- job .getJobOutputExpr ( varName ) = result
231
+ job .getOutputStmt ( ) . getOutputExpr ( varName ) = result
254
232
)
255
233
}
256
234
}
0 commit comments