Skip to content

Commit 95c18ce

Browse files
authored
Merge pull request #17498 from paldepind/rust-improve-cfg
Rust: Improve CFG
2 parents 6a540d8 + 19697b9 commit 95c18ce

File tree

6 files changed

+1293
-126
lines changed

6 files changed

+1293
-126
lines changed

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

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ private import SuccessorType
66
private newtype TCompletion =
77
TSimpleCompletion() or
88
TBooleanCompletion(Boolean b) or
9+
TMatchCompletion(Boolean isMatch) or
10+
TLoopCompletion(TLoopJumpType kind, TLabelType label) {
11+
label = TNoLabel()
12+
or
13+
kind = TBreakJump() and label = TLabel(any(BreakExpr b).getLifetime().getText())
14+
or
15+
kind = TContinueJump() and label = TLabel(any(ContinueExpr b).getLifetime().getText())
16+
} or
917
TReturnCompletion()
1018

1119
/** A completion of a statement or an expression. */
@@ -51,6 +59,10 @@ abstract class ConditionalCompletion extends NormalCompletion {
5159
/** Gets the Boolean value of this conditional completion. */
5260
final boolean getValue() { result = value }
5361

62+
final predicate succeeded() { value = true }
63+
64+
final predicate failed() { value = false }
65+
5466
/** Gets the dual completion. */
5567
abstract ConditionalCompletion getDual();
5668
}
@@ -62,7 +74,34 @@ abstract class ConditionalCompletion extends NormalCompletion {
6274
class BooleanCompletion extends ConditionalCompletion, TBooleanCompletion {
6375
BooleanCompletion() { this = TBooleanCompletion(value) }
6476

65-
override predicate isValidForSpecific(AstNode e) { e = any(IfExpr c).getCondition() }
77+
override predicate isValidForSpecific(AstNode e) {
78+
e = any(IfExpr c).getCondition()
79+
or
80+
any(MatchArm arm).getGuard() = e
81+
or
82+
exists(BinaryExpr expr |
83+
expr.getOperatorName() = ["&&", "||"] and
84+
e = expr.getLhs()
85+
)
86+
or
87+
exists(Expr parent | this.isValidForSpecific(parent) |
88+
parent =
89+
any(PrefixExpr expr |
90+
expr.getOperatorName() = "!" and
91+
e = expr.getExpr()
92+
)
93+
or
94+
parent =
95+
any(BinaryExpr expr |
96+
expr.getOperatorName() = ["&&", "||"] and
97+
e = expr.getRhs()
98+
)
99+
or
100+
parent = any(IfExpr ie | e = [ie.getThen(), ie.getElse()])
101+
or
102+
parent = any(BlockExpr be | e = be.getStmtList().getTailExpr())
103+
)
104+
}
66105

67106
/** Gets the dual Boolean completion. */
68107
override BooleanCompletion getDual() { result = TBooleanCompletion(value.booleanNot()) }
@@ -72,6 +111,63 @@ class BooleanCompletion extends ConditionalCompletion, TBooleanCompletion {
72111
override string toString() { result = "boolean(" + value + ")" }
73112
}
74113

114+
/**
115+
* A completion that represents the result of a pattern match.
116+
*/
117+
class MatchCompletion extends TMatchCompletion, ConditionalCompletion {
118+
MatchCompletion() { this = TMatchCompletion(value) }
119+
120+
override predicate isValidForSpecific(AstNode e) { e instanceof Pat }
121+
122+
override MatchSuccessor getAMatchingSuccessorType() { result.getValue() = value }
123+
124+
/** Gets the dual match completion. */
125+
override MatchCompletion getDual() { result = TMatchCompletion(value.booleanNot()) }
126+
127+
override string toString() { result = "match(" + value + ")" }
128+
}
129+
130+
/**
131+
* A completion that represents a break or a continue.
132+
*/
133+
class LoopJumpCompletion extends TLoopCompletion, Completion {
134+
override LoopJumpSuccessor getAMatchingSuccessorType() {
135+
result = TLoopSuccessor(this.getKind(), this.getLabelType())
136+
}
137+
138+
final TLoopJumpType getKind() { this = TLoopCompletion(result, _) }
139+
140+
final TLabelType getLabelType() { this = TLoopCompletion(_, result) }
141+
142+
final predicate hasLabel() { this.getLabelType() = TLabel(_) }
143+
144+
final string getLabelName() { TLabel(result) = this.getLabelType() }
145+
146+
final predicate isContinue() { this.getKind() = TContinueJump() }
147+
148+
final predicate isBreak() { this.getKind() = TBreakJump() }
149+
150+
override predicate isValidForSpecific(AstNode e) {
151+
this.isBreak() and
152+
e instanceof BreakExpr and
153+
(
154+
not e.(BreakExpr).hasLifetime() and not this.hasLabel()
155+
or
156+
e.(BreakExpr).getLifetime().getText() = this.getLabelName()
157+
)
158+
or
159+
this.isContinue() and
160+
e instanceof ContinueExpr and
161+
(
162+
not e.(ContinueExpr).hasLifetime() and not this.hasLabel()
163+
or
164+
e.(ContinueExpr).getLifetime().getText() = this.getLabelName()
165+
)
166+
}
167+
168+
override string toString() { result = this.getAMatchingSuccessorType().toString() }
169+
}
170+
75171
/**
76172
* A completion that represents a return.
77173
*/

0 commit comments

Comments
 (0)