Skip to content

Commit ad21050

Browse files
committed
Shared: address review comments.
1 parent dcb8ea2 commit ad21050

File tree

1 file changed

+33
-8
lines changed

1 file changed

+33
-8
lines changed

shared/controlflow/codeql/controlflow/Guards.qll

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* controls the basic block `A`, in this case because the true branch dominates
1212
* `A`, but more elaborate controls-relationships may also hold.
1313
* For example, in
14-
* ```
14+
* ```java
1515
* int sz = a != null ? a.length : 0;
1616
* if (sz != 0) {
1717
* // this block is controlled by:
@@ -104,6 +104,19 @@ signature module InputSig<LocationSig Location> {
104104
predicate strictlyDominates(BasicBlock bb);
105105
}
106106

107+
/**
108+
* Holds if `bb1` has `bb2` as a direct successor and the edge between `bb1`
109+
* and `bb2` is a dominating edge.
110+
*
111+
* An edge `(bb1, bb2)` is dominating if there exists a basic block that can
112+
* only be reached from the entry block by going through `(bb1, bb2)`. This
113+
* implies that `(bb1, bb2)` dominates its endpoint `bb2`. I.e., `bb2` can
114+
* only be reached from the entry block by going via `(bb1, bb2)`.
115+
*
116+
* This is a necessary and sufficient condition for an edge to dominate some
117+
* block, and therefore `dominatingEdge(bb1, bb2) and bb2.dominates(bb3)`
118+
* means that the edge `(bb1, bb2)` dominates `bb3`.
119+
*/
107120
predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2);
108121

109122
class AstNode {
@@ -528,6 +541,17 @@ module Make<LocationSig Location, InputSig<Location> Input> {
528541
module Logic<LogicInputSig LogicInput> {
529542
private import LogicInput
530543

544+
/**
545+
* Holds if `guard` evaluating to `v` directly controls `phi` taking the value
546+
* `inp`. This means that `guard` evaluating to `v` must control all the input
547+
* edges to `phi` that read `inp`.
548+
*
549+
* We also require that `guard` dominates `phi` in order to allow logical inferences
550+
* from the value of `phi` to the value of `guard`.
551+
*
552+
* Trivial cases where `guard` controls `phi` itself are excluded, since that makes
553+
* logical inferences from `phi` to `guard` trivial and irrelevant.
554+
*/
531555
private predicate guardControlsPhiBranch(
532556
Guard guard, GuardValue v, SsaPhiNode phi, SsaDefinition inp
533557
) {
@@ -571,6 +595,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
571595
private predicate guardReadsSsaVar(Guard guard, SsaDefinition def) {
572596
def.getARead() = guard
573597
or
598+
// A read of `y` can be considered as a read of `x` if guarded by `x == y`.
574599
exists(Guard eqtest, SsaDefinition other, boolean branch |
575600
guardChecksEqualVars(eqtest, def, other, branch) and
576601
other.getARead() = guard and
@@ -602,21 +627,21 @@ module Make<LocationSig Location, InputSig<Location> Input> {
602627
* boolean `fromBackEdge` indicates whether the flow from `result` to `v` goes
603628
* through a back edge.
604629
*/
605-
private SsaDefinition getADefinition(SsaDefinition v, boolean fromBackEdge) {
630+
private SsaDefinition getAnUltimateDefinition(SsaDefinition v, boolean fromBackEdge) {
606631
result = v and not v instanceof SsaPhiNode and fromBackEdge = false
607632
or
608633
exists(SsaDefinition inp, BasicBlock bb, boolean fbe |
609634
v.(SsaPhiNode).hasInputFromBlock(inp, bb) and
610-
result = getADefinition(inp, fbe) and
635+
result = getAnUltimateDefinition(inp, fbe) and
611636
(if v.getBasicBlock().dominates(bb) then fromBackEdge = true else fromBackEdge = fbe)
612637
)
613638
}
614639

615640
/**
616-
* Holds if `v` can have a value that is not representable as an `GuardValue`.
641+
* Holds if `v` can have a value that is not representable as a `GuardValue`.
617642
*/
618643
private predicate hasPossibleUnknownValue(SsaDefinition v) {
619-
exists(SsaDefinition def | def = getADefinition(v, _) |
644+
exists(SsaDefinition def | def = getAnUltimateDefinition(v, _) |
620645
not exists(def.(SsaWriteDefinition).getDefinition())
621646
or
622647
exists(Expr e | e = possibleValue(def.(SsaWriteDefinition).getDefinition()) |
@@ -633,7 +658,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
633658
private predicate possibleValue(SsaDefinition v, boolean fromBackEdge, Expr e, GuardValue k) {
634659
not hasPossibleUnknownValue(v) and
635660
exists(SsaWriteDefinition def |
636-
def = getADefinition(v, fromBackEdge) and
661+
def = getAnUltimateDefinition(v, fromBackEdge) and
637662
e = possibleValue(def.getDefinition()) and
638663
constantHasValue(e, k)
639664
)
@@ -676,7 +701,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
676701
or
677702
exists(SsaDefinition def |
678703
guardReadsSsaVar(e, def) and
679-
relevantInt(getADefinition(def, _).(SsaWriteDefinition).getDefinition(), k)
704+
relevantInt(getAnUltimateDefinition(def, _).(SsaWriteDefinition).getDefinition(), k)
680705
)
681706
}
682707

@@ -808,7 +833,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
808833
* starting from a given set of base cases.
809834
*/
810835
cached
811-
module ImpliesTC<baseGuardValueSig/2 baseGuardValue> {
836+
private module ImpliesTC<baseGuardValueSig/2 baseGuardValue> {
812837
/**
813838
* Holds if `tgtGuard` evaluating to `tgtVal` implies that `guard`
814839
* evaluates to `v`.

0 commit comments

Comments
 (0)