Skip to content

Commit ce8567c

Browse files
authored
Merge pull request #4293 from hvitved/csharp/cfg/assertions
C#: Model assertions in the CFG
2 parents b70f5bc + af36718 commit ce8567c

34 files changed

+5205
-262
lines changed

csharp/ql/src/semmle/code/csharp/Caching.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ module Stages {
3939

4040
cached
4141
private predicate forceCachingInSameStageRev() {
42-
any(ControlFlowElement cfe).controlsBlock(_, _)
42+
any(ControlFlowElement cfe).controlsBlock(_, _, _)
4343
or
4444
exists(GuardedExpr ge)
4545
or

csharp/ql/src/semmle/code/csharp/commons/Assertions.qll

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class Assertion extends MethodCall {
6262
* does not work.
6363
*/
6464
pragma[nomagic]
65-
private predicate immediatelyDominatesBlockSplit(BasicBlock succ) {
65+
deprecated private predicate immediatelyDominatesBlockSplit(BasicBlock succ) {
6666
// Only calculate dominance by explicit recursion for split nodes;
6767
// all other nodes can use regular CFG dominance
6868
this instanceof ControlFlow::Internal::SplitControlFlowElement and
@@ -78,11 +78,11 @@ class Assertion extends MethodCall {
7878
}
7979

8080
pragma[noinline]
81-
private predicate strictlyDominatesJoinBlockPredecessor(JoinBlock jb, int i) {
81+
deprecated private predicate strictlyDominatesJoinBlockPredecessor(JoinBlock jb, int i) {
8282
this.strictlyDominatesSplit(jb.getJoinBlockPredecessor(i))
8383
}
8484

85-
private predicate strictlyDominatesJoinBlockSplit(JoinBlock jb, int i) {
85+
deprecated private predicate strictlyDominatesJoinBlockSplit(JoinBlock jb, int i) {
8686
i = -1 and
8787
this.strictlyDominatesJoinBlockPredecessor(jb, _)
8888
or
@@ -95,7 +95,7 @@ class Assertion extends MethodCall {
9595
}
9696

9797
pragma[nomagic]
98-
private predicate strictlyDominatesSplit(BasicBlock bb) {
98+
deprecated private predicate strictlyDominatesSplit(BasicBlock bb) {
9999
this.immediatelyDominatesBlockSplit(bb)
100100
or
101101
// Equivalent with
@@ -121,6 +121,8 @@ class Assertion extends MethodCall {
121121
}
122122

123123
/**
124+
* DEPRECATED: Use `getExpr().controlsBlock()` instead.
125+
*
124126
* Holds if this assertion strictly dominates basic block `bb`. That is, `bb`
125127
* can only be reached from the callable entry point by going via *some* basic
126128
* block containing this element.
@@ -130,7 +132,7 @@ class Assertion extends MethodCall {
130132
* in that it takes control flow splitting into account.
131133
*/
132134
pragma[nomagic]
133-
predicate strictlyDominates(BasicBlock bb) {
135+
deprecated predicate strictlyDominates(BasicBlock bb) {
134136
this.strictlyDominatesSplit(bb)
135137
or
136138
this.getAControlFlowNode().getBasicBlock().strictlyDominates(bb)

csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowElement.qll

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -126,39 +126,47 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
126126
* ```
127127
*
128128
* does not work.
129+
*
130+
* `cb` records all of the possible condition blocks for this control flow element
131+
* that a path from the callable entry point to `succ` may go through.
129132
*/
130133
pragma[nomagic]
131-
private predicate immediatelyControlsBlockSplit(BasicBlock succ, ConditionalSuccessor s) {
132-
exists(ConditionBlock cb | this.immediatelyControlsBlockSplit0(cb, succ, s) |
133-
forall(BasicBlock pred, SuccessorType t |
134-
this.immediatelyControlsBlockSplit1(cb, succ, s, pred, t)
135-
|
136-
this.immediatelyControlsBlockSplit2(cb, succ, s, pred, t)
137-
)
134+
private predicate immediatelyControlsBlockSplit(
135+
BasicBlock succ, ConditionalSuccessor s, ConditionBlock cb
136+
) {
137+
this.immediatelyControlsBlockSplit0(cb, succ, s) and
138+
forall(BasicBlock pred, SuccessorType t |
139+
this.immediatelyControlsBlockSplit1(cb, succ, s, pred, t)
140+
|
141+
this.immediatelyControlsBlockSplit2(cb, succ, s, pred, t)
138142
)
139143
}
140144

141145
pragma[noinline]
142-
private predicate controlsJoinBlockPredecessor(JoinBlock controlled, ConditionalSuccessor s, int i) {
143-
this.controlsBlockSplit(controlled.getJoinBlockPredecessor(i), s)
146+
private predicate controlsJoinBlockPredecessor(
147+
JoinBlock controlled, ConditionalSuccessor s, int i, ConditionBlock cb
148+
) {
149+
this.controlsBlockSplit(controlled.getJoinBlockPredecessor(i), s, cb)
144150
}
145151

146152
private predicate controlsJoinBlockSplit(JoinBlock controlled, ConditionalSuccessor s, int i) {
147153
i = -1 and
148-
this.controlsJoinBlockPredecessor(controlled, s, _)
154+
this.controlsJoinBlockPredecessor(controlled, s, _, _)
149155
or
150156
this.controlsJoinBlockSplit(controlled, s, i - 1) and
151157
(
152-
this.controlsJoinBlockPredecessor(controlled, s, i)
158+
this.controlsJoinBlockPredecessor(controlled, s, i, _)
153159
or
154160
controlled.dominates(controlled.getJoinBlockPredecessor(i))
155161
)
156162
}
157163

158164
cached
159-
private predicate controlsBlockSplit(BasicBlock controlled, ConditionalSuccessor s) {
165+
private predicate controlsBlockSplit(
166+
BasicBlock controlled, ConditionalSuccessor s, ConditionBlock cb
167+
) {
160168
Stages::GuardsStage::forceCachingInSameStage() and
161-
this.immediatelyControlsBlockSplit(controlled, s)
169+
this.immediatelyControlsBlockSplit(controlled, s, cb)
162170
or
163171
// Equivalent with
164172
//
@@ -178,10 +186,11 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
178186
last = max(int i | exists(controlled.(JoinBlock).getJoinBlockPredecessor(i)))
179187
|
180188
this.controlsJoinBlockSplit(controlled, s, last)
181-
)
189+
) and
190+
this.controlsJoinBlockPredecessor(controlled, s, _, cb)
182191
or
183192
not controlled instanceof JoinBlock and
184-
this.controlsBlockSplit(controlled.getAPredecessor(), s)
193+
this.controlsBlockSplit(controlled.getAPredecessor(), s, cb)
185194
}
186195

187196
/**
@@ -200,16 +209,25 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
200209
* ```
201210
*
202211
* as control flow splitting is taken into account.
212+
*
213+
* `cb` records all of the possible condition blocks for this control flow element
214+
* that a path from the callable entry point to `controlled` may go through.
203215
*/
204-
predicate controlsBlock(BasicBlock controlled, ConditionalSuccessor s) {
205-
this.controlsBlockSplit(controlled, s)
216+
predicate controlsBlock(BasicBlock controlled, ConditionalSuccessor s, ConditionBlock cb) {
217+
this.controlsBlockSplit(controlled, s, cb)
206218
or
207-
exists(ConditionBlock cb | cb.getLastNode() = this.getAControlFlowNode() |
208-
cb.controls(controlled, s)
209-
)
219+
cb.getLastNode() = this.getAControlFlowNode() and
220+
cb.controls(controlled, s)
221+
}
222+
223+
/** DEPRECATED: Use `controlsBlock/3` instead. */
224+
deprecated predicate controlsBlock(BasicBlock controlled, ConditionalSuccessor s) {
225+
this.controlsBlock(controlled, s, _)
210226
}
211227

212228
/**
229+
* DEPRECATED.
230+
*
213231
* Holds if control flow element `controlled` is controlled by this control flow
214232
* element with conditional value `s`. That is, `controlled` can only be reached
215233
* from the callable entry point by going via the `s` edge out of this element.
@@ -227,7 +245,7 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
227245
*/
228246
// potentially very large predicate, so must be inlined
229247
pragma[inline]
230-
predicate controlsElement(ControlFlowElement controlled, ConditionalSuccessor s) {
248+
deprecated predicate controlsElement(ControlFlowElement controlled, ConditionalSuccessor s) {
231249
forex(BasicBlock bb | bb = controlled.getAControlFlowNode().getBasicBlock() |
232250
this.controlsBlock(bb, s)
233251
)

0 commit comments

Comments
 (0)