Skip to content

Commit 5c930f1

Browse files
committed
feat(ast): Add initial variable support
1 parent 7ec8e87 commit 5c930f1

File tree

2 files changed

+199
-10
lines changed

2 files changed

+199
-10
lines changed

ql/lib/codeql/bicep/ast/Stmts.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,9 @@ class UserDefinedFunction extends AstNode instanceof UserDefinedFunctionImpl {
141141
*/
142142
class Parameter extends AstNode instanceof ParameterImpl {
143143
/** Gets the name of the parameter. */
144-
Idents getName() { result = ParameterImpl.super.getName() }
144+
Idents getIdentifier() { result = ParameterImpl.super.getName() }
145+
146+
string getName() { result = this.getIdentifier().getName() }
145147

146148
/** Gets the type of the parameter. */
147149
Type getType() { result = ParameterImpl.super.getType() }

ql/lib/codeql/bicep/ast/Variables.qll

Lines changed: 196 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
/**
22
* Bicep variable declarations.
33
*/
4+
45
private import bicep
56
private import AstNodes
7+
private import Calls
68
private import Idents
79
private import Stmts
810
private import codeql.bicep.controlflow.BasicBlocks as BasicBlocks
@@ -14,13 +16,198 @@ private import internal.VariableDeclaration
1416
* A VariableDeclaration unknown AST node.
1517
*/
1618
class VariableDeclaration extends AstNode instanceof VariableDeclarationImpl {
17-
/**
18-
* Gets the identifier of the variable declaration.
19-
*/
20-
Idents getIdentifier() { result = VariableDeclarationImpl.super.getIdentifier() }
21-
22-
/**
23-
* Gets the initializer expression of the variable declaration.
24-
*/
25-
Expr getInitializer() { result = VariableDeclarationImpl.super.getInitializer() }
19+
/**
20+
* Gets the identifier of the variable declaration.
21+
*/
22+
Idents getIdentifier() { result = VariableDeclarationImpl.super.getIdentifier() }
23+
24+
/**
25+
* Gets the initializer expression of the variable declaration.
26+
*/
27+
Expr getInitializer() { result = VariableDeclarationImpl.super.getInitializer() }
28+
}
29+
30+
private predicate variableDecl(AstNode node, string name) {
31+
exists(ParameterDeclaration param |
32+
param.getName() = name and
33+
node = param
34+
)
35+
or
36+
exists(VariableDeclaration vardelc |
37+
vardelc.getIdentifier().getName() = name and
38+
node = vardelc
39+
)
40+
or
41+
exists(OutputDeclaration output |
42+
output.getIdentifier().getName() = name and
43+
node = output
44+
)
45+
}
46+
47+
/**
48+
* Variable represents a variable defination.
49+
*/
50+
class Variable extends MkVariable {
51+
private AstNode node;
52+
private string name;
53+
54+
Variable() { this = MkVariable(node, name) }
55+
56+
string getName() { result = name }
57+
58+
string toString() { result = "Variable[" + name + "]" }
59+
60+
AstNode getAstNode() { result = node }
61+
62+
/**
63+
* Get the location of this variable.
64+
*/
65+
Location getLocation() { result = node.getLocation() }
66+
67+
/**
68+
* Geta the inner variable of this variable.
69+
*/
70+
VariableAccess getAnAccess() { result.getVariable() = this }
71+
72+
/**
73+
* Gets the type of this variable, if any.
74+
*/
75+
Type getType() {
76+
result = this.getParameter().getType()
77+
or
78+
result = this.getOutput().getType()
79+
}
80+
81+
/**
82+
* Gets the parameter of this variable, if any.
83+
*/
84+
ParameterDeclaration getParameter() {
85+
exists(ParameterDeclaration param |
86+
param.getName() = this.getName() and
87+
param.getEnclosingCfgScope() = this.getEnclosingCfgScope() and
88+
result = param
89+
)
90+
}
91+
92+
/**
93+
* Gets the variable declaration of this variable, if any.
94+
*/
95+
OutputDeclaration getOutput() {
96+
exists(OutputDeclaration output |
97+
output.getIdentifier().getName() = this.getName() and
98+
output.getEnclosingCfgScope() = this.getEnclosingCfgScope() and
99+
result = output
100+
)
101+
}
102+
103+
/**
104+
* Gets the enclosing scope of this variable, if any.
105+
*/
106+
CfgScope getEnclosingCfgScope() { result = node.getEnclosingCfgScope() }
107+
108+
// Expr getInitializer() { }
109+
string getAPrimaryQlClass() { result = "Variable" }
110+
}
111+
112+
private predicate access(AstNode node, Variable v, string name) {
113+
exists(Identifier ident |
114+
ident.getName() = name and
115+
// Make sure they are not in a declare statement
116+
not ident.getParent() instanceof VariableDeclaration and
117+
// not ident.getParent() instanceof ParameterDeclaration and
118+
// not ident.getParent() instanceof OutputDeclaration and
119+
// Make sure they are in the same scope
120+
ident.getName() = v.getName() and
121+
ident.getEnclosingCfgScope() = v.getEnclosingCfgScope() and
122+
ident = node
123+
)
124+
}
125+
126+
/**
127+
* VariableAccess is a class that represents the access to a variable.
128+
*/
129+
class VariableAccess extends MkVariableAccess, TVariableAccess {
130+
private string name;
131+
private AstNode node;
132+
private Variable v;
133+
134+
VariableAccess() { this = MkVariableAccess(node, v, name) }
135+
136+
string getName() { result = name }
137+
138+
AstNode getAstNode() { result = node }
139+
140+
Variable getVariable() { result = v }
141+
142+
string toString() { result = "VariableAccess[" + name + "]" }
143+
144+
/**
145+
* Get the location of this variable.
146+
*/
147+
Location getLocation() { result = node.getLocation() }
148+
149+
/**
150+
* Gets the type of this variable, if any.
151+
*/
152+
Type getType() { result = this.getVariable().getType() }
153+
154+
/**
155+
* Gets the enclosing scope of this variable, if any.
156+
*/
157+
CfgScope getEnclosingCfgScope() { result = v.getEnclosingCfgScope() }
158+
159+
string getAPrimaryQlClass() { result = "VariableAccess" }
26160
}
161+
162+
class VariableWriteAccess extends VariableAccess {
163+
VariableWriteAccess() {
164+
// Parameter
165+
this.getAstNode().getParent() instanceof ParameterDeclaration
166+
or
167+
// SET
168+
this.getAstNode().getParent() instanceof VariableDeclaration
169+
or
170+
// Output
171+
this.getAstNode().getParent() instanceof OutputDeclaration
172+
}
173+
174+
override string getAPrimaryQlClass() { result = "VariableWrite" }
175+
}
176+
177+
class VariableReadAccess extends VariableAccess {
178+
VariableReadAccess() { not this instanceof VariableWriteAccess }
179+
180+
override string getAPrimaryQlClass() { result = "VariableRead" }
181+
}
182+
183+
/**
184+
* Holds if the variable is written too.
185+
*/
186+
// private predicate variableWrite(Variable node) {
187+
// exists(Parameter param |
188+
// param.getName() = node.getName() and
189+
// param.getEnclosingCfgScope() = node.getEnclosingCfgScope()
190+
// )
191+
// }
192+
cached
193+
private module Cached {
194+
cached
195+
newtype TVariable =
196+
TResource(Resource resource, string name) { resource.getName() = name } or
197+
TVariableDecl(VariableDeclaration varDecl, string name) {
198+
varDecl.getIdentifier().getName() = name
199+
} or
200+
TParameter(ParameterDeclaration param, string name) { param.getName() = name } or
201+
TOutput(OutputDeclaration output, string name) { output.getIdentifier().getName() = name } or
202+
MkVariable(AstNode definingNode, string name) { variableDecl(definingNode, name) }
203+
204+
cached
205+
newtype TVariableAccess =
206+
TIdent(Identifier ident, string name) { ident.getName() = name } or
207+
MkVariableAccess(AstNode node, Variable v, string name) { variableAccess(node, v, name) }
208+
209+
cached
210+
predicate variableAccess(AstNode node, Variable v, string name) { access(node, v, name) }
211+
}
212+
213+
private import Cached

0 commit comments

Comments
 (0)