Skip to content

Commit 06d5a7f

Browse files
authored
Merge pull request github#13139 from MathiasVP/faster-product-flow
C++: Speedup product dataflow
2 parents 13a989b + e1cc7dc commit 06d5a7f

File tree

1 file changed

+84
-18
lines changed

1 file changed

+84
-18
lines changed

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

Lines changed: 84 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -324,25 +324,88 @@ module ProductFlow {
324324

325325
private module Flow2 = DataFlow::GlobalWithState<Config2>;
326326

327+
private predicate isSourcePair(Flow1::PathNode node1, Flow2::PathNode node2) {
328+
Config::isSourcePair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState())
329+
}
330+
331+
private predicate isSinkPair(Flow1::PathNode node1, Flow2::PathNode node2) {
332+
Config::isSinkPair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState())
333+
}
334+
335+
pragma[assume_small_delta]
327336
pragma[nomagic]
328-
private predicate reachableInterprocEntry(
329-
Flow1::PathNode source1, Flow2::PathNode source2, Flow1::PathNode node1, Flow2::PathNode node2
337+
private predicate fwdReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
338+
isSourcePair(node1, node2)
339+
or
340+
fwdIsSuccessor(_, _, node1, node2)
341+
}
342+
343+
pragma[nomagic]
344+
private predicate fwdIsSuccessorExit(
345+
Flow1::PathNode mid1, Flow2::PathNode mid2, Flow1::PathNode succ1, Flow2::PathNode succ2
330346
) {
331-
Config::isSourcePair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState()) and
332-
node1 = source1 and
333-
node2 = source2
347+
isSinkPair(mid1, mid2) and
348+
succ1 = mid1 and
349+
succ2 = mid2
334350
or
335-
exists(
336-
Flow1::PathNode midEntry1, Flow2::PathNode midEntry2, Flow1::PathNode midExit1,
337-
Flow2::PathNode midExit2
338-
|
339-
reachableInterprocEntry(source1, source2, midEntry1, midEntry2) and
340-
interprocEdgePair(midExit1, midExit2, node1, node2) and
341-
localPathStep1*(midEntry1, midExit1) and
342-
localPathStep2*(midEntry2, midExit2)
351+
interprocEdgePair(mid1, mid2, succ1, succ2)
352+
}
353+
354+
private predicate fwdIsSuccessor1(
355+
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode mid1, Flow2::PathNode mid2,
356+
Flow1::PathNode succ1, Flow2::PathNode succ2
357+
) {
358+
fwdReachableInterprocEntry(pred1, pred2) and
359+
localPathStep1*(pred1, mid1) and
360+
fwdIsSuccessorExit(pragma[only_bind_into](mid1), pragma[only_bind_into](mid2), succ1, succ2)
361+
}
362+
363+
private predicate fwdIsSuccessor2(
364+
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode mid1, Flow2::PathNode mid2,
365+
Flow1::PathNode succ1, Flow2::PathNode succ2
366+
) {
367+
fwdReachableInterprocEntry(pred1, pred2) and
368+
localPathStep2*(pred2, mid2) and
369+
fwdIsSuccessorExit(pragma[only_bind_into](mid1), pragma[only_bind_into](mid2), succ1, succ2)
370+
}
371+
372+
pragma[assume_small_delta]
373+
private predicate fwdIsSuccessor(
374+
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode succ1, Flow2::PathNode succ2
375+
) {
376+
exists(Flow1::PathNode mid1, Flow2::PathNode mid2 |
377+
fwdIsSuccessor1(pred1, pred2, mid1, mid2, succ1, succ2) and
378+
fwdIsSuccessor2(pred1, pred2, mid1, mid2, succ1, succ2)
379+
)
380+
}
381+
382+
pragma[assume_small_delta]
383+
pragma[nomagic]
384+
private predicate revReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
385+
fwdReachableInterprocEntry(node1, node2) and
386+
isSinkPair(node1, node2)
387+
or
388+
exists(Flow1::PathNode succ1, Flow2::PathNode succ2 |
389+
revReachableInterprocEntry(succ1, succ2) and
390+
fwdIsSuccessor(node1, node2, succ1, succ2)
343391
)
344392
}
345393

394+
private newtype TNodePair =
395+
TMkNodePair(Flow1::PathNode node1, Flow2::PathNode node2) {
396+
revReachableInterprocEntry(node1, node2)
397+
}
398+
399+
private predicate pathSucc(TNodePair n1, TNodePair n2) {
400+
exists(Flow1::PathNode n11, Flow2::PathNode n12, Flow1::PathNode n21, Flow2::PathNode n22 |
401+
n1 = TMkNodePair(n11, n12) and
402+
n2 = TMkNodePair(n21, n22) and
403+
fwdIsSuccessor(n11, n12, n21, n22)
404+
)
405+
}
406+
407+
private predicate pathSuccPlus(TNodePair n1, TNodePair n2) = fastTC(pathSucc/2)(n1, n2)
408+
346409
private predicate localPathStep1(Flow1::PathNode pred, Flow1::PathNode succ) {
347410
Flow1::PathGraph::edges(pred, succ) and
348411
pragma[only_bind_out](pred.getNode().getEnclosingCallable()) =
@@ -474,11 +537,14 @@ module ProductFlow {
474537
private predicate reachable(
475538
Flow1::PathNode source1, Flow2::PathNode source2, Flow1::PathNode sink1, Flow2::PathNode sink2
476539
) {
477-
exists(Flow1::PathNode mid1, Flow2::PathNode mid2 |
478-
reachableInterprocEntry(source1, source2, mid1, mid2) and
479-
Config::isSinkPair(sink1.getNode(), sink1.getState(), sink2.getNode(), sink2.getState()) and
480-
localPathStep1*(mid1, sink1) and
481-
localPathStep2*(mid2, sink2)
540+
isSourcePair(source1, source2) and
541+
isSinkPair(sink1, sink2) and
542+
exists(TNodePair n1, TNodePair n2 |
543+
n1 = TMkNodePair(source1, source2) and
544+
n2 = TMkNodePair(sink1, sink2)
545+
|
546+
pathSuccPlus(n1, n2) or
547+
n1 = n2
482548
)
483549
}
484550
}

0 commit comments

Comments
 (0)