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

Skip to content

Commit b8caa11

Browse files
committed
C#: Add internal PreBasicBlocks library
1 parent f146e34 commit b8caa11

3 files changed

Lines changed: 174 additions & 11 deletions

File tree

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

Lines changed: 124 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ module ControlFlow {
3434

3535
/** Holds if this control flow node has conditional successors. */
3636
predicate isCondition() {
37-
exists(getASuccessorByType(any(SuccessorTypes::ConditionalSuccessor e)))
37+
exists(getASuccessorByType(any(ConditionalSuccessor e)))
3838
}
3939

4040
/** Gets the basic block that this control flow node belongs to. */
@@ -216,7 +216,7 @@ module ControlFlow {
216216
* on line 1.
217217
*/
218218
Node getATrueSuccessor() {
219-
result = getASuccessorByType(any(SuccessorTypes::BooleanSuccessor t | t.getValue() = true))
219+
result = getASuccessorByType(any(BooleanSuccessor t | t.getValue() = true))
220220
}
221221

222222
/**
@@ -236,7 +236,7 @@ module ControlFlow {
236236
* on line 1.
237237
*/
238238
Node getAFalseSuccessor() {
239-
result = getASuccessorByType(any(SuccessorTypes::BooleanSuccessor t | t.getValue() = false))
239+
result = getASuccessorByType(any(BooleanSuccessor t | t.getValue() = false))
240240
}
241241

242242
/**
@@ -256,7 +256,7 @@ module ControlFlow {
256256
* `x` on line 1.
257257
*/
258258
Node getANullSuccessor() {
259-
result = getASuccessorByType(any(SuccessorTypes::NullnessSuccessor t | t.isNull()))
259+
result = getASuccessorByType(any(NullnessSuccessor t | t.isNull()))
260260
}
261261

262262
/**
@@ -275,7 +275,7 @@ module ControlFlow {
275275
* of the node `x`.
276276
*/
277277
Node getANonNullSuccessor() {
278-
result = getASuccessorByType(any(SuccessorTypes::NullnessSuccessor t | not t.isNull()))
278+
result = getASuccessorByType(any(NullnessSuccessor t | not t.isNull()))
279279
}
280280

281281
/** Holds if this node has more than one predecessor. */
@@ -775,6 +775,7 @@ module ControlFlow {
775775
}
776776
}
777777
}
778+
private import SuccessorTypes
778779

779780
/**
780781
* INTERNAL: Do not use.
@@ -2382,6 +2383,118 @@ module ControlFlow {
23822383
}
23832384
import Successor
23842385

2386+
/**
2387+
* Provides a basic block implementation on control flow elements. That is,
2388+
* a "pre-CFG" where the nodes are (unsplit) control flow elements and the
2389+
* successor releation is `succ = succ(pred, _)`.
2390+
*
2391+
* The logic is duplicated from the implementation in `BasicBlocks.qll`, and
2392+
* being an internal class, all predicate documentation has been removed.
2393+
*/
2394+
module PreBasicBlocks {
2395+
private predicate startsBB(ControlFlowElement cfe) {
2396+
not cfe = succ(_, _) and
2397+
(
2398+
exists(succ(cfe, _))
2399+
or
2400+
exists(succExit(cfe, _))
2401+
)
2402+
or
2403+
strictcount(ControlFlowElement pred, Completion c | cfe = succ(pred, c)) > 1
2404+
or
2405+
exists(ControlFlowElement pred, int i |
2406+
cfe = succ(pred, _) and
2407+
i = count(ControlFlowElement succ, Completion c | succ = succ(pred, c)) |
2408+
i > 1
2409+
or
2410+
i = 1 and
2411+
exists(succExit(pred, _))
2412+
)
2413+
}
2414+
2415+
private predicate intraBBSucc(ControlFlowElement pred, ControlFlowElement succ) {
2416+
succ = succ(pred, _) and
2417+
not startsBB(succ)
2418+
}
2419+
2420+
predicate bbIndex(ControlFlowElement bbStart, ControlFlowElement cfe, int i) =
2421+
shortestDistances(startsBB/1, intraBBSucc/2)(bbStart, cfe, i)
2422+
2423+
private predicate succBB(PreBasicBlock pred, PreBasicBlock succ) {
2424+
succ = pred.getASuccessor()
2425+
}
2426+
2427+
private predicate entryBB(PreBasicBlock bb) {
2428+
bb = succEntry(_)
2429+
}
2430+
2431+
private predicate bbIDominates(PreBasicBlock dom, PreBasicBlock bb) =
2432+
idominance(entryBB/1, succBB/2)(_, dom, bb)
2433+
2434+
class PreBasicBlock extends ControlFlowElement {
2435+
PreBasicBlock() {
2436+
startsBB(this)
2437+
}
2438+
2439+
PreBasicBlock getASuccessor() {
2440+
result = succ(this.getLastElement(), _)
2441+
}
2442+
2443+
PreBasicBlock getAPredecessor() {
2444+
result.getASuccessor() = this
2445+
}
2446+
2447+
ControlFlowElement getElement(int pos) {
2448+
bbIndex(this, result, pos)
2449+
}
2450+
2451+
ControlFlowElement getAnElement() {
2452+
result = this.getElement(_)
2453+
}
2454+
2455+
ControlFlowElement getFirstElement() {
2456+
result = this
2457+
}
2458+
2459+
ControlFlowElement getLastElement() {
2460+
result = this.getElement(length() - 1)
2461+
}
2462+
2463+
int length() {
2464+
result = strictcount(getAnElement())
2465+
}
2466+
2467+
predicate strictlyDominates(PreBasicBlock bb) {
2468+
bbIDominates+(this, bb)
2469+
}
2470+
2471+
predicate dominates(PreBasicBlock bb) {
2472+
bb = this
2473+
or
2474+
this.strictlyDominates(bb)
2475+
}
2476+
2477+
predicate inDominanceFrontier(PreBasicBlock df) {
2478+
this.dominatesPredecessor(df) and
2479+
not this.strictlyDominates(df)
2480+
}
2481+
2482+
private predicate dominatesPredecessor(PreBasicBlock df) {
2483+
this.dominates(df.getAPredecessor())
2484+
}
2485+
}
2486+
2487+
class ConditionBlock extends PreBasicBlock {
2488+
ConditionBlock() {
2489+
strictcount(ConditionalCompletion c |
2490+
exists(succ(this.getLastElement(), c))
2491+
or
2492+
exists(succExit(this.getLastElement(), c))
2493+
) > 1
2494+
}
2495+
}
2496+
}
2497+
23852498
/**
23862499
* Provides classes and predicates relevant for splitting the control flow graph.
23872500
*/
@@ -2464,15 +2577,15 @@ module ControlFlow {
24642577
*/
24652578
class FinallySplitType extends SuccessorType {
24662579
FinallySplitType() {
2467-
not this instanceof SuccessorTypes::ConditionalSuccessor
2580+
not this instanceof ConditionalSuccessor
24682581
}
24692582

24702583
/** Holds if this split type matches entry into a `finally` block with completion `c`. */
24712584
predicate isSplitForEntryCompletion(Completion c) {
24722585
if c instanceof NormalCompletion then
24732586
// If the entry into the `finally` block completes with any normal completion,
24742587
// it simply means normal execution after the `finally` block
2475-
this instanceof SuccessorTypes::NormalSuccessor
2588+
this instanceof NormalSuccessor
24762589
else
24772590
this.matchesCompletion(c)
24782591
}
@@ -2561,7 +2674,7 @@ module ControlFlow {
25612674
}
25622675

25632676
override string toString() {
2564-
if type instanceof SuccessorTypes::NormalSuccessor then
2677+
if type instanceof NormalSuccessor then
25652678
result = ""
25662679
else
25672680
result = "finally: " + type.toString()
@@ -2603,12 +2716,12 @@ module ControlFlow {
26032716
or
26042717
not c instanceof NormalCompletion
26052718
or
2606-
type instanceof SuccessorTypes::NormalSuccessor
2719+
type instanceof NormalSuccessor
26072720
) else (
26082721
// Finally block can exit with completion `c` derived from try/catch
26092722
// block: must match this split
26102723
type.matchesCompletion(c) and
2611-
not type instanceof SuccessorTypes::NormalSuccessor
2724+
not type instanceof NormalSuccessor
26122725
)
26132726
)
26142727
}
@@ -2895,7 +3008,7 @@ module ControlFlow {
28953008
pragma [noinline]
28963009
predicate succEntrySplits(Callable pred, ControlFlowElement succ, Splits succSplits, SuccessorType t) {
28973010
succ = succEntry(pred) and
2898-
t instanceof SuccessorTypes::NormalSuccessor and
3011+
t instanceof NormalSuccessor and
28993012
succSplits = TSplitsNil() // initially no splits
29003013
}
29013014

csharp/ql/test/library-tests/controlflow/graph/PreBasicBlockConsistency.expected

Whitespace-only changes.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import csharp
2+
import ControlFlow::Internal::PreBasicBlocks
3+
4+
predicate bbStartInconsistency(ControlFlowElement cfe) {
5+
exists(ControlFlow::BasicBlock bb |
6+
bb.getFirstNode() = cfe.getAControlFlowNode()
7+
) and
8+
not cfe = any(PreBasicBlock bb).getFirstElement()
9+
}
10+
11+
predicate bbSuccInconsistency(ControlFlowElement pred, ControlFlowElement succ) {
12+
exists(ControlFlow::BasicBlock predBB, ControlFlow::BasicBlock succBB |
13+
predBB.getLastNode() = pred.getAControlFlowNode() and
14+
succBB = predBB.getASuccessor() and
15+
succBB.getFirstNode() = succ.getAControlFlowNode()
16+
) and
17+
not exists(PreBasicBlock predBB, PreBasicBlock succBB |
18+
predBB.getLastElement() = pred and
19+
succBB = predBB.getASuccessor() and
20+
succBB.getFirstElement() = succ
21+
)
22+
}
23+
24+
predicate bbIntraSuccInconsistency(ControlFlowElement pred, ControlFlowElement succ) {
25+
exists(ControlFlow::BasicBlock bb, int i |
26+
pred.getAControlFlowNode() = bb.getNode(i) and
27+
succ.getAControlFlowNode() = bb.getNode(i + 1)
28+
) and
29+
not exists(PreBasicBlock bb |
30+
bb.getLastElement() = pred and
31+
bb.getASuccessor().getFirstElement() = succ
32+
) and
33+
not exists(PreBasicBlock bb, int i |
34+
bb.getElement(i) = pred and
35+
bb.getElement(i + 1) = succ
36+
)
37+
}
38+
39+
from ControlFlowElement cfe1, ControlFlowElement cfe2, string s
40+
where
41+
bbStartInconsistency(cfe1) and
42+
cfe2 = cfe1 and
43+
s = "start inconsistency"
44+
or
45+
bbSuccInconsistency(cfe1, cfe2) and
46+
s = "succ inconsistency"
47+
or
48+
bbIntraSuccInconsistency(cfe1, cfe2) and
49+
s = "intra succ inconsistency"
50+
select cfe1, cfe2, s

0 commit comments

Comments
 (0)