зеркало из https://github.com/github/codeql.git
Java: Re-factor NeutralCallable to include all neutrals and introduce NeutralSummaryCallable.
This commit is contained in:
Родитель
6deeb36a97
Коммит
5623ccf4a0
|
@ -175,8 +175,6 @@ class Provenance = Impl::Public::Provenance;
|
|||
|
||||
class SummarizedCallable = Impl::Public::SummarizedCallable;
|
||||
|
||||
class NeutralCallable = Impl::Public::NeutralCallable;
|
||||
|
||||
/**
|
||||
* An adapter class to add the flow summaries specified on `SyntheticCallable`
|
||||
* to `SummarizedCallable`.
|
||||
|
|
|
@ -2,16 +2,16 @@ private import java
|
|||
private import DataFlowPrivate
|
||||
private import DataFlowUtil
|
||||
private import semmle.code.java.dataflow.InstanceAccess
|
||||
private import semmle.code.java.dataflow.FlowSummary
|
||||
private import semmle.code.java.dataflow.internal.FlowSummaryImpl as Impl
|
||||
private import semmle.code.java.dispatch.VirtualDispatch as VirtualDispatch
|
||||
private import semmle.code.java.dataflow.TypeFlow
|
||||
private import semmle.code.java.dispatch.internal.Unification
|
||||
|
||||
private module DispatchImpl {
|
||||
private predicate hasHighConfidenceTarget(Call c) {
|
||||
exists(SummarizedCallable sc | sc.getACall() = c and not sc.applyGeneratedModel())
|
||||
exists(Impl::Public::SummarizedCallable sc | sc.getACall() = c and not sc.applyGeneratedModel())
|
||||
or
|
||||
exists(NeutralCallable nc | nc.getACall() = c and nc.hasManualModel())
|
||||
exists(Impl::Public::NeutralSummaryCallable nc | nc.getACall() = c and nc.hasManualModel())
|
||||
or
|
||||
exists(Callable srcTgt |
|
||||
srcTgt = VirtualDispatch::viableCallable(c) and
|
||||
|
|
|
@ -296,11 +296,21 @@ module Public {
|
|||
predicate hasProvenance(Provenance provenance) { provenance = "manual" }
|
||||
}
|
||||
|
||||
/** A callable where there is no flow via the callable. */
|
||||
class NeutralCallable extends SummarizedCallableBase {
|
||||
/**
|
||||
* A callable where there is no flow via the callable.
|
||||
*/
|
||||
class NeutralSummaryCallable extends NeutralCallable {
|
||||
NeutralSummaryCallable() { this.getKind() = "summary" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A callable that has a neutral model.
|
||||
*/
|
||||
class NeutralCallable extends NeutralCallableBase {
|
||||
private string kind;
|
||||
private Provenance provenance;
|
||||
|
||||
NeutralCallable() { neutralSummaryElement(this, provenance) }
|
||||
NeutralCallable() { neutralElement(this, kind, provenance) }
|
||||
|
||||
/**
|
||||
* Holds if the neutral is auto generated.
|
||||
|
@ -316,6 +326,11 @@ module Public {
|
|||
* Holds if the neutral has provenance `p`.
|
||||
*/
|
||||
predicate hasProvenance(Provenance p) { p = provenance }
|
||||
|
||||
/**
|
||||
* Gets the kind of the neutral.
|
||||
*/
|
||||
string getKind() { result = kind }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1318,6 +1333,8 @@ module Private {
|
|||
/** Gets the string representation of this callable used by `neutral/1`. */
|
||||
abstract string getCallableCsv();
|
||||
|
||||
string getKind() { result = super.getKind() }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
}
|
||||
|
||||
|
@ -1364,6 +1381,7 @@ module Private {
|
|||
exists(RelevantNeutralCallable c |
|
||||
csv =
|
||||
c.getCallableCsv() // Callable information
|
||||
+ c.getKind() + ";" // kind
|
||||
+ renderProvenanceNeutral(c) // provenance
|
||||
)
|
||||
}
|
||||
|
|
|
@ -14,6 +14,16 @@ private import semmle.code.java.dataflow.internal.AccessPathSyntax as AccessPath
|
|||
|
||||
class SummarizedCallableBase = FlowSummary::SummarizedCallableBase;
|
||||
|
||||
/**
|
||||
* A class of callables that are candidates for neutral modeling.
|
||||
*/
|
||||
class NeutralCallableBase extends Callable {
|
||||
NeutralCallableBase() { this.isSourceDeclaration() }
|
||||
|
||||
/** Gets a call that targets this neutral. */
|
||||
Call getACall() { result.getCallee().getSourceDeclaration() = this }
|
||||
}
|
||||
|
||||
/**
|
||||
* A module for importing frameworks that define synthetic globals.
|
||||
*/
|
||||
|
@ -156,13 +166,13 @@ predicate summaryElement(
|
|||
}
|
||||
|
||||
/**
|
||||
* Holds if a neutral summary model exists for `c` with provenance `provenance`,
|
||||
* which means that there is no flow through `c`.
|
||||
* Holds if a neutral model exists for `c` of kind `kind`
|
||||
* and with provenance `provenance`.
|
||||
*/
|
||||
predicate neutralSummaryElement(SummarizedCallableBase c, string provenance) {
|
||||
predicate neutralElement(NeutralCallableBase c, string kind, string provenance) {
|
||||
exists(string namespace, string type, string name, string signature |
|
||||
neutralModel(namespace, type, name, signature, "summary", provenance) and
|
||||
c.asCallable() = interpretElement(namespace, type, false, name, signature, "")
|
||||
neutralModel(namespace, type, name, signature, kind, provenance) and
|
||||
c = interpretElement(namespace, type, false, name, signature, "")
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -45,12 +45,10 @@ private int getNumApis(string package, string apiSubset) {
|
|||
|
||||
/** Holds if the given `callable` belongs to the specified `apiSubset`. */
|
||||
private predicate callableSubset(Callable callable, string apiSubset) {
|
||||
apiSubset in ["topJdkApis", "allApis"] and
|
||||
(
|
||||
if apiSubset = "topJdkApis"
|
||||
then exists(TopJdkApi topJdkApi | callable = topJdkApi.asCallable())
|
||||
else apiSubset = "allApis"
|
||||
)
|
||||
apiSubset = "topJdkApis" and
|
||||
callable instanceof TopJdkApi
|
||||
or
|
||||
apiSubset = "allApis"
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -287,16 +287,19 @@ predicate hasApiName(Callable c, string apiName) {
|
|||
}
|
||||
|
||||
/** A top JDK API. */
|
||||
class TopJdkApi extends SummarizedCallableBase {
|
||||
class TopJdkApi extends Callable {
|
||||
TopJdkApi() {
|
||||
this.isSourceDeclaration() and
|
||||
exists(string apiName |
|
||||
hasApiName(this.asCallable(), apiName) and
|
||||
hasApiName(this, apiName) and
|
||||
topJdkApiName(apiName)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this API has a manual summary model. */
|
||||
private predicate hasManualSummary() { this.(SummarizedCallable).hasManualModel() }
|
||||
private predicate hasManualSummary() {
|
||||
exists(SummarizedCallable sc | sc.asCallable() = this and sc.hasManualModel())
|
||||
}
|
||||
|
||||
/** Holds if this API has a manual neutral model. */
|
||||
private predicate hasManualNeutral() {
|
||||
|
|
|
@ -79,7 +79,7 @@ class ExternalApi extends Callable {
|
|||
|
||||
/** Holds if this API is a known neutral. */
|
||||
pragma[nomagic]
|
||||
predicate isNeutral() { this = any(FlowSummaryImpl::Public::NeutralCallable nsc).asCallable() }
|
||||
predicate isNeutral() { this instanceof FlowSummaryImpl::Public::NeutralCallable }
|
||||
|
||||
/**
|
||||
* Holds if this API is supported by existing CodeQL libraries, that is, it is either a
|
||||
|
|
|
@ -11,7 +11,7 @@ where
|
|||
// top jdk api names for which there isn't a manual model
|
||||
exists(TopJdkApi topApi |
|
||||
not topApi.hasManualMadModel() and
|
||||
hasApiName(topApi.asCallable(), apiName) and
|
||||
hasApiName(topApi, apiName) and
|
||||
message = "no manual model"
|
||||
)
|
||||
select apiName, message order by apiName
|
||||
|
|
Загрузка…
Ссылка в новой задаче