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

Skip to content

Commit bb637f6

Browse files
committed
C#: Introduce CfgScope class and generalize ControlFlowTree to include callables
1 parent a92404a commit bb637f6

7 files changed

Lines changed: 119 additions & 98 deletions

File tree

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

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -390,19 +390,14 @@ class ExitBasicBlock extends BasicBlock {
390390

391391
private module JoinBlockPredecessors {
392392
private import ControlFlow::Nodes
393-
394-
private class CallableOrCFE extends Element {
395-
CallableOrCFE() { this instanceof Callable or this instanceof ControlFlowElement }
396-
}
397-
398-
private predicate id(CallableOrCFE x, CallableOrCFE y) { x = y }
399-
400-
private predicate idOf(CallableOrCFE x, int y) = equivalenceRelation(id/2)(x, y)
393+
private import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl
401394

402395
int getId(JoinBlockPredecessor jbp) {
403-
idOf(jbp.getFirstNode().(ElementNode).getElement(), result)
404-
or
405-
idOf(jbp.(EntryBasicBlock).getCallable(), result)
396+
exists(ControlFlowTree::Range t | ControlFlowTree::idOf(t, result) |
397+
t = jbp.getFirstNode().getElement()
398+
or
399+
t = jbp.(EntryBasicBlock).getCallable()
400+
)
406401
}
407402

408403
string getSplitString(JoinBlockPredecessor jbp) {

csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,20 @@ private import SuccessorTypes
5050
private import Splitting
5151
private import semmle.code.csharp.ExprOrStmtParent
5252

53-
abstract private class ControlFlowTree extends ControlFlowElement {
53+
/** An element that defines a new CFG scope. */
54+
class CfgScope extends Element, @top_level_exprorstmt_parent { }
55+
56+
module ControlFlowTree {
57+
private class Range_ = @callable or @control_flow_element;
58+
59+
class Range extends Element, Range_ { }
60+
61+
private predicate id(Range x, Range y) { x = y }
62+
63+
predicate idOf(Range x, int y) = equivalenceRelation(id/2)(x, y)
64+
}
65+
66+
abstract private class ControlFlowTree extends ControlFlowTree::Range {
5467
/**
5568
* Holds if `first` is the first element executed within this control
5669
* flow element.
@@ -103,26 +116,10 @@ predicate last(ControlFlowTree cft, ControlFlowElement last, Completion c) {
103116
pragma[nomagic]
104117
predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
105118
any(ControlFlowTree cft).succ(pred, succ, c)
106-
or
107-
exists(Constructor con, InitializerSplitting::InitializedInstanceMember m, int i |
108-
last(m.getInitializer(), pred, c) and
109-
c instanceof NormalCompletion and
110-
InitializerSplitting::constructorInitializeOrder(con, m, i)
111-
|
112-
// Flow from one member initializer to the next
113-
exists(InitializerSplitting::InitializedInstanceMember next |
114-
InitializerSplitting::constructorInitializeOrder(con, next, i + 1) and
115-
first(next.getInitializer(), succ)
116-
)
117-
or
118-
// Flow from last member initializer to constructor body
119-
m = InitializerSplitting::lastConstructorInitializer(con) and
120-
first(con.getBody(), succ)
121-
)
122119
}
123120

124121
/** Holds if `first` is first executed when entering `scope`. */
125-
predicate succEntry(@top_level_exprorstmt_parent scope, ControlFlowElement first) {
122+
predicate scopeFirst(CfgScope scope, ControlFlowElement first) {
126123
scope =
127124
any(Callable c |
128125
if exists(c.(Constructor).getInitializer())
@@ -142,7 +139,7 @@ predicate succEntry(@top_level_exprorstmt_parent scope, ControlFlowElement first
142139
}
143140

144141
/** Holds if `scope` is exited when `last` finishes with completion `c`. */
145-
predicate succExit(ControlFlowElement last, Callable scope, Completion c) {
142+
predicate scopeLast(Callable scope, ControlFlowElement last, Completion c) {
146143
last(scope.getBody(), last, c) and
147144
not c instanceof GotoCompletion
148145
or
@@ -153,6 +150,33 @@ predicate succExit(ControlFlowElement last, Callable scope, Completion c) {
153150
)
154151
}
155152

153+
private class CallableTree extends ControlFlowTree, Callable {
154+
final override predicate propagatesAbnormal(ControlFlowElement child) { none() }
155+
156+
final override predicate first(ControlFlowElement first) { none() }
157+
158+
final override predicate last(ControlFlowElement last, Completion c) { none() }
159+
160+
final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
161+
exists(Constructor con, InitializerSplitting::InitializedInstanceMember m, int i |
162+
this = con and
163+
last(m.getInitializer(), pred, c) and
164+
c instanceof NormalCompletion and
165+
InitializerSplitting::constructorInitializeOrder(con, m, i)
166+
|
167+
// Flow from one member initializer to the next
168+
exists(InitializerSplitting::InitializedInstanceMember next |
169+
InitializerSplitting::constructorInitializeOrder(con, next, i + 1) and
170+
first(next.getInitializer(), succ)
171+
)
172+
or
173+
// Flow from last member initializer to constructor body
174+
m = InitializerSplitting::lastConstructorInitializer(con) and
175+
first(con.getBody(), succ)
176+
)
177+
}
178+
}
179+
156180
/**
157181
* A control flow element where the children are evaluated following a
158182
* standard left-to-right evaluation. The actual evaluation order is
@@ -347,7 +371,7 @@ module Expressions {
347371
not this instanceof ConstructorInitializer
348372
}
349373

350-
final override ControlFlowTree getChildElement(int i) { result = getExprChild(this, i) }
374+
final override ControlFlowElement getChildElement(int i) { result = getExprChild(this, i) }
351375

352376
final override predicate first(ControlFlowElement first) {
353377
first(this.getFirstChild(), first)
@@ -945,7 +969,7 @@ module Statements {
945969
)
946970
}
947971

948-
final override ControlFlowTree getChildElement(int i) {
972+
final override ControlFlowElement getChildElement(int i) {
949973
result =
950974
rank[i + 1](ControlFlowElement cfe, int j | cfe = this.getChildElement0(j) | cfe order by j)
951975
}

csharp/ql/src/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ private predicate startsBB(ControlFlowElement cfe) {
1919
(
2020
succ(cfe, _, _)
2121
or
22-
succExit(cfe, _, _)
22+
scopeLast(_, cfe, _)
2323
)
2424
or
2525
strictcount(ControlFlowElement pred, Completion c | succ(pred, cfe, c)) > 1
@@ -33,7 +33,7 @@ private predicate startsBB(ControlFlowElement cfe) {
3333
i > 1
3434
or
3535
i = 1 and
36-
succExit(pred, _, _)
36+
scopeLast(_, pred, _)
3737
)
3838
}
3939

@@ -47,7 +47,7 @@ private predicate bbIndex(ControlFlowElement bbStart, ControlFlowElement cfe, in
4747

4848
private predicate succBB(PreBasicBlock pred, PreBasicBlock succ) { succ = pred.getASuccessor() }
4949

50-
private predicate entryBB(PreBasicBlock bb) { succEntry(_, bb) }
50+
private predicate entryBB(PreBasicBlock bb) { scopeFirst(_, bb) }
5151

5252
private predicate bbIDominates(PreBasicBlock dom, PreBasicBlock bb) =
5353
idominance(entryBB/1, succBB/2)(_, dom, bb)
@@ -100,7 +100,7 @@ class ConditionBlock extends PreBasicBlock {
100100
exists(Completion c | c = getConditionalCompletion(_) |
101101
succ(this.getLastElement(), _, c)
102102
or
103-
succExit(this.getLastElement(), _, c)
103+
scopeLast(_, this.getLastElement(), c)
104104
)
105105
}
106106

csharp/ql/src/semmle/code/csharp/controlflow/internal/PreSsa.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ class Definition extends TPreSsaDef {
140140
predicate implicitEntryDef(Callable c, PreBasicBlock bb, SimpleAssignable a) {
141141
not a instanceof LocalScopeVariable and
142142
c = a.getACallable() and
143-
succEntry(c, bb)
143+
scopeFirst(c, bb)
144144
}
145145

146146
private predicate assignableDefAt(
@@ -157,7 +157,7 @@ private predicate assignableDefAt(
157157
or
158158
def.(ImplicitParameterDefinition).getParameter() = a and
159159
exists(Callable c | a = c.getAParameter() |
160-
succEntry(c, bb) and
160+
scopeFirst(c, bb) and
161161
i = -1
162162
)
163163
}
@@ -169,7 +169,7 @@ private predicate readAt(PreBasicBlock bb, int i, AssignableRead read, SimpleAss
169169

170170
pragma[noinline]
171171
private predicate exitBlock(PreBasicBlock bb, Callable c) {
172-
succExit(bb.getLastElement(), _, _) and
172+
scopeLast(c, bb.getLastElement(), _) and
173173
c = bb.getEnclosingCallable()
174174
}
175175

0 commit comments

Comments
 (0)