Skip to content

Commit 0d1e061

Browse files
committed
C++: Implement 'getAdditionalFlowIntoCallNodeTerm'.
1 parent 6369006 commit 0d1e061

File tree

2 files changed

+89
-20
lines changed

2 files changed

+89
-20
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ private import DataFlowDispatch
55
private import DataFlowImplConsistency
66
private import semmle.code.cpp.ir.internal.IRCppLanguage
77
private import SsaInternals as Ssa
8+
private import DataFlowImplCommon
9+
private import semmle.code.cpp.ir.ValueNumbering
810

911
cached
1012
private module Cached {
@@ -890,11 +892,81 @@ private class MyConsistencyConfiguration extends Consistency::ConsistencyConfigu
890892
}
891893
}
892894

895+
/**
896+
* Gets the basic block of `node`.
897+
*/
898+
IRBlock getBasicBlock(Node node) {
899+
node.asInstruction().getBlock() = result
900+
or
901+
node.asOperand().getUse().getBlock() = result
902+
or
903+
node.(SsaPhiNode).getPhiNode().getBasicBlock() = result
904+
or
905+
node.(RawIndirectOperand).getOperand().getUse().getBlock() = result
906+
or
907+
node.(RawIndirectInstruction).getInstruction().getBlock() = result
908+
or
909+
result = getBasicBlock(node.(PostUpdateNode).getPreUpdateNode())
910+
}
911+
893912
/**
894913
* Gets an additional term that is added to the `join` and `branch` computations to reflect
895914
* an additional forward or backwards branching factor that is not taken into account
896915
* when calculating the (virtual) dispatch cost.
897916
*
898917
* Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter.
899918
*/
900-
int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() }
919+
pragma[nomagic]
920+
int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) {
921+
exists(ParameterNode switchee, ConditionOperand op, DataFlowCall call |
922+
viableParamArg(call, p, arg) and
923+
viableParamArg(call, switchee, _) and
924+
valueNumber(switchee.asInstruction()).getAUse() = op and
925+
result = countNumberOfBranchesUsingParameter(op, p)
926+
)
927+
}
928+
929+
/** Gets the `IRVariable` associated with the parameter node `p`. */
930+
pragma[nomagic]
931+
private IRVariable getIRVariableForParameterNode(ParameterNode p) {
932+
result = p.(DirectParameterNode).getIRVariable()
933+
or
934+
result.getAst() = p.(IndirectParameterNode).getParameter()
935+
}
936+
937+
/** Holds if `v` is the source variable corresponding to the parameter represented by `p`. */
938+
pragma[nomagic]
939+
private predicate parameterNodeHasSourceVariable(ParameterNode p, Ssa::SourceIRVariable v) {
940+
v.getIRVariable() = getIRVariableForParameterNode(p) and
941+
exists(Position pos | p.isParameterOf(_, pos) |
942+
pos instanceof DirectPosition and
943+
v.getIndirection() = 1
944+
or
945+
pos.(IndirectionPosition).getIndirectionIndex() + 1 = v.getIndirection()
946+
)
947+
}
948+
949+
private EdgeKind caseOrDefaultEdge() {
950+
result instanceof CaseEdge or
951+
result instanceof DefaultEdge
952+
}
953+
954+
/**
955+
* Gets the number of switch branches that that read from (or write to) the parameter `p`.
956+
*/
957+
int countNumberOfBranchesUsingParameter(ConditionOperand op, ParameterNode p) {
958+
exists(SwitchInstruction switch, Ssa::SourceVariable sv |
959+
switch.getExpressionOperand() = op and
960+
parameterNodeHasSourceVariable(p, sv) and
961+
// Count the number of cases that use the parameter. We do this by finding the phi node
962+
// that merges the uses/defs of the parameter. There might be multiple such phi nodes, so
963+
// we pick the one with the highest edge count.
964+
result =
965+
max(SsaPhiNode phi |
966+
switch.getSuccessor(caseOrDefaultEdge()).getBlock().dominanceFrontier() = getBasicBlock(phi) and
967+
phi.getSourceVariable() = sv
968+
|
969+
strictcount(phi.getAnInput())
970+
)
971+
)
972+
}

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,9 @@ class SsaPhiNode extends Node, TSsaPhiNode {
525525

526526
/** Gets a node that is used as input to this phi node. */
527527
final Node getAnInput() { result = this.getAnInput(_) }
528+
529+
/** Gets the source variable underlying this phi node. */
530+
Ssa::SourceVariable getSourceVariable() { result = phi.getSourceVariable() }
528531
}
529532

530533
/**
@@ -1201,10 +1204,20 @@ class ParameterNode extends Node {
12011204
predicate isParameterOf(Function f, ParameterPosition pos) { none() } // overridden by subclasses
12021205
}
12031206

1204-
/** An explicit positional parameter, not including `this` or `...`. */
1205-
private class ExplicitParameterNode extends ParameterNode, InstructionNode {
1207+
/** An explicit positional parameter, including `this`, but not `...`. */
1208+
class DirectParameterNode extends InstructionNode {
12061209
override InitializeParameterInstruction instr;
12071210

1211+
/**
1212+
* INTERNAL: Do not use.
1213+
*
1214+
* Gets the `IRVariable` that this parameter references.
1215+
*/
1216+
IRVariable getIRVariable() { result = instr.getIRVariable() }
1217+
}
1218+
1219+
/** An explicit positional parameter, not including `this` or `...`. */
1220+
private class ExplicitParameterNode extends ParameterNode, DirectParameterNode {
12081221
ExplicitParameterNode() { exists(instr.getParameter()) }
12091222

12101223
override predicate isParameterOf(Function f, ParameterPosition pos) {
@@ -1218,9 +1231,7 @@ private class ExplicitParameterNode extends ParameterNode, InstructionNode {
12181231
}
12191232

12201233
/** An implicit `this` parameter. */
1221-
class ThisParameterNode extends ParameterNode, InstructionNode {
1222-
override InitializeParameterInstruction instr;
1223-
1234+
class ThisParameterNode extends ParameterNode, DirectParameterNode {
12241235
ThisParameterNode() { instr.getIRVariable() instanceof IRThisVariable }
12251236

12261237
override predicate isParameterOf(Function f, ParameterPosition pos) {
@@ -1773,20 +1784,6 @@ class ContentSet instanceof Content {
17731784
}
17741785
}
17751786

1776-
private IRBlock getBasicBlock(Node node) {
1777-
node.asInstruction().getBlock() = result
1778-
or
1779-
node.asOperand().getUse().getBlock() = result
1780-
or
1781-
node.(SsaPhiNode).getPhiNode().getBasicBlock() = result
1782-
or
1783-
node.(RawIndirectOperand).getOperand().getUse().getBlock() = result
1784-
or
1785-
node.(RawIndirectInstruction).getInstruction().getBlock() = result
1786-
or
1787-
result = getBasicBlock(node.(PostUpdateNode).getPreUpdateNode())
1788-
}
1789-
17901787
/**
17911788
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
17921789
*

0 commit comments

Comments
 (0)