Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c4c74cd

Browse files
committed
C#: Split up DataFlowInternal.qll
Split up into `internal/BaseSSA.qll` and `internal/Steps.qll`.
1 parent af3f855 commit c4c74cd

4 files changed

Lines changed: 119 additions & 111 deletions

File tree

csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,7 @@ module Ssa {
10941094

10951095
private module SimpleDelegateAnalysis {
10961096
private import semmle.code.csharp.dataflow.DelegateDataFlow
1097-
private import semmle.code.csharp.dataflow.DataFlowInternal
1097+
private import semmle.code.csharp.dataflow.internal.Steps
10981098
private import semmle.code.csharp.frameworks.system.linq.Expressions
10991099

11001100
/**
@@ -1124,7 +1124,7 @@ module Ssa {
11241124
}
11251125

11261126
private predicate delegateFlowStep(Expr pred, Expr succ) {
1127-
DataFlowInternal::stepClosed(pred, succ)
1127+
Steps::stepClosed(pred, succ)
11281128
or
11291129
exists(Call call, Callable callable |
11301130
callable.getSourceDeclaration().canReturn(pred) and
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import csharp
2+
3+
/**
4+
* INTERNAL: Do not use.
5+
*
6+
* Provides a simple SSA implementation for local scope variables.
7+
*/
8+
module BaseSsa {
9+
private import ControlFlowGraph
10+
11+
/**
12+
* Holds if the `i`th node of basic block `bb` is assignable definition `def`,
13+
* targeting local scope variable `v`.
14+
*/
15+
private predicate defAt(BasicBlock bb, int i, AssignableDefinition def, LocalScopeVariable v) {
16+
bb.getNode(i) = def.getAControlFlowNode() and
17+
v = def.getTarget()
18+
}
19+
20+
/**
21+
* Holds if basic block `bb` would need to start with a phi node for local scope
22+
* variable `v` in an SSA representation.
23+
*/
24+
private predicate needsPhiNode(BasicBlock bb, LocalScopeVariable v) {
25+
exists(BasicBlock def |
26+
def.inDominanceFrontier(bb) |
27+
defAt(def, _, _, v) or
28+
needsPhiNode(def, v)
29+
)
30+
}
31+
32+
private newtype SsaRefKind = SsaRead() or SsaDef()
33+
34+
/**
35+
* Holds if the `i`th node of basic block `bb` is a reference to `v`,
36+
* either a read (when `k` is `SsaRead()`) or a write including phi nodes
37+
* (when `k` is `SsaDef()`).
38+
*/
39+
private predicate ssaRef(BasicBlock bb, int i, LocalScopeVariable v, SsaRefKind k) {
40+
bb.getNode(i).getElement() = v.getAnAccess().(VariableRead) and
41+
k = SsaRead()
42+
or
43+
defAt(bb, i, _, v) and
44+
k = SsaDef()
45+
or
46+
needsPhiNode(bb, v) and
47+
i = -1 and
48+
k = SsaDef()
49+
}
50+
51+
/**
52+
* Gets the (1-based) rank of the reference to `v` at the `i`th node of basic
53+
* block `bb`, which has the given reference kind `k`.
54+
*/
55+
private int ssaRefRank(BasicBlock bb, int i, LocalScopeVariable v, SsaRefKind k) {
56+
i = rank[result](int j | ssaRef(bb, j, v, _)) and
57+
ssaRef(bb, i, v, k)
58+
}
59+
60+
/**
61+
* Holds if definition `def` of local scope variable `v` inside basic block
62+
* `bb` reaches the reference at rank `rnk`, without passing through another
63+
* definition of `v`, including phi nodes.
64+
*/
65+
private predicate defReachesRank(BasicBlock bb, AssignableDefinition def, LocalScopeVariable v, int rnk) {
66+
exists(int i |
67+
rnk = ssaRefRank(bb, i, v, SsaDef()) |
68+
defAt(bb, i, def, v)
69+
)
70+
or
71+
defReachesRank(bb, def, v, rnk - 1) and
72+
rnk = ssaRefRank(bb, _, v, SsaRead())
73+
}
74+
75+
/**
76+
* Holds if definition `def` of local scope variable `v` reaches the end of
77+
* basic block `bb` without passing through another definition of `v`, including
78+
* phi nodes.
79+
*/
80+
private predicate reachesEndOf(AssignableDefinition def, LocalScopeVariable v, BasicBlock bb) {
81+
exists(int rnk |
82+
defReachesRank(bb, def, v, rnk) and
83+
rnk = max(ssaRefRank(bb, _, v, _))
84+
)
85+
or
86+
exists(BasicBlock mid |
87+
reachesEndOf(def, v, mid) and
88+
not exists(ssaRefRank(mid, _, v, SsaDef())) and
89+
bb = mid.getASuccessor()
90+
)
91+
}
92+
93+
/**
94+
* Gets a read of the SSA definition for variable `v` at definition `def`. That is,
95+
* a read that is guaranteed to read the value assigned at definition `def`.
96+
*/
97+
cached AssignableRead getARead(AssignableDefinition def, LocalScopeVariable v) {
98+
exists(BasicBlock bb, int i, int rnk |
99+
result.getTarget() = v and
100+
result.getAControlFlowNode() = bb.getNode(i) and
101+
rnk = ssaRefRank(bb, i, v, SsaRead())
102+
|
103+
defReachesRank(bb, def, v, rnk)
104+
or
105+
reachesEndOf(def, v, bb.getAPredecessor()) and
106+
not ssaRefRank(bb, i, v, SsaDef()) < rnk
107+
)
108+
}
109+
}

csharp/ql/src/semmle/code/csharp/dataflow/DataFlowInternal.qll renamed to csharp/ql/src/semmle/code/csharp/dataflow/internal/Steps.qll

Lines changed: 4 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,5 @@
11
import csharp
22

3-
private cached module MiniSsa {
4-
private import ControlFlowGraph
5-
6-
/**
7-
* Holds if the `i`th node of basic block `bb` is assignable definition `def`,
8-
* targeting local scope variable `v`.
9-
*/
10-
private predicate defAt(BasicBlock bb, int i, AssignableDefinition def, LocalScopeVariable v) {
11-
bb.getNode(i) = def.getAControlFlowNode() and
12-
v = def.getTarget()
13-
}
14-
15-
/**
16-
* Holds if basic block `bb` would need to start with a phi node for local scope
17-
* variable `v` in an SSA representation.
18-
*/
19-
private predicate needsPhiNode(BasicBlock bb, LocalScopeVariable v) {
20-
exists(BasicBlock def |
21-
def.inDominanceFrontier(bb) |
22-
defAt(def, _, _, v) or
23-
needsPhiNode(def, v)
24-
)
25-
}
26-
27-
private newtype SsaRefKind = SsaRead() or SsaDef()
28-
29-
/**
30-
* Holds if the `i`th node of basic block `bb` is a reference to `v`,
31-
* either a read (when `k` is `SsaRead()`) or a write including phi nodes
32-
* (when `k` is `SsaDef()`).
33-
*/
34-
private predicate ssaRef(BasicBlock bb, int i, LocalScopeVariable v, SsaRefKind k) {
35-
bb.getNode(i).getElement() = v.getAnAccess().(VariableRead) and
36-
k = SsaRead()
37-
or
38-
defAt(bb, i, _, v) and
39-
k = SsaDef()
40-
or
41-
needsPhiNode(bb, v) and
42-
i = -1 and
43-
k = SsaDef()
44-
}
45-
46-
/**
47-
* Gets the (1-based) rank of the reference to `v` at the `i`th node of basic
48-
* block `bb`, which has the given reference kind `k`.
49-
*/
50-
private int ssaRefRank(BasicBlock bb, int i, LocalScopeVariable v, SsaRefKind k) {
51-
i = rank[result](int j | ssaRef(bb, j, v, _)) and
52-
ssaRef(bb, i, v, k)
53-
}
54-
55-
/**
56-
* Holds if definition `def` of local scope variable `v` inside basic block
57-
* `bb` reaches the reference at rank `rnk`, without passing through another
58-
* definition of `v`, including phi nodes.
59-
*/
60-
private predicate defReachesRank(BasicBlock bb, AssignableDefinition def, LocalScopeVariable v, int rnk) {
61-
exists(int i |
62-
rnk = ssaRefRank(bb, i, v, SsaDef()) |
63-
defAt(bb, i, def, v)
64-
)
65-
or
66-
defReachesRank(bb, def, v, rnk - 1) and
67-
rnk = ssaRefRank(bb, _, v, SsaRead())
68-
}
69-
70-
/**
71-
* Holds if definition `def` of local scope variable `v` reaches the end of
72-
* basic block `bb` without passing through another definition of `v`, including
73-
* phi nodes.
74-
*/
75-
private predicate reachesEndOf(AssignableDefinition def, LocalScopeVariable v, BasicBlock bb) {
76-
exists(int rnk |
77-
defReachesRank(bb, def, v, rnk) and
78-
rnk = max(ssaRefRank(bb, _, v, _))
79-
)
80-
or
81-
exists(BasicBlock mid |
82-
reachesEndOf(def, v, mid) and
83-
not exists(ssaRefRank(mid, _, v, SsaDef())) and
84-
bb = mid.getASuccessor()
85-
)
86-
}
87-
88-
/**
89-
* Gets a read of the SSA definition for variable `v` at definition `def`. That is,
90-
* a read that is guaranteed to read the value assigned at definition `def`.
91-
*/
92-
cached AssignableRead getARead(AssignableDefinition def, LocalScopeVariable v) {
93-
exists(BasicBlock bb, int i, int rnk |
94-
result.getTarget() = v and
95-
result.getAControlFlowNode() = bb.getNode(i) and
96-
rnk = ssaRefRank(bb, i, v, SsaRead())
97-
|
98-
defReachesRank(bb, def, v, rnk)
99-
or
100-
reachesEndOf(def, v, bb.getAPredecessor()) and
101-
not ssaRefRank(bb, i, v, SsaDef()) < rnk
102-
)
103-
}
104-
}
105-
1063
/**
1074
* INTERNAL: Do not use.
1085
*
@@ -112,12 +9,14 @@ private cached module MiniSsa {
1129
* Instead, this library relies on a self-contained, minimalistic SSA-like
11310
* implementation.
11411
*/
115-
module DataFlowInternal {
12+
module Steps {
13+
private import semmle.code.csharp.dataflow.internal.BaseSSA
14+
11615
/**
11716
* Gets a read that is guaranteed to read the value assigned at definition `def`.
11817
*/
11918
private AssignableRead getARead(AssignableDefinition def) {
120-
result = MiniSsa::getARead(def, _)
19+
result = BaseSsa::getARead(def, _)
12120
or
12221
exists(LocalScopeVariable v |
12322
def.getTarget() = v |

csharp/ql/src/semmle/code/csharp/dispatch/Dispatch.qll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import csharp
99
private import RuntimeCallable
1010
private import OverridableCallable
1111
private import semmle.code.csharp.Conversion
12-
private import semmle.code.csharp.dataflow.DataFlowInternal
12+
private import semmle.code.csharp.dataflow.internal.Steps
1313
private import semmle.code.csharp.frameworks.System
1414
private import semmle.code.csharp.frameworks.system.Reflection
1515

@@ -145,8 +145,8 @@ private module Internal {
145145
* using simple data flow.
146146
*/
147147
private Expr getAMethodCallArgSource(MethodCallArg e) {
148-
DataFlowInternal::stepOpen*(result, e) and
149-
not DataFlowInternal::stepOpen(_, result)
148+
Steps::stepOpen*(result, e) and
149+
not Steps::stepOpen(_, result)
150150
}
151151

152152
/**
@@ -302,7 +302,7 @@ private module Internal {
302302
}
303303

304304
private predicate stepExpr0(Expr succ, Expr pred) {
305-
DataFlowInternal::stepOpen(pred, succ)
305+
Steps::stepOpen(pred, succ)
306306
or
307307
exists(Assignable a |
308308
a instanceof Field or

0 commit comments

Comments
 (0)