Skip to content

Commit 3d95369

Browse files
committed
Shared ConditionalSplitting implementation
1 parent 1f1b1b7 commit 3d95369

File tree

4 files changed

+254
-64
lines changed

4 files changed

+254
-64
lines changed

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

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ private import codeql.rust.controlflow.ControlFlowGraph as Cfg
77
private module CfgInput implements InputSig<Location> {
88
private import rust as Rust
99
private import Completion as C
10-
private import Splitting as S
1110

1211
class AstNode = Rust::AstNode;
1312

@@ -24,10 +23,6 @@ private module CfgInput implements InputSig<Location> {
2423

2524
CfgScope getCfgScope(AstNode n) { result = Scope::scopeOfAst(n) }
2625

27-
class SplitKindBase = S::TSplitKind;
28-
29-
class Split = S::Split;
30-
3126
class SuccessorType = Cfg::SuccessorType;
3227

3328
/** Gets a successor type that matches completion `c`. */
@@ -51,7 +46,22 @@ private module CfgInput implements InputSig<Location> {
5146
predicate scopeLast(CfgScope scope, AstNode last, Completion c) { scope.scopeLast(last, c) }
5247
}
5348

54-
private module CfgImpl = Make<Location, CfgInput>;
49+
private module CfgSplittingInput implements SplittingInputSig<Location, CfgInput> {
50+
private import Splitting as S
51+
52+
class SplitKindBase = S::TSplitKind;
53+
54+
class Split = S::Split;
55+
}
56+
57+
private module ConditionalCompletionSplittingInput implements
58+
ConditionalCompletionSplittingInputSig<Location, CfgInput, CfgSplittingInput>
59+
{
60+
import Splitting::ConditionalCompletionSplitting::ConditionalCompletionSplittingInput
61+
}
62+
63+
private module CfgImpl =
64+
MakeWithSplitting<Location, CfgInput, CfgSplittingInput, ConditionalCompletionSplittingInput>;
5565

5666
import CfgImpl
5767

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

Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ abstract private class Split_ extends TSplit {
2121

2222
final class Split = Split_;
2323

24-
private module ConditionalCompletionSplitting {
24+
module ConditionalCompletionSplitting {
2525
/**
2626
* A split for conditional completions. For example, in
2727
*
@@ -39,77 +39,77 @@ private module ConditionalCompletionSplitting {
3939

4040
ConditionalCompletionSplit() { this = TConditionalCompletionSplit(completion) }
4141

42+
ConditionalCompletion getCompletion() { result = completion }
43+
4244
override string toString() { result = completion.toString() }
4345
}
4446

45-
private class ConditionalCompletionSplitKind extends SplitKind, TConditionalCompletionSplitKind {
47+
private class ConditionalCompletionSplitKind_ extends SplitKind, TConditionalCompletionSplitKind {
4648
override int getListOrder() { result = 0 }
4749

4850
override predicate isEnabled(AstNode cfe) { this.appliesTo(cfe) }
4951

5052
override string toString() { result = "ConditionalCompletion" }
5153
}
5254

53-
private class ConditionalCompletionSplitImpl extends SplitImpl instanceof ConditionalCompletionSplit
54-
{
55-
ConditionalCompletion completion;
55+
module ConditionalCompletionSplittingInput {
56+
private import Completion as Comp
5657

57-
ConditionalCompletionSplitImpl() { this = TConditionalCompletionSplit(completion) }
58+
class ConditionalCompletion = Comp::ConditionalCompletion;
5859

59-
override ConditionalCompletionSplitKind getKind() { any() }
60+
class ConditionalCompletionSplitKind extends ConditionalCompletionSplitKind_, TSplitKind { }
6061

61-
override predicate hasEntry(AstNode pred, AstNode succ, Completion c) {
62-
succ(pred, succ, c) and
63-
last(succ, _, completion) and
62+
class ConditionalCompletionSplit = ConditionalCompletionSplitting::ConditionalCompletionSplit;
63+
64+
bindingset[parent, parentCompletion]
65+
predicate condPropagateExpr(
66+
AstNode parent, ConditionalCompletion parentCompletion, AstNode child,
67+
ConditionalCompletion childCompletion
68+
) {
69+
child = parent.(LogicalNotExpr).getExpr() and
70+
childCompletion.getDual() = parentCompletion
71+
or
72+
childCompletion = parentCompletion and
6473
(
65-
last(succ.(LogicalNotExpr).getExpr(), pred, c) and
66-
completion.(BooleanCompletion).getDual() = c
67-
or
68-
last(succ.(BinaryLogicalOperation).getAnOperand(), pred, c) and
69-
completion = c
74+
child = parent.(BinaryLogicalOperation).getAnOperand()
7075
or
71-
succ =
72-
any(IfExpr ie |
73-
last([ie.getThen(), ie.getElse()], pred, c) and
74-
completion = c
75-
)
76+
parent = any(IfExpr ie | child = [ie.getThen(), ie.getElse()])
7677
or
77-
last(succ.(MatchExpr).getAnArm().getExpr(), pred, c) and
78-
completion = c
78+
child = parent.(MatchExpr).getAnArm().getExpr()
7979
or
80-
last(succ.(BlockExpr).getStmtList().getTailExpr(), pred, c) and
81-
completion = c
80+
child = parent.(BlockExpr).getStmtList().getTailExpr()
8281
)
83-
or
84-
succ(pred, succ, c) and
85-
last(succ.(BreakExpr).getExpr(), pred, c) and
86-
exists(AstNode target |
87-
succ(succ, target, _) and
88-
last(target, _, completion)
89-
) and
90-
completion = c
9182
}
83+
}
9284

93-
override predicate hasEntryScope(CfgScope scope, AstNode first) { none() }
94-
95-
override predicate hasExit(AstNode pred, AstNode succ, Completion c) {
96-
this.appliesTo(pred) and
97-
succ(pred, succ, c) and
98-
if c instanceof ConditionalCompletion
99-
then completion = c
100-
else not this.hasSuccessor(pred, succ, c)
85+
private class ConditionalCompletionSplitImpl extends SplitImplementations::ConditionalCompletionSplitting::ConditionalCompletionSplitImpl
86+
{
87+
/**
88+
* Gets a `break` expression whose target can have a Boolean completion that
89+
* matches this split.
90+
*/
91+
private BreakExpr getABreakExpr(Expr target) {
92+
target = result.getTarget() and
93+
last(target, _, this.getCompletion())
10194
}
10295

103-
override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
104-
this.appliesTo(last) and
105-
scope.scopeLast(last, c) and
106-
if c instanceof ConditionalCompletion then completion = c else any()
96+
override predicate hasEntry(AstNode pred, AstNode succ, Completion c) {
97+
super.hasEntry(pred, succ, c)
98+
or
99+
succ(pred, succ, c) and
100+
last(succ.(BreakExpr).getExpr(), pred, c) and
101+
succ = this.getABreakExpr(_) and
102+
c = this.getCompletion()
107103
}
108104

109105
override predicate hasSuccessor(AstNode pred, AstNode succ, Completion c) {
106+
super.hasSuccessor(pred, succ, c)
107+
or
110108
this.appliesTo(pred) and
111109
succ(pred, succ, c) and
112-
not c instanceof ConditionalCompletion
110+
pred = this.getABreakExpr(succ)
113111
}
114112
}
113+
114+
int getNextListOrder() { result = 1 }
115115
}

0 commit comments

Comments
 (0)