Skip to content

Commit f73680b

Browse files
committed
Rust: Handle short-circuiting logical binary operators
1 parent c821ec2 commit f73680b

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,11 @@ abstract class ConditionalCompletion extends NormalCompletion {
6464
class BooleanCompletion extends ConditionalCompletion, TBooleanCompletion {
6565
BooleanCompletion() { this = TBooleanCompletion(value) }
6666

67-
override predicate isValidForSpecific(AstNode e) { e = any(IfExpr c).getCondition() }
67+
override predicate isValidForSpecific(AstNode e) {
68+
e = any(IfExpr c).getCondition()
69+
or
70+
exists(BinaryOpExpr expr | expr.getOp() = ["&&", "||"] and expr.getLhs() = e)
71+
}
6872

6973
/** Gets the dual Boolean completion. */
7074
override BooleanCompletion getDual() { result = TBooleanCompletion(value.booleanNot()) }

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,57 @@ class CallExprTree extends StandardPostOrderTree instanceof CallExpr {
9090
}
9191

9292
class BinaryOpExprTree extends StandardPostOrderTree instanceof BinaryOpExpr {
93+
BinaryOpExprTree() { super.getOp() != "&&" and super.getOp() != "||" }
94+
9395
override ControlFlowTree getChildNode(int i) {
9496
i = 0 and result = super.getLhs()
9597
or
9698
i = 1 and result = super.getRhs()
9799
}
98100
}
99101

102+
class LogicalOrBinaryOpExprTree extends PostOrderTree instanceof BinaryOpExpr {
103+
LogicalOrBinaryOpExprTree() { super.getOp() = "||" }
104+
105+
final override predicate propagatesAbnormal(AstNode child) {
106+
child = [super.getRhs(), super.getLhs()]
107+
}
108+
109+
override predicate first(AstNode node) { first(super.getLhs(), node) }
110+
111+
override predicate succ(AstNode pred, AstNode succ, Completion c) {
112+
last(super.getLhs(), pred, c) and
113+
(
114+
succ = this and c.(BooleanCompletion).getValue() = true
115+
or
116+
first(super.getRhs(), succ) and c.(BooleanCompletion).getValue() = false
117+
)
118+
or
119+
last(super.getRhs(), pred, c) and succ = this
120+
}
121+
}
122+
123+
class LogicalAndBinaryOpExprTree extends PostOrderTree instanceof BinaryOpExpr {
124+
LogicalAndBinaryOpExprTree() { super.getOp() = "&&" }
125+
126+
final override predicate propagatesAbnormal(AstNode child) {
127+
child = [super.getRhs(), super.getLhs()]
128+
}
129+
130+
override predicate first(AstNode node) { first(super.getLhs(), node) }
131+
132+
override predicate succ(AstNode pred, AstNode succ, Completion c) {
133+
last(super.getLhs(), pred, c) and
134+
(
135+
succ = this and c.(BooleanCompletion).getValue() = false
136+
or
137+
first(super.getRhs(), succ) and c.(BooleanCompletion).getValue() = true
138+
)
139+
or
140+
last(super.getRhs(), pred, c) and succ = this
141+
}
142+
}
143+
100144
class IfExprTree extends PostOrderTree instanceof IfExpr {
101145
override predicate first(AstNode node) { first(super.getCondition(), node) }
102146

0 commit comments

Comments
 (0)