mirror of
https://github.com/github/codeql.git
synced 2026-04-28 02:05:14 +02:00
C++: Use CallInstruction as DataFlowCall
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
private import semmle.code.cpp.ir.IR
|
||||
|
||||
Function viableImpl(CallInstruction call) { result = viableCallable(call) }
|
||||
|
||||
/**
|
||||
* Gets a function that might be called by `call`.
|
||||
*/
|
||||
Function viableCallable(CallInstruction call) {
|
||||
result = 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
|
||||
// will be determined at run time when the caller and callee are linked
|
||||
// together by the operating system's dynamic linker. In case a _unique_
|
||||
// function with the right signature is present in the database, we return
|
||||
// that as a potential callee.
|
||||
exists(string qualifiedName, int nparams |
|
||||
callSignatureWithoutBody(qualifiedName, nparams, call) and
|
||||
functionSignatureWithBody(qualifiedName, nparams, result) and
|
||||
strictcount(Function other | functionSignatureWithBody(qualifiedName, nparams, other)) = 1
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `f` is a function with a body that has name `qualifiedName` and
|
||||
* `nparams` parameter count. See `functionSignature`.
|
||||
*/
|
||||
private predicate functionSignatureWithBody(string qualifiedName, int nparams, Function f) {
|
||||
functionSignature(f, qualifiedName, nparams) and
|
||||
exists(f.getBlock())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the target of `call` is a function _with no definition_ that has
|
||||
* name `qualifiedName` and `nparams` parameter count. See `functionSignature`.
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate callSignatureWithoutBody(string qualifiedName, int nparams, CallInstruction call) {
|
||||
exists(Function target |
|
||||
target = call.getStaticCallTarget() and
|
||||
not exists(target.getBlock()) and
|
||||
functionSignature(target, qualifiedName, nparams)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `f` has name `qualifiedName` and `nparams` parameter count. This is
|
||||
* an approximation of its signature for the purpose of matching functions that
|
||||
* might be the same across link targets.
|
||||
*/
|
||||
private predicate functionSignature(Function f, string qualifiedName, int nparams) {
|
||||
qualifiedName = f.getQualifiedName() and
|
||||
nparams = f.getNumberOfParameters() and
|
||||
not f.isStatic()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the call context `ctx` reduces the set of viable dispatch
|
||||
* targets of `ma` in `c`.
|
||||
*/
|
||||
predicate reducedViableImplInCallContext(CallInstruction call, Function f, CallInstruction ctx) { none() }
|
||||
|
||||
/**
|
||||
* Gets a viable dispatch target of `ma` in the context `ctx`. This is
|
||||
* restricted to those `ma`s for which the context makes a difference.
|
||||
*/
|
||||
Function prunedViableImplInCallContext(CallInstruction call, CallInstruction ctx) { none() }
|
||||
|
||||
/**
|
||||
* Holds if flow returning from `m` to `ma` might return further and if
|
||||
* this path restricts the set of call sites that can be returned to.
|
||||
*/
|
||||
predicate reducedViableImplInReturn(Function f, CallInstruction call) { none() }
|
||||
|
||||
/**
|
||||
* Gets a viable dispatch target of `ma` in the context `ctx`. This is
|
||||
* restricted to those `ma`s and results for which the return flow from the
|
||||
* result to `ma` restricts the possible context `ctx`.
|
||||
*/
|
||||
Function prunedViableImplInCallContextReverse(CallInstruction call, CallInstruction ctx) { none() }
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
module Private {
|
||||
import DataFlowPrivate
|
||||
import semmle.code.cpp.dataflow.internal.DataFlowDispatch
|
||||
import DataFlowDispatch
|
||||
}
|
||||
|
||||
module Public {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
private import cpp
|
||||
private import DataFlowUtil
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.dataflow.internal.DataFlowDispatch
|
||||
private import DataFlowDispatch
|
||||
|
||||
/**
|
||||
* A data flow node that occurs as the argument of a call and is passed as-is
|
||||
@@ -15,14 +15,9 @@ class ArgumentNode extends Node {
|
||||
* The instance argument is considered to have index `-1`.
|
||||
*/
|
||||
predicate argumentOf(DataFlowCall call, int pos) {
|
||||
exists(CallInstruction callInstr |
|
||||
callInstr.getAST() = call and
|
||||
(
|
||||
this = callInstr.getPositionalArgument(pos)
|
||||
or
|
||||
this = callInstr.getThisArgument() and pos = -1
|
||||
)
|
||||
)
|
||||
this = call.getPositionalArgument(pos)
|
||||
or
|
||||
this = call.getThisArgument() and pos = -1
|
||||
}
|
||||
|
||||
/** Gets the call in which this node is an argument. */
|
||||
@@ -52,11 +47,9 @@ class ReturnNode extends Node {
|
||||
}
|
||||
|
||||
/** A data flow node that represents a call. */
|
||||
class OutNode extends ExprNode {
|
||||
OutNode() { this.getExpr() instanceof FunctionCall }
|
||||
|
||||
class OutNode extends Node, CallInstruction {
|
||||
/** Gets the underlying call. */
|
||||
DataFlowCall getCall() { result = this.getExpr() }
|
||||
DataFlowCall getCall() { result = this }
|
||||
}
|
||||
|
||||
/** Gets a node that can read the value returned at position `pos`. */
|
||||
@@ -198,19 +191,11 @@ class DataFlowType = Type;
|
||||
class DataFlowLocation = Location;
|
||||
|
||||
/** A function call relevant for data flow. */
|
||||
class DataFlowCall extends Expr {
|
||||
DataFlowCall() { this instanceof Call }
|
||||
|
||||
class DataFlowCall extends CallInstruction, Node {
|
||||
/**
|
||||
* Gets the nth argument for this call.
|
||||
*
|
||||
* The range of `n` is from `0` to `getNumberOfArguments() - 1`.
|
||||
*/
|
||||
Expr getArgument(int n) { result = this.(Call).getArgument(n) }
|
||||
|
||||
/** Gets the data flow node corresponding to this call. */
|
||||
ExprNode getNode() { result.getExpr() = this }
|
||||
|
||||
/** Gets the enclosing callable of this call. */
|
||||
Function getEnclosingCallable() { result = this.getEnclosingFunction() }
|
||||
Node getArgument(int n) { result = this.getPositionalArgument(n) }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user