Skip to content

Commit b2e5d23

Browse files
committed
C++: IR sanity queries for outgoing edges
These queries have no results on our test cases in the repo, but `ambiguousSuccessors` has results on any large C++ code base, and `unexplainedLoop` has results on Windows builds of ChakraCore.
1 parent aba73f4 commit b2e5d23

File tree

6 files changed

+84
-0
lines changed

6 files changed

+84
-0
lines changed

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,32 @@ module InstructionSanity {
106106
not instr instanceof UnreachedInstruction
107107
}
108108

109+
/**
110+
* Holds if there are multiple (`n`) edges of kind `kind` from `source`,
111+
* where `target` is among the targets of those edges.
112+
*/
113+
query predicate ambiguousSuccessors(
114+
Instruction source, EdgeKind kind, int n, Instruction target
115+
) {
116+
n = strictcount(Instruction t | source.getSuccessor(kind) = t) and
117+
n > 1 and
118+
source.getSuccessor(kind) = target
119+
}
120+
121+
/**
122+
* Holds if `instr` in `f` is part of a loop even though the AST of `f`
123+
* contains no element that can cause loops.
124+
*/
125+
query predicate unexplainedLoop(Function f, Instruction instr) {
126+
exists(IRBlock block |
127+
instr.getBlock() = block and
128+
block.getFunction() = f and
129+
block.getASuccessor+() = block
130+
) and
131+
not exists(Loop l | l.getEnclosingFunction() = f) and
132+
not exists(GotoStmt s | s.getEnclosingFunction() = f)
133+
}
134+
109135
/**
110136
* Holds if a `Phi` instruction is present in a block with fewer than two
111137
* predecessors.

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,32 @@ module InstructionSanity {
106106
not instr instanceof UnreachedInstruction
107107
}
108108

109+
/**
110+
* Holds if there are multiple (`n`) edges of kind `kind` from `source`,
111+
* where `target` is among the targets of those edges.
112+
*/
113+
query predicate ambiguousSuccessors(
114+
Instruction source, EdgeKind kind, int n, Instruction target
115+
) {
116+
n = strictcount(Instruction t | source.getSuccessor(kind) = t) and
117+
n > 1 and
118+
source.getSuccessor(kind) = target
119+
}
120+
121+
/**
122+
* Holds if `instr` in `f` is part of a loop even though the AST of `f`
123+
* contains no element that can cause loops.
124+
*/
125+
query predicate unexplainedLoop(Function f, Instruction instr) {
126+
exists(IRBlock block |
127+
instr.getBlock() = block and
128+
block.getFunction() = f and
129+
block.getASuccessor+() = block
130+
) and
131+
not exists(Loop l | l.getEnclosingFunction() = f) and
132+
not exists(GotoStmt s | s.getEnclosingFunction() = f)
133+
}
134+
109135
/**
110136
* Holds if a `Phi` instruction is present in a block with fewer than two
111137
* predecessors.

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,32 @@ module InstructionSanity {
106106
not instr instanceof UnreachedInstruction
107107
}
108108

109+
/**
110+
* Holds if there are multiple (`n`) edges of kind `kind` from `source`,
111+
* where `target` is among the targets of those edges.
112+
*/
113+
query predicate ambiguousSuccessors(
114+
Instruction source, EdgeKind kind, int n, Instruction target
115+
) {
116+
n = strictcount(Instruction t | source.getSuccessor(kind) = t) and
117+
n > 1 and
118+
source.getSuccessor(kind) = target
119+
}
120+
121+
/**
122+
* Holds if `instr` in `f` is part of a loop even though the AST of `f`
123+
* contains no element that can cause loops.
124+
*/
125+
query predicate unexplainedLoop(Function f, Instruction instr) {
126+
exists(IRBlock block |
127+
instr.getBlock() = block and
128+
block.getFunction() = f and
129+
block.getASuccessor+() = block
130+
) and
131+
not exists(Loop l | l.getEnclosingFunction() = f) and
132+
not exists(GotoStmt s | s.getEnclosingFunction() = f)
133+
}
134+
109135
/**
110136
* Holds if a `Phi` instruction is present in a block with fewer than two
111137
* predecessors.

cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ unexpectedOperand
33
duplicateOperand
44
missingPhiOperand
55
instructionWithoutSuccessor
6+
ambiguousSuccessors
7+
unexplainedLoop
68
unnecessaryPhiInstruction
79
operandAcrossFunctions
810
instructionWithoutUniqueBlock

cpp/ql/test/library-tests/ir/ir/raw_sanity.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ unexpectedOperand
33
duplicateOperand
44
missingPhiOperand
55
instructionWithoutSuccessor
6+
ambiguousSuccessors
7+
unexplainedLoop
68
unnecessaryPhiInstruction
79
operandAcrossFunctions
810
instructionWithoutUniqueBlock

cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ unexpectedOperand
33
duplicateOperand
44
missingPhiOperand
55
instructionWithoutSuccessor
6+
ambiguousSuccessors
7+
unexplainedLoop
68
unnecessaryPhiInstruction
79
operandAcrossFunctions
810
instructionWithoutUniqueBlock

0 commit comments

Comments
 (0)