mirror of
https://github.com/github/codeql.git
synced 2025-12-22 03:36:30 +01:00
Java: Add VS Code model editor queries
This commit is contained in:
@@ -25,7 +25,7 @@ class TestLibrary extends RefType {
|
||||
}
|
||||
|
||||
/** Holds if the given file is a test file. */
|
||||
private predicate isInTestFile(File file) {
|
||||
predicate isInTestFile(File file) {
|
||||
file.getAbsolutePath().matches(["%/test/%", "%/guava-tests/%", "%/guava-testlib/%"]) and
|
||||
not file.getAbsolutePath().matches(["%/ql/test/%", "%/ql/automodel/test/%"]) // allows our test cases to work
|
||||
}
|
||||
|
||||
139
java/ql/src/utils/modeleditor/AutomodelVsCode.qll
Normal file
139
java/ql/src/utils/modeleditor/AutomodelVsCode.qll
Normal file
@@ -0,0 +1,139 @@
|
||||
/** Provides classes and predicates related to handling APIs for the VS Code extension. */
|
||||
|
||||
private import java
|
||||
private import semmle.code.java.dataflow.DataFlow
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
private import semmle.code.java.dataflow.FlowSources
|
||||
private import semmle.code.java.dataflow.FlowSummary
|
||||
private import semmle.code.java.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
private import semmle.code.java.dataflow.TaintTracking
|
||||
private import semmle.code.java.dataflow.internal.ModelExclusions
|
||||
|
||||
/** Holds if the given callable/method is not worth supporting. */
|
||||
private predicate isUninteresting(Callable c) {
|
||||
c.getDeclaringType() instanceof TestLibrary or
|
||||
c.(Constructor).isParameterless() or
|
||||
c.getDeclaringType() instanceof AnonymousClass
|
||||
}
|
||||
|
||||
/**
|
||||
* A callable method from either the Standard Library, a 3rd party library or from the source.
|
||||
*/
|
||||
class CallableMethod extends Callable {
|
||||
CallableMethod() { not isUninteresting(this) }
|
||||
|
||||
/**
|
||||
* Gets information about the external API in the form expected by the MaD modeling framework.
|
||||
*/
|
||||
string getApiName() {
|
||||
result =
|
||||
this.getDeclaringType().getPackage() + "." + this.getDeclaringType().nestedName() + "#" +
|
||||
this.getName() + paramsString(this)
|
||||
}
|
||||
|
||||
private string getJarName() {
|
||||
result = this.getCompilationUnit().getParentContainer*().(JarFile).getBaseName()
|
||||
}
|
||||
|
||||
private string getJarVersion() {
|
||||
result = this.getCompilationUnit().getParentContainer*().(JarFile).getSpecificationVersion()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the jar file containing this API. Normalizes the Java Runtime to "rt.jar" despite the presence of modules.
|
||||
*/
|
||||
string jarContainer() {
|
||||
result = this.getJarName()
|
||||
or
|
||||
not exists(this.getJarName()) and result = "rt.jar"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the version of the JAR file containing this API. Empty if no version is found in the JAR.
|
||||
*/
|
||||
string jarVersion() {
|
||||
result = this.getJarVersion()
|
||||
or
|
||||
not exists(this.getJarVersion()) and result = ""
|
||||
}
|
||||
|
||||
/** Gets a node that is an input to a call to this API. */
|
||||
private DataFlow::Node getAnInput() {
|
||||
exists(Call call | call.getCallee().getSourceDeclaration() = this |
|
||||
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() {
|
||||
exists(Call call | call.getCallee().getSourceDeclaration() = this |
|
||||
result.asExpr() = call or
|
||||
result.(DataFlow::PostUpdateNode).getPreUpdateNode().(ArgumentNode).getCall().asCall() = call
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this API has a supported summary. */
|
||||
pragma[nomagic]
|
||||
predicate hasSummary() {
|
||||
this = any(SummarizedCallable sc).asCallable() or
|
||||
TaintTracking::localAdditionalTaintStep(this.getAnInput(), _)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate isSource() {
|
||||
this.getAnOutput() instanceof RemoteFlowSource or sourceNode(this.getAnOutput(), _)
|
||||
}
|
||||
|
||||
/** Holds if this API is a known sink. */
|
||||
pragma[nomagic]
|
||||
predicate isSink() { sinkNode(this.getAnInput(), _) }
|
||||
|
||||
/** Holds if this API is a known neutral. */
|
||||
pragma[nomagic]
|
||||
predicate isNeutral() {
|
||||
exists(
|
||||
string namespace, string type, string name, string signature, string kind, string provenance
|
||||
|
|
||||
neutralModel(namespace, type, name, signature, kind, provenance) and
|
||||
this = interpretElement(namespace, type, false, name, signature, "")
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
predicate isSupported() {
|
||||
this.hasSummary() or this.isSource() or this.isSink() or this.isNeutral()
|
||||
}
|
||||
}
|
||||
|
||||
boolean isSupported(CallableMethod method) {
|
||||
method.isSupported() and result = true
|
||||
or
|
||||
not method.isSupported() and result = false
|
||||
}
|
||||
|
||||
string supportedType(CallableMethod method) {
|
||||
method.isSink() and result = "sink"
|
||||
or
|
||||
method.isSource() and result = "source"
|
||||
or
|
||||
method.hasSummary() and result = "summary"
|
||||
or
|
||||
method.isNeutral() and result = "neutral"
|
||||
or
|
||||
not method.isSupported() and result = ""
|
||||
}
|
||||
|
||||
string methodClassification(Call method) {
|
||||
isInTestFile(method.getLocation().getFile()) and result = "test"
|
||||
or
|
||||
method.getFile() instanceof GeneratedFile and result = "generated"
|
||||
or
|
||||
not isInTestFile(method.getLocation().getFile()) and
|
||||
not method.getFile() instanceof GeneratedFile and
|
||||
result = "source"
|
||||
}
|
||||
29
java/ql/src/utils/modeleditor/FetchApplicationModeMethods.ql
Normal file
29
java/ql/src/utils/modeleditor/FetchApplicationModeMethods.ql
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @name Fetch model editor methods (application mode)
|
||||
* @description A list of 3rd party APIs used in the codebase. Excludes test and generated code.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @id java/utils/modeleditor/fetch-application-mode-methods
|
||||
* @tags modeleditor fetch methods application-mode
|
||||
*/
|
||||
|
||||
private import java
|
||||
private import AutomodelVsCode
|
||||
|
||||
class ExternalApi extends CallableMethod {
|
||||
ExternalApi() { not this.fromSource() }
|
||||
}
|
||||
|
||||
private Call aUsage(ExternalApi api) { result.getCallee().getSourceDeclaration() = api }
|
||||
|
||||
from
|
||||
ExternalApi externalApi, string apiName, boolean supported, Call usage, string type,
|
||||
string classification
|
||||
where
|
||||
apiName = externalApi.getApiName() and
|
||||
supported = isSupported(externalApi) and
|
||||
usage = aUsage(externalApi) and
|
||||
type = supportedType(externalApi) and
|
||||
classification = methodClassification(usage)
|
||||
select usage, apiName, supported.toString(), "supported", externalApi.jarContainer(),
|
||||
externalApi.jarVersion(), type, "type", classification, "classification"
|
||||
23
java/ql/src/utils/modeleditor/FetchFrameworkModeMethods.ql
Normal file
23
java/ql/src/utils/modeleditor/FetchFrameworkModeMethods.ql
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @name Fetch model editor methods (framework mode)
|
||||
* @description A list of APIs callable by consumers. Excludes test and generated code.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @id java/utils/modeleditor/fetch-framework-mode-methods
|
||||
* @tags modeleditor fetch methods framework-mode
|
||||
*/
|
||||
|
||||
private import java
|
||||
private import semmle.code.java.dataflow.internal.ModelExclusions
|
||||
private import AutomodelVsCode
|
||||
|
||||
class PublicMethodFromSource extends CallableMethod, ModelApi { }
|
||||
|
||||
from PublicMethodFromSource publicMethod, string apiName, boolean supported, string type
|
||||
where
|
||||
apiName = publicMethod.getApiName() and
|
||||
supported = isSupported(publicMethod) and
|
||||
type = supportedType(publicMethod)
|
||||
select publicMethod, apiName, supported.toString(), "supported",
|
||||
publicMethod.getCompilationUnit().getParentContainer().getBaseName(), "library", type, "type",
|
||||
"unknown", "classification"
|
||||
@@ -0,0 +1,8 @@
|
||||
| com/github/codeql/test/NonPublicClass.java:5:5:5:28 | println(...) | java.io.PrintStream#println(String) | true | supported | rt.jar | | sink | type | source | classification |
|
||||
| com/github/codeql/test/PublicClass.java:7:5:7:27 | println(...) | java.io.PrintStream#println(String) | true | supported | rt.jar | | sink | type | source | classification |
|
||||
| com/github/codeql/test/PublicClass.java:11:5:11:27 | println(...) | java.io.PrintStream#println(String) | true | supported | rt.jar | | sink | type | source | classification |
|
||||
| com/github/codeql/test/PublicClass.java:15:5:15:45 | println(...) | java.io.PrintStream#println(Object) | true | supported | rt.jar | | sink | type | source | classification |
|
||||
| com/github/codeql/test/PublicClass.java:15:24:15:44 | get(...) | java.nio.file.Paths#get(String,String[]) | true | supported | rt.jar | | sink | type | source | classification |
|
||||
| com/github/codeql/test/PublicClass.java:15:24:15:44 | get(...) | java.nio.file.Paths#get(String,String[]) | true | supported | rt.jar | | summary | type | source | classification |
|
||||
| com/github/codeql/test/PublicClass.java:19:5:19:27 | println(...) | java.io.PrintStream#println(String) | true | supported | rt.jar | | sink | type | source | classification |
|
||||
| com/github/codeql/test/PublicInterface.java:7:7:7:29 | println(...) | java.io.PrintStream#println(String) | true | supported | rt.jar | | sink | type | source | classification |
|
||||
@@ -0,0 +1 @@
|
||||
utils/modeleditor/FetchApplicationModeMethods.ql
|
||||
@@ -0,0 +1,5 @@
|
||||
| com/github/codeql/test/PublicClass.java:6:15:6:19 | stuff | com.github.codeql.test.PublicClass#stuff(String) | false | supported | test | library | | type | unknown | classification |
|
||||
| com/github/codeql/test/PublicClass.java:10:22:10:32 | staticStuff | com.github.codeql.test.PublicClass#staticStuff(String) | false | supported | test | library | | type | unknown | classification |
|
||||
| com/github/codeql/test/PublicClass.java:14:18:14:31 | nonPublicStuff | com.github.codeql.test.PublicClass#nonPublicStuff(String) | false | supported | test | library | | type | unknown | classification |
|
||||
| com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | com.github.codeql.test.PublicInterface#stuff(String) | false | supported | test | library | | type | unknown | classification |
|
||||
| com/github/codeql/test/PublicInterface.java:6:24:6:34 | staticStuff | com.github.codeql.test.PublicInterface#staticStuff(String) | false | supported | test | library | | type | unknown | classification |
|
||||
@@ -0,0 +1 @@
|
||||
utils/modeleditor/FetchFrameworkModeMethods.ql
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.github.codeql.test;
|
||||
|
||||
class NonPublicClass {
|
||||
public void noCandidates(String here) {
|
||||
System.out.println(here);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.github.codeql.test;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class PublicClass {
|
||||
public void stuff(String arg) {
|
||||
System.out.println(arg);
|
||||
}
|
||||
|
||||
public static void staticStuff(String arg) {
|
||||
System.out.println(arg);
|
||||
}
|
||||
|
||||
protected void nonPublicStuff(String arg) {
|
||||
System.out.println(Paths.get("foo", arg));
|
||||
}
|
||||
|
||||
void packagePrivateStuff(String arg) {
|
||||
System.out.println(arg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.github.codeql.test;
|
||||
|
||||
public interface PublicInterface {
|
||||
public void stuff(String arg);
|
||||
|
||||
public static void staticStuff(String arg) {
|
||||
System.out.println(arg);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user