Skip to content

Commit 1a85dfd

Browse files
committed
Rust: Loops propagate CFG return completions but captures continue and break
1 parent b979df6 commit 1a85dfd

File tree

2 files changed

+15
-1
lines changed

2 files changed

+15
-1
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,9 @@ predicate completionIsSimple(Completion c) { c instanceof SimpleCompletion }
119119

120120
/** Holds if `c` is a valid completion for `n`. */
121121
predicate completionIsValidFor(Completion c, AstNode n) { c.isValidFor(n) }
122+
123+
/** Holds if `c` is a completion that interacts with a loop such as `loop`, `for`, `while`. */
124+
predicate isLoopCompletion(Completion c) {
125+
c instanceof BreakCompletion or
126+
c instanceof ContinueCompletion
127+
}

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ class LetStmtTree extends StandardPostOrderTree instanceof LetStmt {
174174
}
175175

176176
class LoopExprTree extends PostOrderTree instanceof LoopExpr {
177-
override predicate propagatesAbnormal(AstNode child) { child = super.getBody() }
177+
override predicate propagatesAbnormal(AstNode child) { none() }
178178

179179
override predicate first(AstNode node) { first(super.getBody(), node) }
180180

@@ -189,6 +189,14 @@ class LoopExprTree extends PostOrderTree instanceof LoopExpr {
189189
c instanceof BreakCompletion and
190190
succ = this
191191
}
192+
193+
override predicate last(AstNode last, Completion c) {
194+
super.last(last, c)
195+
or
196+
last(super.getBody(), last, c) and
197+
not completionIsNormal(c) and
198+
not isLoopCompletion(c)
199+
}
192200
}
193201

194202
class ReturnExprTree extends PostOrderTree instanceof ReturnExpr {

0 commit comments

Comments
 (0)