Skip to content

Commit 06bc460

Browse files
authored
Merge pull request github#13528 from rdmarsh2/rdmarsh2/cpp/range-analysis-back-edge
C++: fix range analysis back edge detection for irreducible CFGs
2 parents a17c812 + dcb3494 commit 06bc460

File tree

2 files changed

+45
-0
lines changed
  • cpp/ql

2 files changed

+45
-0
lines changed

cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticSSA.qll

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,27 @@ predicate semBackEdge(SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionP
7070
// Conservatively assume that every edge is a back edge if we don't have dominance information.
7171
(
7272
phi.getBasicBlock().bbDominates(edge.getOrigBlock()) or
73+
irreducibleSccEdge(phi.getBasicBlock(), edge.getOrigBlock()) or
7374
not edge.getOrigBlock().hasDominanceInformation()
7475
)
7576
}
77+
78+
/**
79+
* Holds if the edge from b1 to b2 is part of a multiple-entry cycle in an irreducible control flow
80+
* graph.
81+
*
82+
* An ireducible control flow graph is one where the usual dominance-based back edge detection does
83+
* not work, because there is a cycle with multiple entry points, meaning there are
84+
* mutually-reachable basic blocks where neither dominates the other. For such a graph, we first
85+
* remove all detectable back-edges using the normal condition that the predecessor block is
86+
* dominated by the successor block, then mark all edges in a cycle in the resulting graph as back
87+
* edges.
88+
*/
89+
private predicate irreducibleSccEdge(SemBasicBlock b1, SemBasicBlock b2) {
90+
trimmedEdge(b1, b2) and trimmedEdge+(b2, b1)
91+
}
92+
93+
private predicate trimmedEdge(SemBasicBlock pred, SemBasicBlock succ) {
94+
pred.getASuccessor() = succ and
95+
not succ.bbDominates(pred)
96+
}

cpp/ql/test/library-tests/ir/range-analysis/test.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,27 @@ int f4(int x) {
7070
}
7171
}
7272
}
73+
74+
// No interesting ranges to check here - this irreducible CFG caused an infinite loop due to back edge detection
75+
void gotoLoop(bool b1, bool b2)
76+
{
77+
int j;
78+
79+
if (b1)
80+
return;
81+
82+
if (!b2)
83+
{
84+
for (j = 0; j < 10; ++j)
85+
{
86+
goto main_decode_loop;
87+
}
88+
}
89+
else
90+
{
91+
for (j = 0; j < 10; ++j)
92+
{
93+
main_decode_loop:
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)