Skip to content

Commit b1de54e

Browse files
committed
C++: rewrite ProductFlow recursion for performance
1 parent 56eacce commit b1de54e

File tree

1 file changed

+41
-41
lines changed

1 file changed

+41
-41
lines changed

cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ module ProductFlow {
2424
DataFlow::PathNode source1, DataFlow2::PathNode source2, DataFlow::PathNode sink1,
2525
DataFlow2::PathNode sink2
2626
) {
27-
isSinkPair(sink1.getNode(), sink2.getNode()) and
28-
reachablePair2(this, source1, source2, sink1, sink2)
27+
reachable(this, source1, source2, sink1, sink2)
2928
}
3029
}
3130

@@ -62,58 +61,59 @@ module ProductFlow {
6261
}
6362
}
6463

65-
private predicate reachablePair1(
64+
65+
private predicate reachableInterprocEntry(
6666
Configuration conf, DataFlow::PathNode source1, DataFlow2::PathNode source2,
6767
DataFlow::PathNode node1, DataFlow2::PathNode node2
6868
) {
69-
reachablePair(conf, source1, source2, node1, node2)
69+
conf.isSourcePair(node1.getNode(), node2.getNode()) and
70+
node1 = source1 and
71+
node2 = source2
7072
or
71-
exists(DataFlow::PathNode mid1 |
72-
reachablePair1(conf, source1, source2, mid1, node2) and
73-
mid1.getASuccessor() = node1 and
74-
mid1.getNode().getEnclosingCallable() = node1.getNode().getEnclosingCallable()
73+
exists(
74+
DataFlow::PathNode midEntry1, DataFlow2::PathNode midEntry2, DataFlow::PathNode midExit1,
75+
DataFlow2::PathNode midExit2
76+
|
77+
reachableInterprocEntry(conf, source1, source2, midEntry1, midEntry2) and
78+
interprocEdgePair(midExit1, midExit2, node1, node2) and
79+
localPathStep1*(midEntry1, midExit1) and
80+
localPathStep2*(midEntry2, midExit2)
7581
)
7682
}
7783

78-
private predicate reachablePair2(
79-
Configuration conf, DataFlow::PathNode source1, DataFlow2::PathNode source2,
80-
DataFlow::PathNode node1, DataFlow2::PathNode node2
81-
) {
82-
reachablePair1(conf, source1, source2, node1, node2) // TODO: restrict more
83-
or
84-
exists(DataFlow2::PathNode mid2 |
85-
reachablePair2(conf, source1, source2, node1, mid2) and
86-
mid2.getASuccessor() = node2 and
87-
mid2.getNode().getEnclosingCallable() = node2.getNode().getEnclosingCallable()
88-
)
84+
private predicate localPathStep1(DataFlow::PathNode pred, DataFlow::PathNode succ) {
85+
DataFlow::PathGraph::edges(pred, succ) and
86+
pred.getNode().getEnclosingCallable() = succ.getNode().getEnclosingCallable()
8987
}
9088

91-
private predicate interprocStep(
92-
Configuration conf, DataFlow::PathNode source1, DataFlow2::PathNode source2,
93-
DataFlow::PathNode node1, DataFlow2::PathNode node2
89+
private predicate localPathStep2(DataFlow2::PathNode pred, DataFlow2::PathNode succ) {
90+
DataFlow2::PathGraph::edges(pred, succ) and
91+
pred.getNode().getEnclosingCallable() = succ.getNode().getEnclosingCallable()
92+
}
93+
94+
private predicate interprocEdgePair(
95+
DataFlow::PathNode pred1, DataFlow2::PathNode pred2, DataFlow::PathNode succ1,
96+
DataFlow2::PathNode succ2
9497
) {
95-
exists(DataFlow::PathNode mid1, DataFlow2::PathNode mid2, Function funcMid, Function func |
96-
reachablePair2(conf, source1, source2, mid1, mid2) and
97-
mid1.getASuccessor() = node1 and
98-
mid2.getASuccessor() = node2 and
99-
mid1.getNode().getEnclosingCallable() = funcMid and // TODO: recursive function weirdness?
100-
mid2.getNode().getEnclosingCallable() = funcMid and
101-
node1.getNode().getEnclosingCallable() = func and
102-
node2.getNode().getEnclosingCallable() = func and
103-
funcMid != func
98+
exists(Declaration predDecl, Declaration succDecl |
99+
DataFlow::PathGraph::edges(pred1, succ1) and
100+
DataFlow2::PathGraph::edges(pred2, succ2) and
101+
predDecl != succDecl and
102+
pred1.getNode().getEnclosingCallable() = predDecl and
103+
pred2.getNode().getEnclosingCallable() = predDecl and
104+
succ1.getNode().getEnclosingCallable() = succDecl and
105+
succ2.getNode().getEnclosingCallable() = succDecl
104106
)
105107
}
106108

107-
private predicate reachablePair(
108-
Configuration conf, DataFlow::PathNode source1, DataFlow2::PathNode source2,
109-
DataFlow::PathNode node1, DataFlow2::PathNode node2
109+
private predicate reachable(
110+
Configuration conf, DataFlow::PathNode source1, DataFlow2::PathNode source2, DataFlow::PathNode sink1, DataFlow2::PathNode sink2
110111
) {
111-
conf.isSourcePair(node1.getNode(), node2.getNode()) and
112-
node1.isSource() and
113-
node2.isSource() and
114-
source1 = node1 and
115-
source2 = node2
116-
or
117-
interprocStep(conf, source1, source2, node1, node2)
112+
exists(DataFlow::PathNode mid1, DataFlow2::PathNode mid2 |
113+
reachableInterprocEntry(conf, source1, source2, mid1, mid2) and
114+
conf.isSinkPair(sink1.getNode(), sink2.getNode()) and
115+
localPathStep1*(mid1, sink1) and
116+
localPathStep2*(mid2, sink2)
117+
)
118118
}
119119
}

0 commit comments

Comments
 (0)