Merge pull request #12429 from MathiasVP/actually-implement-language-specific-flow-into-call-node-cand1

C++: Implement `getAdditionalFlowIntoCallNodeTerm`
This commit is contained in:
Mathias Vorreiter Pedersen
2023-03-08 11:58:56 +00:00
committed by GitHub
2 changed files with 89 additions and 20 deletions

View File

@@ -5,6 +5,8 @@ private import DataFlowDispatch
private import DataFlowImplConsistency private import DataFlowImplConsistency
private import semmle.code.cpp.ir.internal.IRCppLanguage private import semmle.code.cpp.ir.internal.IRCppLanguage
private import SsaInternals as Ssa private import SsaInternals as Ssa
private import DataFlowImplCommon
private import semmle.code.cpp.ir.ValueNumbering
cached cached
private module Cached { private module Cached {
@@ -890,6 +892,23 @@ private class MyConsistencyConfiguration extends Consistency::ConsistencyConfigu
} }
} }
/**
* Gets the basic block of `node`.
*/
IRBlock getBasicBlock(Node node) {
node.asInstruction().getBlock() = result
or
node.asOperand().getUse().getBlock() = result
or
node.(SsaPhiNode).getPhiNode().getBasicBlock() = result
or
node.(RawIndirectOperand).getOperand().getUse().getBlock() = result
or
node.(RawIndirectInstruction).getInstruction().getBlock() = result
or
result = getBasicBlock(node.(PostUpdateNode).getPreUpdateNode())
}
/** /**
* Gets an additional term that is added to the `join` and `branch` computations to reflect * Gets an additional term that is added to the `join` and `branch` computations to reflect
* an additional forward or backwards branching factor that is not taken into account * an additional forward or backwards branching factor that is not taken into account
@@ -897,4 +916,57 @@ private class MyConsistencyConfiguration extends Consistency::ConsistencyConfigu
* *
* Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter. * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter.
*/ */
int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() } pragma[nomagic]
int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) {
exists(ParameterNode switchee, SwitchInstruction switch, ConditionOperand op, DataFlowCall call |
viableParamArg(call, p, arg) and
viableParamArg(call, switchee, _) and
switch.getExpressionOperand() = op and
valueNumber(switchee.asInstruction()).getAUse() = op and
result = countNumberOfBranchesUsingParameter(switch, p)
)
}
/** Gets the `IRVariable` associated with the parameter node `p`. */
pragma[nomagic]
private IRVariable getIRVariableForParameterNode(ParameterNode p) {
result = p.(DirectParameterNode).getIRVariable()
or
result.getAst() = p.(IndirectParameterNode).getParameter()
}
/** Holds if `v` is the source variable corresponding to the parameter represented by `p`. */
pragma[nomagic]
private predicate parameterNodeHasSourceVariable(ParameterNode p, Ssa::SourceIRVariable v) {
v.getIRVariable() = getIRVariableForParameterNode(p) and
exists(Position pos | p.isParameterOf(_, pos) |
pos instanceof DirectPosition and
v.getIndirection() = 1
or
pos.(IndirectionPosition).getIndirectionIndex() + 1 = v.getIndirection()
)
}
private EdgeKind caseOrDefaultEdge() {
result instanceof CaseEdge or
result instanceof DefaultEdge
}
/**
* Gets the number of switch branches that that read from (or write to) the parameter `p`.
*/
int countNumberOfBranchesUsingParameter(SwitchInstruction switch, ParameterNode p) {
exists(Ssa::SourceVariable sv |
parameterNodeHasSourceVariable(p, sv) and
// Count the number of cases that use the parameter. We do this by finding the phi node
// that merges the uses/defs of the parameter. There might be multiple such phi nodes, so
// we pick the one with the highest edge count.
result =
max(SsaPhiNode phi |
switch.getSuccessor(caseOrDefaultEdge()).getBlock().dominanceFrontier() = getBasicBlock(phi) and
phi.getSourceVariable() = sv
|
strictcount(phi.getAnInput())
)
)
}

View File

@@ -525,6 +525,9 @@ class SsaPhiNode extends Node, TSsaPhiNode {
/** Gets a node that is used as input to this phi node. */ /** Gets a node that is used as input to this phi node. */
final Node getAnInput() { result = this.getAnInput(_) } final Node getAnInput() { result = this.getAnInput(_) }
/** Gets the source variable underlying this phi node. */
Ssa::SourceVariable getSourceVariable() { result = phi.getSourceVariable() }
} }
/** /**
@@ -1202,10 +1205,20 @@ class ParameterNode extends Node {
predicate isParameterOf(Function f, ParameterPosition pos) { none() } // overridden by subclasses predicate isParameterOf(Function f, ParameterPosition pos) { none() } // overridden by subclasses
} }
/** An explicit positional parameter, not including `this` or `...`. */ /** An explicit positional parameter, including `this`, but not `...`. */
private class ExplicitParameterNode extends ParameterNode, InstructionNode { class DirectParameterNode extends InstructionNode {
override InitializeParameterInstruction instr; override InitializeParameterInstruction instr;
/**
* INTERNAL: Do not use.
*
* Gets the `IRVariable` that this parameter references.
*/
IRVariable getIRVariable() { result = instr.getIRVariable() }
}
/** An explicit positional parameter, not including `this` or `...`. */
private class ExplicitParameterNode extends ParameterNode, DirectParameterNode {
ExplicitParameterNode() { exists(instr.getParameter()) } ExplicitParameterNode() { exists(instr.getParameter()) }
override predicate isParameterOf(Function f, ParameterPosition pos) { override predicate isParameterOf(Function f, ParameterPosition pos) {
@@ -1219,9 +1232,7 @@ private class ExplicitParameterNode extends ParameterNode, InstructionNode {
} }
/** An implicit `this` parameter. */ /** An implicit `this` parameter. */
class ThisParameterNode extends ParameterNode, InstructionNode { class ThisParameterNode extends ParameterNode, DirectParameterNode {
override InitializeParameterInstruction instr;
ThisParameterNode() { instr.getIRVariable() instanceof IRThisVariable } ThisParameterNode() { instr.getIRVariable() instanceof IRThisVariable }
override predicate isParameterOf(Function f, ParameterPosition pos) { override predicate isParameterOf(Function f, ParameterPosition pos) {
@@ -1774,20 +1785,6 @@ class ContentSet instanceof Content {
} }
} }
private IRBlock getBasicBlock(Node node) {
node.asInstruction().getBlock() = result
or
node.asOperand().getUse().getBlock() = result
or
node.(SsaPhiNode).getPhiNode().getBasicBlock() = result
or
node.(RawIndirectOperand).getOperand().getUse().getBlock() = result
or
node.(RawIndirectInstruction).getInstruction().getBlock() = result
or
result = getBasicBlock(node.(PostUpdateNode).getPreUpdateNode())
}
/** /**
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`. * Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
* *