Skip to content

Commit 186f0cd

Browse files
committed
feat(cfg): Enhance control flow graph with additional AST node classes and tree structures for Bicep
1 parent 3fee620 commit 186f0cd

File tree

2 files changed

+478
-66
lines changed

2 files changed

+478
-66
lines changed

ql/lib/codeql/bicep/controlflow/CfgNodes.qll

Lines changed: 270 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
/** Provides classes representing nodes in a control flow graph. */
22

33
private import bicep
4+
private import codeql.bicep.ast.Calls
5+
private import codeql.bicep.ast.Literals
6+
private import codeql.bicep.ast.Resources
47
private import BasicBlocks
58
private import ControlFlowGraph
69
import internal.ControlFlowGraphImpl
@@ -29,15 +32,280 @@ class StmtsCfgNode extends AstCfgNode {
2932
Stmts getStmt() { result = s }
3033
}
3134

35+
/** A control-flow node that wraps an AST literal. */
36+
class LiteralsCfgNode extends AstCfgNode {
37+
string getAPrimaryQlClass() { result = "LiteralsCfgNode" }
38+
39+
Literals l;
40+
41+
LiteralsCfgNode() { l = this.getAstNode() }
42+
43+
/** Gets the underlying literal. */
44+
Literals getLiteral() { result = l }
45+
}
46+
3247
/** Provides classes for control-flow nodes that wrap AST expressions. */
33-
module ExprNodes {
48+
module ExprNodes {
49+
/** A mapping from a child of an expression to an expression. */
50+
abstract class ExprChildMapping extends Expr {
51+
/** Holds if `n` is a relevant child of this expression. */
52+
abstract predicate relevantChild(AstNode n);
53+
}
54+
55+
/** A mapping from a child of a literal to a literal. */
56+
abstract class LiteralChildMapping extends AstNode {
57+
/** Holds if `n` is a relevant child of this literal. */
58+
abstract predicate relevantChild(AstNode n);
59+
}
60+
61+
/** A control-flow node that wraps an Array AST node. */
62+
class ArrayCfgNode extends LiteralsCfgNode {
63+
override string getAPrimaryQlClass() { result = "ArrayCfgNode" }
64+
65+
Array e;
66+
67+
ArrayCfgNode() { l = this.getLiteral() }
68+
69+
/** Gets the underlying array literal. */
70+
Array getArray() { result = l }
71+
}
72+
73+
/** A control-flow node that wraps a Boolean AST node. */
74+
class BooleanCfgNode extends LiteralsCfgNode {
75+
override string getAPrimaryQlClass() { result = "BooleanCfgNode" }
76+
77+
Boolean e;
78+
79+
BooleanCfgNode() { l = this.getLiteral() }
80+
81+
/** Gets the underlying boolean literal. */
82+
Boolean getBoolean() { result = l }
83+
}
84+
85+
/** A control-flow node that wraps a NullLiteral AST node. */
86+
class NullLiteralCfgNode extends LiteralsCfgNode {
87+
override string getAPrimaryQlClass() { result = "NullLiteralCfgNode" }
88+
89+
NullLiteral e;
90+
91+
NullLiteralCfgNode() { l = this.getLiteral() }
92+
93+
/** Gets the underlying null literal. */
94+
NullLiteral getNullLiteral() { result = l }
95+
}
96+
97+
/** A control-flow node that wraps a Number AST node. */
98+
class NumberCfgNode extends LiteralsCfgNode {
99+
override string getAPrimaryQlClass() { result = "NumberCfgNode" }
100+
101+
Number e;
102+
103+
NumberCfgNode() { l = this.getLiteral() }
104+
105+
/** Gets the underlying number literal. */
106+
Number getNumber() { result = l }
107+
}
108+
109+
/** A control-flow node that wraps a StringLiteral AST node. */
110+
class StringLiteralCfgNode extends LiteralsCfgNode {
111+
override string getAPrimaryQlClass() { result = "StringLiteralCfgNode" }
112+
113+
StringLiteral e;
114+
115+
StringLiteralCfgNode() { l = this.getLiteral() }
116+
117+
/** Gets the underlying string literal. */
118+
StringLiteral getStringLiteral() { result = l }
119+
}
120+
121+
/** A control-flow node that wraps a StringContentLiteral AST node. */
122+
class StringContentLiteralCfgNode extends LiteralsCfgNode {
123+
override string getAPrimaryQlClass() { result = "StringContentLiteralCfgNode" }
124+
125+
StringContentLiteral e;
126+
127+
StringContentLiteralCfgNode() { l = this.getLiteral() }
128+
129+
/** Gets the underlying string content literal. */
130+
StringContentLiteral getStringContentLiteral() { result = l }
131+
}
132+
133+
/** A control-flow node that wraps a CallExpression AST node. */
34134
class CallCfgNode extends ExprCfgNode {
35135
override string getAPrimaryQlClass() { result = "CallCfgNode" }
36136

37137
override CallExpression e;
38138

39139
override CallExpression getExpr() { result = super.getExpr() }
40140
}
141+
142+
/** A mapping from a child of an Arguments expression to the expression. */
143+
abstract class ArgumentsChildMapping extends ExprChildMapping, Arguments {
144+
override predicate relevantChild(AstNode n) { n = this.getArgument(_) }
145+
}
146+
147+
/** A control-flow node that wraps an Arguments AST node. */
148+
class ArgumentsCfgNode extends ExprCfgNode {
149+
override string getAPrimaryQlClass() { result = "ArgumentsCfgNode" }
150+
151+
override Arguments e;
152+
153+
override Arguments getExpr() { result = super.getExpr() }
154+
}
155+
156+
/** A mapping from a child of an AssignmentExpression to the expression. */
157+
abstract class AssignmentExpressionChildMapping extends ExprChildMapping, AssignmentExpression {
158+
override predicate relevantChild(AstNode n) { n = this.getLeft() or n = this.getRight() }
159+
}
160+
161+
/** A control-flow node that wraps an AssignmentExpression AST node. */
162+
class AssignmentExpressionCfgNode extends ExprCfgNode {
163+
override string getAPrimaryQlClass() { result = "AssignmentExpressionCfgNode" }
164+
165+
override AssignmentExpression e;
166+
167+
override AssignmentExpression getExpr() { result = super.getExpr() }
168+
}
169+
170+
/** A mapping from a child of a BinaryExpression to the expression. */
171+
abstract class BinaryExpressionChildMapping extends ExprChildMapping, BinaryExpression {
172+
override predicate relevantChild(AstNode n) { n = this.getLeft() or n = this.getRight() }
173+
}
174+
175+
/** A control-flow node that wraps a BinaryExpression AST node. */
176+
class BinaryExpressionCfgNode extends ExprCfgNode {
177+
override string getAPrimaryQlClass() { result = "BinaryExpressionCfgNode" }
178+
179+
override BinaryExpression e;
180+
181+
override BinaryExpression getExpr() { result = super.getExpr() }
182+
183+
/** Gets the left operand CFG node */
184+
final ExprCfgNode getLeftOperand() {
185+
result = this.getAPredecessor().(ExprCfgNode) and
186+
result.getExpr() = this.getExpr().getLeft()
187+
}
188+
189+
/** Gets the right operand CFG node */
190+
final ExprCfgNode getRightOperand() {
191+
result = this.getAPredecessor().(ExprCfgNode) and
192+
result.getExpr() = this.getExpr().getRight()
193+
}
194+
}
195+
196+
/** A mapping from a child of an Interpolation to the expression. */
197+
abstract class InterpolationChildMapping extends ExprChildMapping, Interpolation {
198+
override predicate relevantChild(AstNode n) { n = this.getExpression() }
199+
}
200+
201+
/** A control-flow node that wraps an Interpolation AST node. */
202+
class InterpolationCfgNode extends ExprCfgNode {
203+
override string getAPrimaryQlClass() { result = "InterpolationCfgNode" }
204+
205+
override Interpolation e;
206+
207+
override Interpolation getExpr() { result = super.getExpr() }
208+
}
209+
210+
/** A mapping from a child of a LambdaExpression to the expression. */
211+
abstract class LambdaExpressionChildMapping extends ExprChildMapping, LambdaExpression {
212+
override predicate relevantChild(AstNode n) { n = this.getAChild() }
213+
}
214+
215+
/** A control-flow node that wraps a LambdaExpression AST node. */
216+
class LambdaExpressionCfgNode extends ExprCfgNode {
217+
override string getAPrimaryQlClass() { result = "LambdaExpressionCfgNode" }
218+
219+
override LambdaExpression e;
220+
221+
override LambdaExpression getExpr() { result = super.getExpr() }
222+
}
223+
224+
/** A mapping from a child of a MemberExpression to the expression. */
225+
abstract class MemberExpressionChildMapping extends ExprChildMapping, MemberExpression {
226+
override predicate relevantChild(AstNode n) { n = this.getNamespace() or n = this.getName() }
227+
}
228+
229+
/** A control-flow node that wraps a MemberExpression AST node. */
230+
class MemberExpressionCfgNode extends ExprCfgNode {
231+
override string getAPrimaryQlClass() { result = "MemberExpressionCfgNode" }
232+
233+
override MemberExpression e;
234+
235+
override MemberExpression getExpr() { result = super.getExpr() }
236+
}
237+
238+
/** A mapping from a child of a NullableType to the expression. */
239+
abstract class NullableTypeChildMapping extends ExprChildMapping, NullableType {
240+
override predicate relevantChild(AstNode n) { n = this.getAChild() }
241+
}
242+
243+
/** A control-flow node that wraps a NullableType AST node. */
244+
class NullableTypeCfgNode extends ExprCfgNode {
245+
override string getAPrimaryQlClass() { result = "NullableTypeCfgNode" }
246+
247+
override NullableType e;
248+
249+
override NullableType getExpr() { result = super.getExpr() }
250+
}
251+
252+
/** A mapping from a child of a ParenthesizedExpression to the expression. */
253+
abstract class ParenthesizedExpressionChildMapping extends ExprChildMapping,
254+
ParenthesizedExpression
255+
{
256+
override predicate relevantChild(AstNode n) { n = this.getExpression(_) }
257+
}
258+
259+
/** A control-flow node that wraps a ParenthesizedExpression AST node. */
260+
class ParenthesizedExpressionCfgNode extends ExprCfgNode {
261+
override string getAPrimaryQlClass() { result = "ParenthesizedExpressionCfgNode" }
262+
263+
override ParenthesizedExpression e;
264+
265+
override ParenthesizedExpression getExpr() { result = super.getExpr() }
266+
}
267+
268+
/** A mapping from a child of a ResourceExpression to the expression. */
269+
abstract class ResourceExpressionChildMapping extends ExprChildMapping, ResourceExpression {
270+
override predicate relevantChild(AstNode n) { n = this.getAChild() }
271+
}
272+
273+
/** A control-flow node that wraps a ResourceExpression AST node. */
274+
class ResourceExpressionCfgNode extends ExprCfgNode {
275+
override string getAPrimaryQlClass() { result = "ResourceExpressionCfgNode" }
276+
277+
override ResourceExpression e;
278+
279+
override ResourceExpression getExpr() { result = super.getExpr() }
280+
}
281+
282+
/** A mapping from a child of a TernaryExpression to the expression. */
283+
abstract class TernaryExpressionChildMapping extends ExprChildMapping, TernaryExpression {
284+
override predicate relevantChild(AstNode n) { n = this.getAChild() }
285+
}
286+
287+
/** A control-flow node that wraps a TernaryExpression AST node. */
288+
class TernaryExpressionCfgNode extends ExprCfgNode {
289+
override string getAPrimaryQlClass() { result = "TernaryExpressionCfgNode" }
290+
291+
override TernaryExpression e;
292+
293+
override TernaryExpression getExpr() { result = super.getExpr() }
294+
}
295+
296+
/** A mapping from a child of a UnaryExpression to the expression. */
297+
abstract class UnaryExpressionChildMapping extends ExprChildMapping, UnaryExpression {
298+
override predicate relevantChild(AstNode n) { n = this.getAChild() }
299+
}
300+
301+
/** A control-flow node that wraps a UnaryExpression AST node. */
302+
class UnaryExpressionCfgNode extends ExprCfgNode {
303+
override string getAPrimaryQlClass() { result = "UnaryExpressionCfgNode" }
304+
305+
override UnaryExpression e;
306+
307+
override UnaryExpression getExpr() { result = super.getExpr() }
308+
}
41309
}
42310

43311
module StmtNodes {
@@ -49,4 +317,4 @@ module StmtNodes {
49317

50318
override UserDefinedFunction getStmt() { result = super.getStmt() }
51319
}
52-
}
320+
}

0 commit comments

Comments
 (0)