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

Skip to content

Commit 952b2da

Browse files
committed
C#: Add copy of ControlFlowReachability.qll to be used by sign/modulus analysis
1 parent c32242e commit 952b2da

2 files changed

Lines changed: 219 additions & 0 deletions

File tree

config/identical-files.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,10 @@
345345
"csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll",
346346
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll"
347347
],
348+
"C# ControlFlowReachability": [
349+
"csharp/ql/src/semmle/code/csharp/dataflow/internal/ControlFlowReachability.qll",
350+
"csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ControlFlowReachability.qll"
351+
],
348352
"Inline Test Expectations": [
349353
"cpp/ql/test/TestUtilities/InlineExpectationsTest.qll",
350354
"python/ql/test/TestUtilities/InlineExpectationsTest.qll"
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
import csharp
2+
3+
private class ControlFlowScope extends ControlFlowElement {
4+
private boolean exactScope;
5+
6+
ControlFlowScope() {
7+
exists(ControlFlowReachabilityConfiguration c |
8+
c.candidate(_, _, this, exactScope, _) or
9+
c.candidateDef(_, _, this, exactScope, _)
10+
)
11+
}
12+
13+
predicate isExact() { exactScope = true }
14+
15+
predicate isNonExact() { exactScope = false }
16+
}
17+
18+
private ControlFlowElement getANonExactScopeChild(ControlFlowScope scope) {
19+
scope.isNonExact() and
20+
result = scope
21+
or
22+
result = getANonExactScopeChild(scope).getAChild()
23+
}
24+
25+
pragma[noinline]
26+
private ControlFlow::BasicBlock getABasicBlockInScope(ControlFlowScope scope, boolean exactScope) {
27+
result.getANode().getElement() = getANonExactScopeChild(scope) and
28+
exactScope = false
29+
or
30+
scope.isExact() and
31+
result.getANode().getElement() = scope and
32+
exactScope = true
33+
}
34+
35+
/**
36+
* A helper class for determining control-flow reachability for pairs of
37+
* elements.
38+
*
39+
* This is useful when defining for example expression-based data-flow steps in
40+
* the presence of control-flow splitting, where a data-flow step should make
41+
* sure to stay in the same split.
42+
*
43+
* For example, in
44+
*
45+
* ```csharp
46+
* if (b)
47+
* ....
48+
* var x = "foo";
49+
* if (b)
50+
* ....
51+
* ```
52+
*
53+
* there should only be steps from `[b = true] "foo"` to `[b = true] SSA def(x)`
54+
* and `[b = false] "foo"` to `[b = false] SSA def(x)`, and for example not from
55+
* `[b = true] "foo"` to `[b = false] SSA def(x)`
56+
*/
57+
abstract class ControlFlowReachabilityConfiguration extends string {
58+
bindingset[this]
59+
ControlFlowReachabilityConfiguration() { any() }
60+
61+
/**
62+
* Holds if `e1` and `e2` are expressions for which we want to find a
63+
* control-flow path that follows control flow successors (resp.
64+
* predecessors, as specified by `isSuccesor`) inside the syntactic scope
65+
* `scope`. The Boolean `exactScope` indicates whether a transitive child
66+
* of `scope` is allowed (`exactScope = false`).
67+
*/
68+
predicate candidate(
69+
Expr e1, Expr e2, ControlFlowElement scope, boolean exactScope, boolean isSuccessor
70+
) {
71+
none()
72+
}
73+
74+
/**
75+
* Holds if `e` and `def` are elements for which we want to find a
76+
* control-flow path that follows control flow successors (resp.
77+
* predecessors, as specified by `isSuccesor`) inside the syntactic scope
78+
* `scope`. The Boolean `exactScope` indicates whether a transitive child
79+
* of `scope` is allowed (`exactScope = false`).
80+
*/
81+
predicate candidateDef(
82+
Expr e, AssignableDefinition def, ControlFlowElement scope, boolean exactScope,
83+
boolean isSuccessor
84+
) {
85+
none()
86+
}
87+
88+
pragma[nomagic]
89+
private predicate reachesBasicBlockExprBase(
90+
Expr e1, Expr e2, boolean isSuccessor, ControlFlow::Nodes::ElementNode cfn1, int i,
91+
ControlFlow::BasicBlock bb
92+
) {
93+
this.candidate(e1, e2, _, _, isSuccessor) and
94+
cfn1 = e1.getAControlFlowNode() and
95+
bb.getNode(i) = cfn1
96+
}
97+
98+
pragma[nomagic]
99+
private predicate reachesBasicBlockExprRec(
100+
Expr e1, Expr e2, boolean isSuccessor, ControlFlow::Nodes::ElementNode cfn1,
101+
ControlFlow::BasicBlock bb
102+
) {
103+
exists(ControlFlow::BasicBlock mid |
104+
this.reachesBasicBlockExpr(e1, e2, isSuccessor, cfn1, mid)
105+
|
106+
isSuccessor = true and
107+
bb = mid.getASuccessor()
108+
or
109+
isSuccessor = false and
110+
bb = mid.getAPredecessor()
111+
)
112+
}
113+
114+
pragma[nomagic]
115+
private predicate reachesBasicBlockExpr(
116+
Expr e1, Expr e2, boolean isSuccessor, ControlFlow::Nodes::ElementNode cfn1,
117+
ControlFlow::BasicBlock bb
118+
) {
119+
this.reachesBasicBlockExprBase(e1, e2, isSuccessor, cfn1, _, bb)
120+
or
121+
exists(ControlFlowElement scope, boolean exactScope |
122+
this.candidate(e1, e2, scope, exactScope, isSuccessor) and
123+
this.reachesBasicBlockExprRec(e1, e2, isSuccessor, cfn1, bb) and
124+
bb = getABasicBlockInScope(scope, exactScope)
125+
)
126+
}
127+
128+
pragma[nomagic]
129+
private predicate reachesBasicBlockDefinitionBase(
130+
Expr e, AssignableDefinition def, boolean isSuccessor, ControlFlow::Nodes::ElementNode cfn,
131+
int i, ControlFlow::BasicBlock bb
132+
) {
133+
this.candidateDef(e, def, _, _, isSuccessor) and
134+
cfn = e.getAControlFlowNode() and
135+
bb.getNode(i) = cfn
136+
}
137+
138+
pragma[nomagic]
139+
private predicate reachesBasicBlockDefinitionRec(
140+
Expr e, AssignableDefinition def, boolean isSuccessor, ControlFlow::Nodes::ElementNode cfn,
141+
ControlFlow::BasicBlock bb
142+
) {
143+
exists(ControlFlow::BasicBlock mid |
144+
this.reachesBasicBlockDefinition(e, def, isSuccessor, cfn, mid)
145+
|
146+
isSuccessor = true and
147+
bb = mid.getASuccessor()
148+
or
149+
isSuccessor = false and
150+
bb = mid.getAPredecessor()
151+
)
152+
}
153+
154+
pragma[nomagic]
155+
private predicate reachesBasicBlockDefinition(
156+
Expr e, AssignableDefinition def, boolean isSuccessor, ControlFlow::Nodes::ElementNode cfn,
157+
ControlFlow::BasicBlock bb
158+
) {
159+
this.reachesBasicBlockDefinitionBase(e, def, isSuccessor, cfn, _, bb)
160+
or
161+
exists(ControlFlowElement scope, boolean exactScope |
162+
this.candidateDef(e, def, scope, exactScope, isSuccessor) and
163+
this.reachesBasicBlockDefinitionRec(e, def, isSuccessor, cfn, bb) and
164+
bb = getABasicBlockInScope(scope, exactScope)
165+
)
166+
}
167+
168+
/**
169+
* Holds if there is a control-flow path from `cfn1` to `cfn2`, where `cfn1` is a
170+
* control-flow node for `e1` and `cfn2` is a control-flow node for `e2`.
171+
*/
172+
pragma[nomagic]
173+
predicate hasExprPath(Expr e1, ControlFlow::Node cfn1, Expr e2, ControlFlow::Node cfn2) {
174+
exists(ControlFlow::BasicBlock bb, boolean isSuccessor, int i, int j |
175+
this.reachesBasicBlockExprBase(e1, e2, isSuccessor, cfn1, i, bb) and
176+
cfn2 = bb.getNode(j) and
177+
cfn2 = e2.getAControlFlowNode()
178+
|
179+
isSuccessor = true and j >= i
180+
or
181+
isSuccessor = false and i >= j
182+
)
183+
or
184+
exists(ControlFlow::BasicBlock bb |
185+
this.reachesBasicBlockExprRec(e1, e2, _, cfn1, bb) and
186+
cfn2 = bb.getANode() and
187+
cfn2 = e2.getAControlFlowNode()
188+
)
189+
}
190+
191+
/**
192+
* Holds if there is a control-flow path from `cfn` to `cfnDef`, where `cfn` is a
193+
* control-flow node for `e` and `cfnDef` is a control-flow node for `def`.
194+
*/
195+
pragma[nomagic]
196+
predicate hasDefPath(
197+
Expr e, ControlFlow::Node cfn, AssignableDefinition def, ControlFlow::Node cfnDef
198+
) {
199+
exists(ControlFlow::BasicBlock bb, boolean isSuccessor, int i, int j |
200+
this.reachesBasicBlockDefinitionBase(e, def, isSuccessor, cfn, i, bb) and
201+
cfnDef = bb.getNode(j) and
202+
def.getAControlFlowNode() = cfnDef
203+
|
204+
isSuccessor = true and j >= i
205+
or
206+
isSuccessor = false and i >= j
207+
)
208+
or
209+
exists(ControlFlow::BasicBlock bb |
210+
this.reachesBasicBlockDefinitionRec(e, def, _, cfn, bb) and
211+
def.getAControlFlowNode() = cfnDef and
212+
cfnDef = bb.getANode()
213+
)
214+
}
215+
}

0 commit comments

Comments
 (0)