Update library used by java query.

This commit is contained in:
Anders Starcke Henriksen
2023-04-17 15:42:53 +02:00
parent 0ee090b6e1
commit 7b901b4814

View File

@@ -33,147 +33,157 @@ select apiName, supported, usage
dependencies: { dependencies: {
"ExternalApi.qll": `/** Provides classes and predicates related to handling APIs from external libraries. */ "ExternalApi.qll": `/** Provides classes and predicates related to handling APIs from external libraries. */
private import java private import java
private import semmle.code.java.dataflow.DataFlow private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.ExternalFlow private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.dataflow.FlowSources private import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.dataflow.FlowSummary private import semmle.code.java.dataflow.FlowSummary
private import semmle.code.java.dataflow.internal.DataFlowPrivate private import semmle.code.java.dataflow.internal.DataFlowPrivate
private import semmle.code.java.dataflow.TaintTracking private import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.java.dataflow.TaintTracking
pragma[nomagic]
private predicate isTestPackage(Package p) { pragma[nomagic]
p.getName() private predicate isTestPackage(Package p) {
.matches([ p.getName()
"org.junit%", "junit.%", "org.mockito%", "org.assertj%", .matches([
"com.github.tomakehurst.wiremock%", "org.hamcrest%", "org.springframework.test.%", "org.junit%", "junit.%", "org.mockito%", "org.assertj%",
"org.springframework.mock.%", "org.springframework.boot.test.%", "reactor.test%", "com.github.tomakehurst.wiremock%", "org.hamcrest%", "org.springframework.test.%",
"org.xmlunit%", "org.testcontainers.%", "org.opentest4j%", "org.mockserver%", "org.springframework.mock.%", "org.springframework.boot.test.%", "reactor.test%",
"org.powermock%", "org.skyscreamer.jsonassert%", "org.rnorth.visibleassertions", "org.xmlunit%", "org.testcontainers.%", "org.opentest4j%", "org.mockserver%",
"org.openqa.selenium%", "com.gargoylesoftware.htmlunit%", "org.jboss.arquillian.testng%", "org.powermock%", "org.skyscreamer.jsonassert%", "org.rnorth.visibleassertions",
"org.testng%" "org.openqa.selenium%", "com.gargoylesoftware.htmlunit%", "org.jboss.arquillian.testng%",
]) "org.testng%"
} ])
}
/**
* A test library. /**
*/ * A test library.
private class TestLibrary extends RefType { */
TestLibrary() { isTestPackage(this.getPackage()) } private class TestLibrary extends RefType {
} TestLibrary() { isTestPackage(this.getPackage()) }
}
private string containerAsJar(Container container) {
if container instanceof JarFile then result = container.getBaseName() else result = "rt.jar" private string containerAsJar(Container container) {
} if container instanceof JarFile then result = container.getBaseName() else result = "rt.jar"
}
/** Holds if the given callable is not worth supporting. */
private predicate isUninteresting(Callable c) { /** Holds if the given callable is not worth supporting. */
c.getDeclaringType() instanceof TestLibrary or private predicate isUninteresting(Callable c) {
c.(Constructor).isParameterless() c.getDeclaringType() instanceof TestLibrary or
} c.(Constructor).isParameterless()
}
/**
* An external API from either the Standard Library or a 3rd party library. /**
*/ * An external API from either the Standard Library or a 3rd party library.
class ExternalApi extends Callable { */
ExternalApi() { not this.fromSource() and not isUninteresting(this) } class ExternalApi extends Callable {
ExternalApi() { not this.fromSource() and not isUninteresting(this) }
/**
* Gets information about the external API in the form expected by the MaD modeling framework. /**
*/ * Gets information about the external API in the form expected by the MaD modeling framework.
string getApiName() { */
result = string getApiName() {
this.getDeclaringType().getPackage() + "." + this.getDeclaringType().getSourceDeclaration() + result =
"#" + this.getName() + paramsString(this) this.getDeclaringType().getPackage() + "." + this.getDeclaringType().getSourceDeclaration() +
} "#" + this.getName() + paramsString(this)
}
/**
* Gets the jar file containing this API. Normalizes the Java Runtime to "rt.jar" despite the presence of modules. /**
*/ * Gets the jar file containing this API. Normalizes the Java Runtime to "rt.jar" despite the presence of modules.
string jarContainer() { result = containerAsJar(this.getCompilationUnit().getParentContainer*()) } */
string jarContainer() { result = containerAsJar(this.getCompilationUnit().getParentContainer*()) }
/** Gets a node that is an input to a call to this API. */
private DataFlow::Node getAnInput() { /** Gets a node that is an input to a call to this API. */
exists(Call call | call.getCallee().getSourceDeclaration() = this | private DataFlow::Node getAnInput() {
result.asExpr().(Argument).getCall() = call or exists(Call call | call.getCallee().getSourceDeclaration() = this |
result.(ArgumentNode).getCall().asCall() = call result.asExpr().(Argument).getCall() = call or
) result.(ArgumentNode).getCall().asCall() = call
} )
}
/** Gets a node that is an output from a call to this API. */
private DataFlow::Node getAnOutput() { /** Gets a node that is an output from a call to this API. */
exists(Call call | call.getCallee().getSourceDeclaration() = this | private DataFlow::Node getAnOutput() {
result.asExpr() = call or exists(Call call | call.getCallee().getSourceDeclaration() = this |
result.(DataFlow::PostUpdateNode).getPreUpdateNode().(ArgumentNode).getCall().asCall() = call result.asExpr() = call or
) result.(DataFlow::PostUpdateNode).getPreUpdateNode().(ArgumentNode).getCall().asCall() = call
} )
}
/** Holds if this API has a supported summary. */
pragma[nomagic] /** Holds if this API has a supported summary. */
predicate hasSummary() { pragma[nomagic]
this = any(SummarizedCallable sc).asCallable() or predicate hasSummary() {
TaintTracking::localAdditionalTaintStep(this.getAnInput(), _) this = any(SummarizedCallable sc).asCallable() or
} TaintTracking::localAdditionalTaintStep(this.getAnInput(), _)
}
pragma[nomagic]
predicate isSource() { pragma[nomagic]
this.getAnOutput() instanceof RemoteFlowSource or sourceNode(this.getAnOutput(), _) predicate isSource() {
} this.getAnOutput() instanceof RemoteFlowSource or sourceNode(this.getAnOutput(), _)
}
/** Holds if this API is a known sink. */
pragma[nomagic] /** Holds if this API is a known sink. */
predicate isSink() { sinkNode(this.getAnInput(), _) } pragma[nomagic]
predicate isSink() { sinkNode(this.getAnInput(), _) }
/** Holds if this API is supported by existing CodeQL libraries, that is, it is either a recognized source or sink or has a flow summary. */
predicate isSupported() { this.hasSummary() or this.isSource() or this.isSink() } /** Holds if this API is a known neutral. */
} pragma[nomagic]
predicate isNeutral() { this = any(FlowSummaryImpl::Public::NeutralCallable nsc).asCallable() }
/** DEPRECATED: Alias for ExternalApi */
deprecated class ExternalAPI = ExternalApi; /**
* Holds if this API is supported by existing CodeQL libraries, that is, it is either a
/** * recognized source, sink or neutral or it has a flow summary.
* Gets the limit for the number of results produced by a telemetry query. */
*/ predicate isSupported() {
int resultLimit() { result = 1000 } this.hasSummary() or this.isSource() or this.isSink() or this.isNeutral()
}
/** }
* Holds if it is relevant to count usages of \`api\`.
*/ /** DEPRECATED: Alias for ExternalApi */
signature predicate relevantApi(ExternalApi api); deprecated class ExternalAPI = ExternalApi;
/** /**
* Given a predicate to count relevant API usages, this module provides a predicate * Gets the limit for the number of results produced by a telemetry query.
* for restricting the number or returned results based on a certain limit. */
*/ int resultLimit() { result = 1000 }
module Results<relevantApi/1 getRelevantUsages> {
private int getUsages(string apiName) { /**
result = * Holds if it is relevant to count usages of \`api\`.
strictcount(Call c, ExternalApi api | */
c.getCallee().getSourceDeclaration() = api and signature predicate relevantApi(ExternalApi api);
not c.getFile() instanceof GeneratedFile and
apiName = api.getApiName() and /**
getRelevantUsages(api) * Given a predicate to count relevant API usages, this module provides a predicate
) * for restricting the number or returned results based on a certain limit.
} */
module Results<relevantApi/1 getRelevantUsages> {
private int getOrder(string apiInfo) { private int getUsages(string apiName) {
apiInfo = result =
rank[result](string info, int usages | strictcount(Call c, ExternalApi api |
usages = getUsages(info) c.getCallee().getSourceDeclaration() = api and
| not c.getFile() instanceof GeneratedFile and
info order by usages desc, info apiName = api.getApiName() and
) getRelevantUsages(api)
} )
}
/**
* Holds if there exists an API with \`apiName\` that is being used \`usages\` times private int getOrder(string apiInfo) {
* and if it is in the top results (guarded by resultLimit). apiInfo =
*/ rank[result](string info, int usages |
predicate restrict(string apiName, int usages) { usages = getUsages(info)
usages = getUsages(apiName) and |
getOrder(apiName) <= resultLimit() info order by usages desc, info
} )
} }
/**
* Holds if there exists an API with \`apiName\` that is being used \`usages\` times
* and if it is in the top results (guarded by resultLimit).
*/
predicate restrict(string apiName, int usages) {
usages = getUsages(apiName) and
getOrder(apiName) <= resultLimit()
}
}
`, `,
}, },
}; };