Skip to content

Commit ff61344

Browse files
committed
Cfg: Add support for until-statements.
1 parent fe8c029 commit ff61344

3 files changed

Lines changed: 26 additions & 7 deletions

File tree

csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraph.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ module Ast implements AstSig<Location> {
172172

173173
class DoStmt = CS::DoStmt;
174174

175+
class UntilStmt extends LoopStmt {
176+
UntilStmt() { none() }
177+
}
178+
175179
final private class FinalForStmt = CS::ForStmt;
176180

177181
class ForStmt extends FinalForStmt {

java/ql/lib/semmle/code/java/ControlFlowGraph.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ private module Ast implements AstSig<Location> {
8484

8585
class DoStmt = J::DoStmt;
8686

87+
class UntilStmt extends LoopStmt {
88+
UntilStmt() { none() }
89+
}
90+
8791
final private class FinalForStmt = J::ForStmt;
8892

8993
class ForStmt extends FinalForStmt {

shared/controlflow/codeql/controlflow/ControlFlowGraph.qll

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ signature module AstSig<LocationSig Location> {
119119
Expr getCondition();
120120
}
121121

122+
/** An `until` loop statement. */
123+
class UntilStmt extends LoopStmt {
124+
/** Gets the boolean condition of this `until` loop. */
125+
Expr getCondition();
126+
}
127+
122128
/** A traditional C-style `for` loop. */
123129
class ForStmt extends LoopStmt {
124130
/** Gets the initializer of the loop at the specified (zero-based) position, if any. */
@@ -608,6 +614,7 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
608614
any(IfStmt ifstmt).getCondition() = n or
609615
any(WhileStmt whilestmt).getCondition() = n or
610616
any(DoStmt dostmt).getCondition() = n or
617+
any(UntilStmt untilstmt).getCondition() = n or
611618
any(ForStmt forstmt).getCondition() = n or
612619
any(ConditionalExpr condexpr).getCondition() = n or
613620
any(CatchClause catch).getCondition() = n or
@@ -1535,26 +1542,30 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
15351542
n2.isAfter(ifstmt)
15361543
)
15371544
or
1538-
exists(WhileStmt whilestmt |
1539-
n1.isBefore(whilestmt) and
1540-
n2.isAdditional(whilestmt, loopHeaderTag())
1545+
exists(LoopStmt loopstmt | loopstmt instanceof WhileStmt or loopstmt instanceof UntilStmt |
1546+
n1.isBefore(loopstmt) and
1547+
n2.isAdditional(loopstmt, loopHeaderTag())
15411548
)
15421549
or
15431550
exists(DoStmt dostmt |
15441551
n1.isBefore(dostmt) and
15451552
n2.isBefore(dostmt.getBody())
15461553
)
15471554
or
1548-
exists(LoopStmt loopstmt, AstNode cond |
1549-
loopstmt.(WhileStmt).getCondition() = cond or loopstmt.(DoStmt).getCondition() = cond
1555+
exists(LoopStmt loopstmt, AstNode cond, boolean while |
1556+
loopstmt.(WhileStmt).getCondition() = cond and while = true
1557+
or
1558+
loopstmt.(DoStmt).getCondition() = cond and while = true
1559+
or
1560+
loopstmt.(UntilStmt).getCondition() = cond and while = false
15501561
|
15511562
n1.isAdditional(loopstmt, loopHeaderTag()) and
15521563
n2.isBefore(cond)
15531564
or
1554-
n1.isAfterTrue(cond) and
1565+
n1.isAfterValue(cond, any(BooleanSuccessor b | b.getValue() = while)) and
15551566
n2.isBefore(loopstmt.getBody())
15561567
or
1557-
n1.isAfterFalse(cond) and
1568+
n1.isAfterValue(cond, any(BooleanSuccessor b | b.getValue() = while.booleanNot())) and
15581569
n2.isAfter(loopstmt)
15591570
or
15601571
n1.isAfter(loopstmt.getBody()) and

0 commit comments

Comments
 (0)