Skip to content

Commit 7992678

Browse files
committed
C++: Fix non-monotonic recursion problems in 'StackVariableReachabilityWithReassignment' by using the old StackVariableReachability predicates that don't care about paths.
1 parent c32f720 commit 7992678

File tree

1 file changed

+45
-3
lines changed

1 file changed

+45
-3
lines changed

cpp/ql/src/semmle/code/cpp/controlflow/StackVariableReachability.qll

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -636,10 +636,52 @@ abstract class StackVariableReachabilityWithReassignment extends StackVariableRe
636636
)
637637
}
638638

639+
private predicate bbSuccessorEntryReaches(
640+
BasicBlock bb, SemanticStackVariable v, ControlFlowNode node,
641+
boolean skipsFirstLoopAlwaysTrueUponEntry
642+
) {
643+
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
644+
bbSuccessorEntryReachesLoopInvariant0(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
645+
succSkipsFirstLoopAlwaysTrueUponEntry)
646+
|
647+
revBbEntryReachesLocally(succ, v, node, this) and
648+
succSkipsFirstLoopAlwaysTrueUponEntry = false
649+
or
650+
not isBarrier(succ.getNode(_), v) and
651+
bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
652+
)
653+
}
654+
655+
private predicate reaches0(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
656+
/*
657+
* Implementation detail: the predicates in this class are a generalization of
658+
* those in DefinitionsAndUses.qll, and should be kept in sync.
659+
*
660+
* Unfortunately, caching of abstract predicates does not work well, so the
661+
* predicates in DefinitionsAndUses.qll cannot use this library.
662+
*/
663+
664+
exists(BasicBlock bb, int i |
665+
isSource(source, v) and
666+
bb.getNode(i) = source and
667+
not bb.isUnreachable()
668+
|
669+
exists(int j |
670+
j > i and
671+
sink = bb.getNode(j) and
672+
isSink(sink, v) and
673+
not isBarrier(bb.getNode(pragma[only_bind_into]([i + 1 .. j - 1])), v)
674+
)
675+
or
676+
not exists(int k | isBarrier(bb.getNode(k), v) | k > i) and
677+
bbSuccessorEntryReaches(bb, v, sink, _)
678+
)
679+
}
680+
639681
private predicate reassignment(
640682
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0
641683
) {
642-
StackVariableReachability.super.reaches(source, v, def) and
684+
reaches0(source, v, def) and
643685
exprDefinition(v0, def, v.getAnAccess())
644686
}
645687

@@ -705,11 +747,11 @@ abstract class StackVariableReachabilityExt extends string {
705747
boolean skipsFirstLoopAlwaysTrueUponEntry
706748
) {
707749
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
708-
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
750+
bbSuccessorEntryReachesLoopInvariant0(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
709751
succSkipsFirstLoopAlwaysTrueUponEntry) and
710752
not isBarrier(source, bb.getEnd(), succ.getStart(), v)
711753
|
712-
bbEntryReachesLocally(source, succ, v, node) and
754+
this.bbEntryReachesLocally(source, succ, v, node) and
713755
succSkipsFirstLoopAlwaysTrueUponEntry = false
714756
or
715757
not exists(int k | isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and

0 commit comments

Comments
 (0)