mirror of
https://github.com/github/codeql.git
synced 2026-04-24 00:05:14 +02:00
C++: Create a proper class for DataFlowCallable, that includes summarized callables.
This commit is contained in:
@@ -119,7 +119,10 @@ module SourceSinkInterpretationInput implements
|
||||
}
|
||||
|
||||
/** Gets the callable that this node corresponds to, if any. */
|
||||
DataFlowCallable asCallable() { result.(Function) = this.asElement() }
|
||||
DataFlowCallable asCallable() {
|
||||
result.asSourceCallable() = this.asElement()
|
||||
// TODO: or summary callable?
|
||||
}
|
||||
|
||||
/** Gets the target of this call, if any. */
|
||||
Element getCallTarget() { result = this.asCall().getStaticCallTarget() }
|
||||
|
||||
@@ -14,7 +14,7 @@ private import DataFlowImplCommon as DataFlowImplCommon
|
||||
cached
|
||||
DataFlowCallable defaultViableCallable(DataFlowCall call) {
|
||||
DataFlowImplCommon::forceCachingInSameStage() and
|
||||
result = call.getStaticCallTarget()
|
||||
result = TSourceCallable(call.getStaticCallTarget())
|
||||
or
|
||||
// If the target of the call does not have a body in the snapshot, it might
|
||||
// be because the target is just a header declaration, and the real target
|
||||
@@ -24,12 +24,12 @@ DataFlowCallable defaultViableCallable(DataFlowCall call) {
|
||||
// that as a potential callee.
|
||||
exists(string qualifiedName, int nparams |
|
||||
callSignatureWithoutBody(qualifiedName, nparams, call.asCallInstruction()) and
|
||||
functionSignatureWithBody(qualifiedName, nparams, result) and
|
||||
functionSignatureWithBody(qualifiedName, nparams, result.asSourceCallable()) and
|
||||
strictcount(Function other | functionSignatureWithBody(qualifiedName, nparams, other)) = 1
|
||||
)
|
||||
or
|
||||
// Virtual dispatch
|
||||
result = call.(VirtualDispatch::DataSensitiveCall).resolve()
|
||||
result = TSourceCallable(call.(VirtualDispatch::DataSensitiveCall).resolve())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,7 +89,7 @@ private module VirtualDispatch {
|
||||
// Call return
|
||||
exists(DataFlowCall call, ReturnKind returnKind |
|
||||
other = getAnOutNode(call, returnKind) and
|
||||
returnNodeWithKindAndEnclosingCallable(src, returnKind, call.getStaticCallTarget())
|
||||
returnNodeWithKindAndEnclosingCallable(src, returnKind, TSourceCallable(call.getStaticCallTarget()))
|
||||
) and
|
||||
allowFromArg = false
|
||||
or
|
||||
@@ -258,12 +258,12 @@ predicate mayBenefitFromCallContext(DataFlowCall call, DataFlowCallable f) {
|
||||
* value is given as the `arg`'th argument to `f`.
|
||||
*/
|
||||
private predicate mayBenefitFromCallContext(
|
||||
VirtualDispatch::DataSensitiveCall call, Function f, int arg
|
||||
VirtualDispatch::DataSensitiveCall call, DataFlowCallable f, int arg
|
||||
) {
|
||||
f = pragma[only_bind_out](call).getEnclosingCallable() and
|
||||
exists(InitializeParameterInstruction init |
|
||||
not exists(call.getStaticCallTarget()) and
|
||||
init.getEnclosingFunction() = f and
|
||||
init.getEnclosingFunction() = f.asSourceCallable() and
|
||||
call.flowsFrom(DataFlow::instructionNode(init), _) and
|
||||
init.getParameter().getIndex() = arg
|
||||
)
|
||||
@@ -275,10 +275,10 @@ private predicate mayBenefitFromCallContext(
|
||||
*/
|
||||
DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) {
|
||||
result = viableCallable(call) and
|
||||
exists(int i, Function f |
|
||||
exists(int i, DataFlowCallable f |
|
||||
mayBenefitFromCallContext(pragma[only_bind_into](call), f, i) and
|
||||
f = ctx.getStaticCallTarget() and
|
||||
result = ctx.getArgument(i).getUnconvertedResultExpression().(FunctionAccess).getTarget()
|
||||
f.asSourceCallable() = ctx.getStaticCallTarget() and
|
||||
result = TSourceCallable(ctx.getArgument(i).getUnconvertedResultExpression().(FunctionAccess).getTarget())
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ class Node0Impl extends TIRDataFlowNode0 {
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
Declaration getEnclosingCallable() { none() } // overridden in subclasses
|
||||
DataFlowCallable getEnclosingCallable() { none() } // overridden in subclasses
|
||||
|
||||
/** Gets the function to which this node belongs, if any. */
|
||||
Declaration getFunction() { none() } // overridden in subclasses
|
||||
@@ -174,7 +174,7 @@ abstract class InstructionNode0 extends Node0Impl {
|
||||
/** Gets the instruction corresponding to this node. */
|
||||
Instruction getInstruction() { result = instr }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
override DataFlowCallable getEnclosingCallable() { result = TSourceCallable(this.getFunction()) }
|
||||
|
||||
override Declaration getFunction() { result = instr.getEnclosingFunction() }
|
||||
|
||||
@@ -219,7 +219,7 @@ abstract class OperandNode0 extends Node0Impl {
|
||||
/** Gets the operand corresponding to this node. */
|
||||
Operand getOperand() { result = op }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
override DataFlowCallable getEnclosingCallable() { result = TSourceCallable(this.getFunction()) }
|
||||
|
||||
override Declaration getFunction() { result = op.getUse().getEnclosingFunction() }
|
||||
|
||||
@@ -340,7 +340,7 @@ DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCalla
|
||||
|
||||
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */
|
||||
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
|
||||
p.isParameterOf(c, pos)
|
||||
p.isParameterOf(c.asSourceCallable(), pos) // TODO: if c is a summary node?
|
||||
}
|
||||
|
||||
/** Holds if `arg` is an `ArgumentNode` of `c` with position `pos`. */
|
||||
@@ -941,13 +941,57 @@ class CastNode extends Node {
|
||||
CastNode() { none() } // stub implementation
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TDataFlowCallable =
|
||||
TSourceCallable(Cpp::Declaration decl) { not decl instanceof FlowSummaryImpl::Public::SummarizedCallable } or
|
||||
TSummarizedCallable(FlowSummaryImpl::Public::SummarizedCallable c)
|
||||
|
||||
/**
|
||||
* A function that may contain code or a variable that may contain itself. When
|
||||
* flow crosses from one _enclosing callable_ to another, the interprocedural
|
||||
* data-flow library discards call contexts and inserts a node in the big-step
|
||||
* relation used for human-readable path explanations.
|
||||
* A callable, which may be:
|
||||
* - a function (that may contain code)
|
||||
* - a summarized function (that may contain only `FlowSummaryNode`s)
|
||||
* - a variable (this is used as context for global initialization, and also
|
||||
* for the mid-point in interprocedural data flow between a write and read
|
||||
* of a global variable in different functions).
|
||||
* When flow crosses from one _enclosing callable_ to another, the
|
||||
* interprocedural data-flow library discards call contexts and inserts a node
|
||||
* in the big-step relation used for human-readable path explanations.
|
||||
*/
|
||||
class DataFlowCallable = Cpp::Declaration;
|
||||
class DataFlowCallable extends TDataFlowCallable {
|
||||
/** Gets the location of this callable. */
|
||||
Location getLocation() { none() }
|
||||
|
||||
/** Gets a textual representation of this callable. */
|
||||
string toString() { none() }
|
||||
|
||||
Cpp::Declaration asSourceCallable() { this = TSourceCallable(result) }
|
||||
|
||||
FlowSummaryImpl::Public::SummarizedCallable asSummarizedCallable() { this = TSummarizedCallable(result) }
|
||||
|
||||
/* Callable::TypeRange getUnderlyingCallable() { TODO
|
||||
result = this.asSummarizedCallable() or result = this.asSourceCallable()
|
||||
}*/
|
||||
}
|
||||
|
||||
private class SourceCallable extends DataFlowCallable, TSourceCallable {
|
||||
Cpp::Declaration decl;
|
||||
|
||||
SourceCallable() { this = TSourceCallable(decl) }
|
||||
|
||||
override string toString() { result = decl.toString() }
|
||||
|
||||
override Location getLocation() { result = decl.getLocation() }
|
||||
}
|
||||
|
||||
private class SummarizedCallable extends DataFlowCallable, TSummarizedCallable {
|
||||
FlowSummaryImpl::Public::SummarizedCallable sc;
|
||||
|
||||
SummarizedCallable() { this = TSummarizedCallable(sc) }
|
||||
|
||||
override string toString() { result = sc.toString() }
|
||||
|
||||
override Location getLocation() { result = sc.getLocation() }
|
||||
}
|
||||
|
||||
class DataFlowExpr = Expr;
|
||||
|
||||
@@ -980,7 +1024,7 @@ class DataFlowCall extends TDataFlowCall {
|
||||
/**
|
||||
* Gets the `Function` that the call targets, if this is statically known.
|
||||
*/
|
||||
Function getStaticCallTarget() { none() }
|
||||
Function getStaticCallTarget() { none() } // TODO: should this return DataFlowCallable?
|
||||
|
||||
/**
|
||||
* Gets the `index`'th argument operand. The qualifier is considered to have index `-1`.
|
||||
@@ -1029,7 +1073,7 @@ private class NormalCall extends DataFlowCall, TNormalCall {
|
||||
result = call.getArgumentOperand(index)
|
||||
}
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { result = call.getEnclosingFunction() }
|
||||
override DataFlowCallable getEnclosingCallable() { result = TSourceCallable(call.getEnclosingFunction()) }
|
||||
|
||||
override string toString() { result = call.toString() }
|
||||
|
||||
@@ -1053,7 +1097,7 @@ class SummaryCall extends DataFlowCall, TSummaryCall {
|
||||
|
||||
// override ArgumentOperand getArgumentOperand(int index) TODO
|
||||
|
||||
// override DataFlowCallable getEnclosingCallable() { result = TSummarizedCallable(c) } TODO
|
||||
override DataFlowCallable getEnclosingCallable() { result = TSummarizedCallable(c) }
|
||||
|
||||
override string toString() { result = "[summary] call to " + receiver + " in " + c }
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ class Node extends TIRDataFlowNode {
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
Declaration getEnclosingCallable() { none() } // overridden in subclasses
|
||||
DataFlowCallable getEnclosingCallable() { none() } // overridden in subclasses
|
||||
|
||||
/** Gets the function to which this node belongs, if any. */
|
||||
Declaration getFunction() { none() } // overridden in subclasses
|
||||
@@ -503,7 +503,7 @@ private class Node0 extends Node, TNode0 {
|
||||
|
||||
Node0() { this = TNode0(node) }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = node.getEnclosingCallable() }
|
||||
override DataFlowCallable getEnclosingCallable() { result = node.getEnclosingCallable() }
|
||||
|
||||
override Declaration getFunction() { result = node.getFunction() }
|
||||
|
||||
@@ -568,7 +568,7 @@ class PostUpdateNodeImpl extends PartialDefinitionNode, TPostUpdateNodeImpl {
|
||||
|
||||
override Declaration getFunction() { result = operand.getUse().getEnclosingFunction() }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
override DataFlowCallable getEnclosingCallable() { result = TSourceCallable(this.getFunction()) }
|
||||
|
||||
/** Gets the operand associated with this node. */
|
||||
Operand getOperand() { result = operand }
|
||||
@@ -621,7 +621,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
|
||||
/** Gets the phi node associated with this node. */
|
||||
Ssa::PhiNode getPhiNode() { result = phi }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
override DataFlowCallable getEnclosingCallable() { result = TSourceCallable(this.getFunction()) }
|
||||
|
||||
override Declaration getFunction() { result = phi.getBasicBlock().getEnclosingFunction() }
|
||||
|
||||
@@ -690,7 +690,7 @@ class SideEffectOperandNode extends Node instanceof IndirectOperand {
|
||||
|
||||
int getArgumentIndex() { result = argumentIndex }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
override DataFlowCallable getEnclosingCallable() { result = TSourceCallable(this.getFunction()) }
|
||||
|
||||
override Declaration getFunction() { result = call.getEnclosingFunction() }
|
||||
|
||||
@@ -711,7 +711,7 @@ class FinalGlobalValue extends Node, TFinalGlobalValue {
|
||||
/** Gets the underlying SSA use. */
|
||||
Ssa::GlobalUse getGlobalUse() { result = globalUse }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
override DataFlowCallable getEnclosingCallable() { result = TSourceCallable(this.getFunction()) }
|
||||
|
||||
override Declaration getFunction() { result = globalUse.getIRFunction().getFunction() }
|
||||
|
||||
@@ -741,7 +741,7 @@ class InitialGlobalValue extends Node, TInitialGlobalValue {
|
||||
/** Gets the underlying SSA definition. */
|
||||
Ssa::GlobalDef getGlobalDef() { result = globalDef }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
override DataFlowCallable getEnclosingCallable() { result = TSourceCallable(this.getFunction()) }
|
||||
|
||||
override Declaration getFunction() { result = globalDef.getIRFunction().getFunction() }
|
||||
|
||||
@@ -778,7 +778,7 @@ class FlowSummaryNode extends Node, TFlowSummaryNode {
|
||||
* TODO: QLDoc.
|
||||
*/
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
none() //result.asSummarizedCallable() = this.getSummarizedCallable() TODO
|
||||
result = TSummarizedCallable(this.getSummarizedCallable())
|
||||
}
|
||||
|
||||
override Location getLocationImpl() { result = this.getSummarizedCallable().getLocation() }
|
||||
@@ -801,7 +801,7 @@ class IndirectParameterNode extends Node instanceof IndirectInstruction {
|
||||
/** Gets the parameter whose indirection is initialized. */
|
||||
Parameter getParameter() { result = init.getParameter() }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
override DataFlowCallable getEnclosingCallable() { result = TSourceCallable(this.getFunction()) }
|
||||
|
||||
override Declaration getFunction() { result = init.getEnclosingFunction() }
|
||||
|
||||
@@ -836,7 +836,7 @@ class IndirectReturnNode extends Node {
|
||||
.hasOperandAndIndirectionIndex(any(ReturnValueInstruction ret).getReturnAddressOperand(), _)
|
||||
}
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
override DataFlowCallable getEnclosingCallable() { result = TSourceCallable(this.getFunction()) }
|
||||
|
||||
/**
|
||||
* Holds if this node represents the value that is returned to the caller
|
||||
@@ -1031,7 +1031,7 @@ private module RawIndirectNodes {
|
||||
result = this.getOperand().getDef().getEnclosingFunction()
|
||||
}
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
override DataFlowCallable getEnclosingCallable() { result = TSourceCallable(this.getFunction()) }
|
||||
|
||||
override DataFlowType getType() {
|
||||
exists(int sub, DataFlowType type, boolean isGLValue |
|
||||
@@ -1073,7 +1073,7 @@ private module RawIndirectNodes {
|
||||
|
||||
override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
override DataFlowCallable getEnclosingCallable() { result = TSourceCallable(this.getFunction()) }
|
||||
|
||||
override DataFlowType getType() {
|
||||
exists(int sub, DataFlowType type, boolean isGLValue |
|
||||
@@ -1171,7 +1171,7 @@ class FinalParameterNode extends Node, TFinalParameterNode {
|
||||
|
||||
override Declaration getFunction() { result = p.getFunction() }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
override DataFlowCallable getEnclosingCallable() { result = TSourceCallable(this.getFunction()) }
|
||||
|
||||
override DataFlowType getType() { result = getTypeImpl(p.getUnspecifiedType(), indirectionIndex) }
|
||||
|
||||
@@ -1704,7 +1704,7 @@ private predicate indirectParameterNodeHasArgumentIndexAndIndex(
|
||||
/** A synthetic parameter to model the pointed-to object of a pointer parameter. */
|
||||
class ParameterIndirectionNode extends ParameterNode instanceof IndirectParameterNode {
|
||||
override predicate isParameterOf(Function f, ParameterPosition pos) {
|
||||
IndirectParameterNode.super.getEnclosingCallable() = f and
|
||||
IndirectParameterNode.super.getEnclosingCallable().asSourceCallable() = f and
|
||||
exists(int argumentIndex, int indirectionIndex |
|
||||
indirectPositionHasArgumentIndexAndIndex(pos, argumentIndex, indirectionIndex) and
|
||||
indirectParameterNodeHasArgumentIndexAndIndex(this, argumentIndex, indirectionIndex)
|
||||
@@ -1795,13 +1795,13 @@ class VariableNode extends Node, TVariableNode {
|
||||
|
||||
override Declaration getFunction() { none() }
|
||||
|
||||
override Declaration getEnclosingCallable() {
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
// When flow crosses from one _enclosing callable_ to another, the
|
||||
// interprocedural data-flow library discards call contexts and inserts a
|
||||
// node in the big-step relation used for human-readable path explanations.
|
||||
// Therefore we want a distinct enclosing callable for each `VariableNode`,
|
||||
// and that can be the `Variable` itself.
|
||||
result = v
|
||||
result = TSourceCallable(v)
|
||||
}
|
||||
|
||||
override DataFlowType getType() {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
| tests.cpp:115:5:115:19 | [summary param] 0 in madArg0ToReturn | | madArg0ToReturn | |
|
||||
| tests.cpp:115:5:115:19 | [summary] to write: ReturnValue in madArg0ToReturn | | madArg0ToReturn | |
|
||||
| tests.cpp:117:5:117:28 | [summary param] 0 in madArg0ToReturnValueFlow | | madArg0ToReturnValueFlow | |
|
||||
| tests.cpp:117:5:117:28 | [summary] to write: ReturnValue in madArg0ToReturnValueFlow | | madArg0ToReturnValueFlow | |
|
||||
| tests.cpp:119:6:119:18 | [summary param] 0 in madArg0ToArg1 | | madArg0ToArg1 | |
|
||||
| tests.cpp:119:6:119:18 | [summary param] 1 in madArg0ToArg1 | | madArg0ToArg1 | |
|
||||
| tests.cpp:119:6:119:18 | [summary] to write: Argument[1] in madArg0ToArg1 | | madArg0ToArg1 | |
|
||||
| tests.cpp:180:7:180:19 | [summary param] 0 in madArg0ToSelf | | madArg0ToSelf | |
|
||||
| tests.cpp:180:7:180:19 | [summary param] this in madArg0ToSelf | | madArg0ToSelf | |
|
||||
| tests.cpp:180:7:180:19 | [summary] to write: Argument[this] in madArg0ToSelf | | madArg0ToSelf | |
|
||||
| tests.cpp:181:6:181:20 | [summary param] this in madSelfToReturn | | madSelfToReturn | |
|
||||
| tests.cpp:181:6:181:20 | [summary] to write: ReturnValue in madSelfToReturn | | madSelfToReturn | |
|
||||
| tests.cpp:209:7:209:30 | [summary param] this in namespaceMadSelfToReturn | | namespaceMadSelfToReturn | |
|
||||
| tests.cpp:209:7:209:30 | [summary] to write: ReturnValue in namespaceMadSelfToReturn | | namespaceMadSelfToReturn | |
|
||||
| tests.cpp:115:5:115:19 | [summary param] 0 in madArg0ToReturn | | madArg0ToReturn | madArg0ToReturn |
|
||||
| tests.cpp:115:5:115:19 | [summary] to write: ReturnValue in madArg0ToReturn | | madArg0ToReturn | madArg0ToReturn |
|
||||
| tests.cpp:117:5:117:28 | [summary param] 0 in madArg0ToReturnValueFlow | | madArg0ToReturnValueFlow | madArg0ToReturnValueFlow |
|
||||
| tests.cpp:117:5:117:28 | [summary] to write: ReturnValue in madArg0ToReturnValueFlow | | madArg0ToReturnValueFlow | madArg0ToReturnValueFlow |
|
||||
| tests.cpp:119:6:119:18 | [summary param] 0 in madArg0ToArg1 | | madArg0ToArg1 | madArg0ToArg1 |
|
||||
| tests.cpp:119:6:119:18 | [summary param] 1 in madArg0ToArg1 | | madArg0ToArg1 | madArg0ToArg1 |
|
||||
| tests.cpp:119:6:119:18 | [summary] to write: Argument[1] in madArg0ToArg1 | | madArg0ToArg1 | madArg0ToArg1 |
|
||||
| tests.cpp:180:7:180:19 | [summary param] 0 in madArg0ToSelf | | madArg0ToSelf | madArg0ToSelf |
|
||||
| tests.cpp:180:7:180:19 | [summary param] this in madArg0ToSelf | | madArg0ToSelf | madArg0ToSelf |
|
||||
| tests.cpp:180:7:180:19 | [summary] to write: Argument[this] in madArg0ToSelf | | madArg0ToSelf | madArg0ToSelf |
|
||||
| tests.cpp:181:6:181:20 | [summary param] this in madSelfToReturn | | madSelfToReturn | madSelfToReturn |
|
||||
| tests.cpp:181:6:181:20 | [summary] to write: ReturnValue in madSelfToReturn | | madSelfToReturn | madSelfToReturn |
|
||||
| tests.cpp:209:7:209:30 | [summary param] this in namespaceMadSelfToReturn | | namespaceMadSelfToReturn | namespaceMadSelfToReturn |
|
||||
| tests.cpp:209:7:209:30 | [summary] to write: ReturnValue in namespaceMadSelfToReturn | | namespaceMadSelfToReturn | namespaceMadSelfToReturn |
|
||||
|
||||
Reference in New Issue
Block a user