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

Skip to content

Commit ebb63c8

Browse files
committed
Java: Refactor Guard.controls in terms of dominating edges.
1 parent bb67ac9 commit ebb63c8

2 files changed

Lines changed: 53 additions & 42 deletions

File tree

java/ql/src/semmle/code/java/controlflow/Dominance.qll

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,21 @@ predicate dominanceFrontier(BasicBlock x, BasicBlock w) {
8080
)
8181
}
8282

83+
/**
84+
* Holds if `(bb1, bb2)` is an edge that dominates `bb2`, that is, all other
85+
* predecessors of `bb2` are dominated by `bb2`. This implies that `bb1` is the
86+
* immediate dominator of `bb2`.
87+
*
88+
* This is a necessary and sufficient condition for an edge to dominate anything,
89+
* and in particular `dominatingEdge(bb1, bb2) and bb2.bbDominates(bb3)` means
90+
* that the edge `(bb1, bb2)` dominates `bb3`.
91+
*/
92+
predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2) {
93+
bbIDominates(bb1, bb2) and
94+
bb1.getABBSuccessor() = bb2 and
95+
forall(BasicBlock pred | pred = bb2.getABBPredecessor() and pred != bb1 | bbDominates(bb2, pred))
96+
}
97+
8398
/*
8499
* Predicates for expression-level dominance.
85100
*/

java/ql/src/semmle/code/java/controlflow/Guards.qll

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -20,51 +20,49 @@ class ConditionBlock extends BasicBlock {
2020
result = this.getConditionNode().getABranchSuccessor(testIsTrue)
2121
}
2222

23+
/*
24+
* For this block to control the block `controlled` with `testIsTrue` the following must be true:
25+
* Execution must have passed through the test i.e. `this` must strictly dominate `controlled`.
26+
* Execution must have passed through the `testIsTrue` edge leaving `this`.
27+
*
28+
* Although "passed through the true edge" implies that `this.getATrueSuccessor()` dominates `controlled`,
29+
* the reverse is not true, as flow may have passed through another edge to get to `this.getATrueSuccessor()`
30+
* so we need to assert that `this.getATrueSuccessor()` dominates `controlled` *and* that
31+
* all predecessors of `this.getATrueSuccessor()` are either `this` or dominated by `this.getATrueSuccessor()`.
32+
*
33+
* For example, in the following java snippet:
34+
* ```
35+
* if (x)
36+
* controlled;
37+
* false_successor;
38+
* uncontrolled;
39+
* ```
40+
* `false_successor` dominates `uncontrolled`, but not all of its predecessors are `this` (`if (x)`)
41+
* or dominated by itself. Whereas in the following code:
42+
* ```
43+
* if (x)
44+
* while (controlled)
45+
* also_controlled;
46+
* false_successor;
47+
* uncontrolled;
48+
* ```
49+
* the block `while controlled` is controlled because all of its predecessors are `this` (`if (x)`)
50+
* or (in the case of `also_controlled`) dominated by itself.
51+
*
52+
* The additional constraint on the predecessors of the test successor implies
53+
* that `this` strictly dominates `controlled` so that isn't necessary to check
54+
* directly.
55+
*/
56+
2357
/**
2458
* Holds if `controlled` is a basic block controlled by this condition, that
2559
* is, a basic blocks for which the condition is `testIsTrue`.
2660
*/
2761
predicate controls(BasicBlock controlled, boolean testIsTrue) {
28-
/*
29-
* For this block to control the block `controlled` with `testIsTrue` the following must be true:
30-
* Execution must have passed through the test i.e. `this` must strictly dominate `controlled`.
31-
* Execution must have passed through the `testIsTrue` edge leaving `this`.
32-
*
33-
* Although "passed through the true edge" implies that `this.getATrueSuccessor()` dominates `controlled`,
34-
* the reverse is not true, as flow may have passed through another edge to get to `this.getATrueSuccessor()`
35-
* so we need to assert that `this.getATrueSuccessor()` dominates `controlled` *and* that
36-
* all predecessors of `this.getATrueSuccessor()` are either `this` or dominated by `this.getATrueSuccessor()`.
37-
*
38-
* For example, in the following java snippet:
39-
* ```
40-
* if (x)
41-
* controlled;
42-
* false_successor;
43-
* uncontrolled;
44-
* ```
45-
* `false_successor` dominates `uncontrolled`, but not all of its predecessors are `this` (`if (x)`)
46-
* or dominated by itself. Whereas in the following code:
47-
* ```
48-
* if (x)
49-
* while (controlled)
50-
* also_controlled;
51-
* false_successor;
52-
* uncontrolled;
53-
* ```
54-
* the block `while controlled` is controlled because all of its predecessors are `this` (`if (x)`)
55-
* or (in the case of `also_controlled`) dominated by itself.
56-
*
57-
* The additional constraint on the predecessors of the test successor implies
58-
* that `this` strictly dominates `controlled` so that isn't necessary to check
59-
* directly.
60-
*/
61-
6262
exists(BasicBlock succ |
6363
succ = this.getTestSuccessor(testIsTrue) and
64-
succ.bbDominates(controlled) and
65-
forall(BasicBlock pred | pred = succ.getABBPredecessor() and pred != this |
66-
succ.bbDominates(pred)
67-
)
64+
dominatingEdge(this, succ) and
65+
succ.bbDominates(controlled)
6866
)
6967
}
7068
}
@@ -183,10 +181,8 @@ private predicate preconditionBranchEdge(
183181
private predicate preconditionControls(MethodAccess ma, BasicBlock controlled, boolean branch) {
184182
exists(BasicBlock check, BasicBlock succ |
185183
preconditionBranchEdge(ma, check, succ, branch) and
186-
succ.bbDominates(controlled) and
187-
forall(BasicBlock pred | pred = succ.getABBPredecessor() and pred != check |
188-
succ.bbDominates(pred)
189-
)
184+
dominatingEdge(check, succ) and
185+
succ.bbDominates(controlled)
190186
)
191187
}
192188

0 commit comments

Comments
 (0)