mirror of
https://github.com/github/codeql.git
synced 2026-06-24 14:17:05 +02:00
Mostly just adding `private import LegacyPointsTo`. Sometimes getting rid of other imports that are superceded by that module.
155 lines
4.8 KiB
Plaintext
155 lines
4.8 KiB
Plaintext
/**
|
|
* Provides predicates for measuring the quality of the call graph, that is,
|
|
* the number of calls that could be resolved to a target.
|
|
*/
|
|
|
|
import python
|
|
import meta.MetaMetrics
|
|
private import LegacyPointsTo
|
|
|
|
newtype TTarget =
|
|
TFunction(Function func) or
|
|
TClass(Class cls)
|
|
|
|
class Target extends TTarget {
|
|
/** Gets a textual representation of this element. */
|
|
abstract string toString();
|
|
|
|
/** Gets the location of this dataflow call. */
|
|
abstract Location getLocation();
|
|
|
|
/** Whether this target is relevant. */
|
|
predicate isRelevant() { exists(this.getLocation().getFile().getRelativePath()) }
|
|
}
|
|
|
|
class TargetFunction extends Target, TFunction {
|
|
Function func;
|
|
|
|
TargetFunction() { this = TFunction(func) }
|
|
|
|
override string toString() { result = func.toString() }
|
|
|
|
override Location getLocation() { result = func.getLocation() }
|
|
|
|
Function getFunction() { result = func }
|
|
}
|
|
|
|
class TargetClass extends Target, TClass {
|
|
Class cls;
|
|
|
|
TargetClass() { this = TClass(cls) }
|
|
|
|
override string toString() { result = cls.toString() }
|
|
|
|
override Location getLocation() { result = cls.getLocation() }
|
|
|
|
Class getClass() { result = cls }
|
|
}
|
|
|
|
/**
|
|
* A call that is (possibly) relevant for analysis quality.
|
|
* See `IgnoredFile` for details on what is excluded.
|
|
*/
|
|
class RelevantCall extends CallNode {
|
|
RelevantCall() { not this.getLocation().getFile() instanceof IgnoredFile }
|
|
}
|
|
|
|
/** Provides classes for call-graph resolution by using points-to. */
|
|
module PointsToBasedCallGraph {
|
|
/** A call that can be resolved by points-to. */
|
|
class ResolvableCall extends RelevantCall {
|
|
Value targetValue;
|
|
|
|
ResolvableCall() { targetValue.getACall() = this }
|
|
|
|
/** Gets a resolved target of this call. */
|
|
Target getTarget() {
|
|
result.(TargetFunction).getFunction() = targetValue.(CallableValue).getScope()
|
|
or
|
|
result.(TargetClass).getClass() = targetValue.(ClassValue).getScope()
|
|
}
|
|
}
|
|
|
|
/** A call that cannot be resolved by points-to. */
|
|
class UnresolvableCall extends RelevantCall {
|
|
UnresolvableCall() { not this instanceof ResolvableCall }
|
|
}
|
|
|
|
/**
|
|
* A call that can be resolved by points-to, where the resolved target is relevant.
|
|
* Relevant targets include:
|
|
* - source code of the project
|
|
*/
|
|
class ResolvableCallRelevantTarget extends ResolvableCall {
|
|
ResolvableCallRelevantTarget() {
|
|
exists(Target target | target = this.getTarget() |
|
|
exists(target.getLocation().getFile().getRelativePath())
|
|
)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A call that can be resolved by points-to, where the resolved target is not considered relevant.
|
|
* See `ResolvableCallRelevantTarget` for the definition of relevance.
|
|
*/
|
|
class ResolvableCallIrrelevantTarget extends ResolvableCall {
|
|
ResolvableCallIrrelevantTarget() { not this instanceof ResolvableCallRelevantTarget }
|
|
}
|
|
}
|
|
|
|
/** Provides classes for call-graph resolution by using type-tracking. */
|
|
module TypeTrackingBasedCallGraph {
|
|
private import semmle.python.dataflow.new.internal.DataFlowDispatch as TT
|
|
|
|
/** A call that can be resolved by type-tracking. */
|
|
class ResolvableCall extends RelevantCall {
|
|
ResolvableCall() {
|
|
TT::resolveCall(this, _, _)
|
|
or
|
|
TT::resolveClassCall(this, _)
|
|
}
|
|
|
|
/** Gets a resolved target of this call. */
|
|
Target getTarget() {
|
|
exists(TT::CallType ct, Function targetFunc |
|
|
TT::resolveCall(this, targetFunc, ct) and
|
|
not ct instanceof TT::CallTypeClass and
|
|
targetFunc = result.(TargetFunction).getFunction()
|
|
)
|
|
or
|
|
// TT::resolveCall only holds when the call can be resolved to a function.
|
|
// Since points-to just says the call goes directly to the class itself, and
|
|
// type-tracking based wants to resolve this to the constructor, which might not
|
|
// exist. So to do a proper comparison, we don't require the call to be resolve to
|
|
// a specific function.
|
|
TT::resolveClassCall(this, result.(TargetClass).getClass())
|
|
}
|
|
}
|
|
|
|
/** A call that cannot be resolved by type-tracking. */
|
|
class UnresolvableCall extends RelevantCall {
|
|
UnresolvableCall() { not this instanceof ResolvableCall }
|
|
}
|
|
|
|
/**
|
|
* A call that can be resolved by type-tracking, where the resolved callee is relevant.
|
|
* Relevant targets include:
|
|
* - source code of the project
|
|
*/
|
|
class ResolvableCallRelevantTarget extends ResolvableCall {
|
|
ResolvableCallRelevantTarget() {
|
|
exists(Target target | target = this.getTarget() |
|
|
exists(target.getLocation().getFile().getRelativePath())
|
|
)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A call that can be resolved by type-tracking, where the resolved target is not considered relevant.
|
|
* See `ResolvableCallRelevantTarget` for the definition of relevance.
|
|
*/
|
|
class ResolvableCallIrrelevantTarget extends ResolvableCall {
|
|
ResolvableCallIrrelevantTarget() { not this instanceof ResolvableCallRelevantTarget }
|
|
}
|
|
}
|