Skip to content

Commit f6f54c6

Browse files
committed
Rust: Include parameters in the CFG
1 parent 665da39 commit f6f54c6

File tree

4 files changed

+181
-39
lines changed

4 files changed

+181
-39
lines changed

rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,26 @@ class CastExprTree extends StandardPostOrderTree instanceof CastExpr {
183183
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
184184
}
185185

186-
class ClosureExprTree extends LeafTree instanceof ClosureExpr { }
186+
// Closures have their own CFG scope, so we need to make sure that their
187+
// CFG is not mixed with the surrounding CFG. This is done by retrofitting
188+
// `first`, `propagatesAbnormal`, and `succ` below.
189+
class ClosureExprTree extends StandardPostOrderTree, ClosureExpr {
190+
override predicate first(AstNode first) { first = this }
191+
192+
override predicate propagatesAbnormal(AstNode child) { none() }
193+
194+
override AstNode getChildNode(int i) {
195+
result = this.getParamList().getParam(i)
196+
or
197+
i = this.getParamList().getNumberOfParams() and
198+
result = this.getBody()
199+
}
200+
201+
override predicate succ(AstNode pred, AstNode succ, Completion c) {
202+
super.succ(pred, succ, c) and
203+
not succ = this
204+
}
205+
}
187206

188207
class ContinueExprTree extends LeafTree, ContinueExpr {
189208
override predicate last(AstNode last, Completion c) { none() }
@@ -203,7 +222,34 @@ class FieldExprTree extends StandardPostOrderTree instanceof FieldExpr {
203222
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
204223
}
205224

206-
class FunctionTree extends LeafTree instanceof Function { }
225+
// Functions have their own CFG scope, so we need to make sure that their
226+
// CFG is not mixed with the surrounding CFG in case of nested functions.
227+
// This is done by retrofitting `last`, `propagatesAbnormal`, and `succ`
228+
// below.
229+
class FunctionTree extends StandardPreOrderTree, Function {
230+
override predicate last(AstNode last, Completion c) {
231+
last = this and
232+
completionIsValidFor(c, this)
233+
}
234+
235+
override predicate propagatesAbnormal(AstNode child) { none() }
236+
237+
override AstNode getChildNode(int i) {
238+
result = this.getParamList().getParam(i)
239+
or
240+
i = this.getParamList().getNumberOfParams() and
241+
result = this.getBody()
242+
}
243+
244+
override predicate succ(AstNode pred, AstNode succ, Completion c) {
245+
super.succ(pred, succ, c) and
246+
not pred = this
247+
}
248+
}
249+
250+
class ParamTree extends StandardPostOrderTree, Param {
251+
override AstNode getChildNode(int i) { i = 0 and result = this.getPat() }
252+
}
207253

208254
class IfExprTree extends PostOrderTree instanceof IfExpr {
209255
override predicate first(AstNode node) { first(super.getCondition(), node) }

rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,17 @@ abstract class CfgScope extends AstNode {
1212
}
1313

1414
final class FunctionScope extends CfgScope, Function {
15-
override predicate scopeFirst(AstNode node) { first(this.getBody(), node) }
15+
override predicate scopeFirst(AstNode node) {
16+
first(this.(FunctionTree).getFirstChildNode(), node)
17+
}
1618

1719
override predicate scopeLast(AstNode node, Completion c) { last(this.getBody(), node, c) }
1820
}
1921

2022
final class ClosureScope extends CfgScope, ClosureExpr {
21-
override predicate scopeFirst(AstNode node) { first(this.getBody(), node) }
23+
override predicate scopeFirst(AstNode node) {
24+
first(this.(ClosureExprTree).getFirstChildNode(), node)
25+
}
2226

2327
override predicate scopeLast(AstNode node, Completion c) { last(this.getBody(), node, c) }
2428
}

0 commit comments

Comments
 (0)