mirror of
https://github.com/github/codeql.git
synced 2026-04-23 07:45:17 +02:00
Merge pull request #15554 from github/max-schaefer/automodel-candidate-fixes
Automodel: Improve handling of varargs and overriding in extraction queries
This commit is contained in:
@@ -35,14 +35,10 @@ newtype TApplicationModeEndpoint =
|
||||
arg = DataFlow::getInstanceArgument(call) and
|
||||
not call instanceof ConstructorCall
|
||||
} or
|
||||
TImplicitVarargsArray(Call call, DataFlow::Node arg, int idx) {
|
||||
TImplicitVarargsArray(Call call, DataFlow::ImplicitVarargsArray arg, int idx) {
|
||||
AutomodelJavaUtil::isFromSource(call) and
|
||||
exists(Argument argExpr |
|
||||
arg.asExpr() = argExpr and
|
||||
call.getArgument(idx) = argExpr and
|
||||
argExpr.isVararg() and
|
||||
not exists(int i | i < idx and call.getArgument(i).(Argument).isVararg())
|
||||
)
|
||||
call = arg.getCall() and
|
||||
idx = call.getCallee().getVaragsParameterIndex()
|
||||
} or
|
||||
TMethodReturnValue(Call call) {
|
||||
AutomodelJavaUtil::isFromSource(call) and
|
||||
@@ -255,45 +251,74 @@ module ApplicationCandidatesImpl implements SharedCharacteristics::CandidateSig
|
||||
predicate isKnownKind = AutomodelJavaUtil::isKnownKind/2;
|
||||
|
||||
predicate isSink(Endpoint e, string kind, string provenance) {
|
||||
exists(string package, string type, string name, string signature, string ext, string input |
|
||||
sinkSpec(e, package, type, name, signature, ext, input) and
|
||||
ExternalFlow::sinkModel(package, type, _, name, [signature, ""], ext, input, kind, provenance)
|
||||
exists(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input
|
||||
|
|
||||
sinkSpec(e, package, type, subtypes, name, signature, ext, input) and
|
||||
ExternalFlow::sinkModel(package, type, subtypes, name, [signature, ""], ext, input, kind,
|
||||
provenance)
|
||||
)
|
||||
or
|
||||
isCustomSink(e, kind) and provenance = "custom-sink"
|
||||
}
|
||||
|
||||
predicate isSource(Endpoint e, string kind, string provenance) {
|
||||
exists(string package, string type, string name, string signature, string ext, string output |
|
||||
sourceSpec(e, package, type, name, signature, ext, output) and
|
||||
ExternalFlow::sourceModel(package, type, _, name, [signature, ""], ext, output, kind,
|
||||
exists(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string output
|
||||
|
|
||||
sourceSpec(e, package, type, subtypes, name, signature, ext, output) and
|
||||
ExternalFlow::sourceModel(package, type, subtypes, name, [signature, ""], ext, output, kind,
|
||||
provenance)
|
||||
)
|
||||
}
|
||||
|
||||
predicate isNeutral(Endpoint e) {
|
||||
exists(string package, string type, string name, string signature |
|
||||
sinkSpec(e, package, type, name, signature, _, _) and
|
||||
ExternalFlow::neutralModel(package, type, name, [signature, ""], "sink", _)
|
||||
exists(string package, string type, string name, string signature, string endpointType |
|
||||
sinkSpec(e, package, type, _, name, signature, _, _) and
|
||||
endpointType = "sink"
|
||||
or
|
||||
sourceSpec(e, package, type, _, name, signature, _, _) and
|
||||
endpointType = "source"
|
||||
|
|
||||
ExternalFlow::neutralModel(package, type, name, [signature, ""], endpointType, _)
|
||||
)
|
||||
}
|
||||
|
||||
// XXX how to extend to support sources?
|
||||
additional predicate sinkSpec(
|
||||
Endpoint e, string package, string type, string name, string signature, string ext, string input
|
||||
/**
|
||||
* Holds if the endpoint concerns a callable with the given package, type, name and signature.
|
||||
*
|
||||
* If `subtypes` is `false`, only the exact callable is considered. If `true`, the callable and
|
||||
* all its overrides are considered.
|
||||
*/
|
||||
additional predicate endpointCallable(
|
||||
Endpoint e, string package, string type, boolean subtypes, string name, string signature
|
||||
) {
|
||||
e.getCallable().hasQualifiedName(package, type, name) and
|
||||
signature = ExternalFlow::paramsString(e.getCallable()) and
|
||||
exists(Callable c |
|
||||
c = e.getCallable() and subtypes in [true, false]
|
||||
or
|
||||
e.getCallable().(Method).getSourceDeclaration().overrides+(c) and subtypes = true
|
||||
|
|
||||
c.hasQualifiedName(package, type, name) and
|
||||
signature = ExternalFlow::paramsString(c)
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate sinkSpec(
|
||||
Endpoint e, string package, string type, boolean subtypes, string name, string signature,
|
||||
string ext, string input
|
||||
) {
|
||||
endpointCallable(e, package, type, subtypes, name, signature) and
|
||||
ext = "" and
|
||||
input = e.getMaDInput()
|
||||
}
|
||||
|
||||
additional predicate sourceSpec(
|
||||
Endpoint e, string package, string type, string name, string signature, string ext,
|
||||
string output
|
||||
Endpoint e, string package, string type, boolean subtypes, string name, string signature,
|
||||
string ext, string output
|
||||
) {
|
||||
e.getCallable().hasQualifiedName(package, type, name) and
|
||||
signature = ExternalFlow::paramsString(e.getCallable()) and
|
||||
endpointCallable(e, package, type, subtypes, name, signature) and
|
||||
ext = "" and
|
||||
output = e.getMaDOutput()
|
||||
}
|
||||
|
||||
@@ -209,46 +209,72 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
|
||||
predicate isKnownKind = AutomodelJavaUtil::isKnownKind/2;
|
||||
|
||||
predicate isSink(Endpoint e, string kind, string provenance) {
|
||||
exists(string package, string type, string name, string signature, string ext, string input |
|
||||
sinkSpec(e, package, type, name, signature, ext, input) and
|
||||
ExternalFlow::sinkModel(package, type, _, name, [signature, ""], ext, input, kind, provenance)
|
||||
exists(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input
|
||||
|
|
||||
sinkSpec(e, package, type, subtypes, name, signature, ext, input) and
|
||||
ExternalFlow::sinkModel(package, type, subtypes, name, [signature, ""], ext, input, kind,
|
||||
provenance)
|
||||
)
|
||||
}
|
||||
|
||||
predicate isSource(Endpoint e, string kind, string provenance) {
|
||||
exists(string package, string type, string name, string signature, string ext, string output |
|
||||
sourceSpec(e, package, type, name, signature, ext, output) and
|
||||
ExternalFlow::sourceModel(package, type, _, name, [signature, ""], ext, output, kind,
|
||||
exists(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string output
|
||||
|
|
||||
sourceSpec(e, package, type, subtypes, name, signature, ext, output) and
|
||||
ExternalFlow::sourceModel(package, type, subtypes, name, [signature, ""], ext, output, kind,
|
||||
provenance)
|
||||
)
|
||||
}
|
||||
|
||||
predicate isNeutral(Endpoint e) {
|
||||
exists(string package, string type, string name, string signature |
|
||||
(
|
||||
sinkSpec(e, package, type, name, signature, _, _)
|
||||
or
|
||||
sourceSpec(e, package, type, name, signature, _, _)
|
||||
) and
|
||||
ExternalFlow::neutralModel(package, type, name, [signature, ""], "sink", _)
|
||||
exists(string package, string type, string name, string signature, string endpointType |
|
||||
sinkSpec(e, package, type, _, name, signature, _, _) and
|
||||
endpointType = "sink"
|
||||
or
|
||||
sourceSpec(e, package, type, _, name, signature, _, _) and
|
||||
endpointType = "source"
|
||||
|
|
||||
ExternalFlow::neutralModel(package, type, name, [signature, ""], endpointType, _)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the endpoint concerns a callable with the given package, type, name and signature.
|
||||
*
|
||||
* If `subtypes` is `false`, only the exact callable is considered. If `true`, the callable and
|
||||
* all its overrides are considered.
|
||||
*/
|
||||
additional predicate endpointCallable(
|
||||
Endpoint e, string package, string type, boolean subtypes, string name, string signature
|
||||
) {
|
||||
exists(Callable c |
|
||||
c = e.getCallable() and subtypes in [true, false]
|
||||
or
|
||||
e.getCallable().(Method).getSourceDeclaration().overrides+(c) and subtypes = true
|
||||
|
|
||||
c.hasQualifiedName(package, type, name) and
|
||||
signature = ExternalFlow::paramsString(c)
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate sinkSpec(
|
||||
Endpoint e, string package, string type, string name, string signature, string ext, string input
|
||||
Endpoint e, string package, string type, boolean subtypes, string name, string signature,
|
||||
string ext, string input
|
||||
) {
|
||||
e.getCallable().hasQualifiedName(package, type, name) and
|
||||
signature = ExternalFlow::paramsString(e.getCallable()) and
|
||||
endpointCallable(e, package, type, subtypes, name, signature) and
|
||||
ext = "" and
|
||||
input = e.getMaDInput()
|
||||
}
|
||||
|
||||
additional predicate sourceSpec(
|
||||
Endpoint e, string package, string type, string name, string signature, string ext,
|
||||
string output
|
||||
Endpoint e, string package, string type, boolean subtypes, string name, string signature,
|
||||
string ext, string output
|
||||
) {
|
||||
e.getCallable().hasQualifiedName(package, type, name) and
|
||||
signature = ExternalFlow::paramsString(e.getCallable()) and
|
||||
endpointCallable(e, package, type, subtypes, name, signature) and
|
||||
ext = "" and
|
||||
output = e.getMaDOutput()
|
||||
}
|
||||
|
||||
@@ -40,11 +40,12 @@ class Test {
|
||||
); // $ sourceModelCandidate=newInputStream(Path,OpenOption[]):ReturnValue
|
||||
}
|
||||
|
||||
public static InputStream getInputStream(String openPath) throws Exception {
|
||||
public static InputStream getInputStream(String openPath, String otherPath) throws Exception {
|
||||
return Test.getInputStream( // the call is not a source candidate (argument to local call)
|
||||
Paths.get(
|
||||
openPath // $ negativeSinkExample=get(String,String[]):Argument[0] // modeled as a flow step
|
||||
) // $ sourceModelCandidate=get(String,String[]):ReturnValue
|
||||
openPath, // $ negativeSinkExample=get(String,String[]):Argument[0] // modeled as a flow step
|
||||
otherPath
|
||||
) // $ sourceModelCandidate=get(String,String[]):ReturnValue negativeSinkExample=get(String,String[]):Argument[1]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.github.codeql.test;
|
||||
|
||||
public class MyWriter extends java.io.Writer {
|
||||
@Override
|
||||
public void write(char[] cbuf, int off, int len) { // $ sinkModelCandidate=write(char[],int,int):Argument[this] sourceModelCandidate=write(char[],int,int):Parameter[this] sourceModelCandidate=write(char[],int,int):Parameter[0]
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() { // $ sinkModelCandidate=close():Argument[this] sourceModelCandidate=close():Parameter[this]
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() { // $ sinkModelCandidate=flush():Argument[this] sourceModelCandidate=flush():Parameter[this]
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package java.io;
|
||||
|
||||
public class File {
|
||||
public int compareTo( // $ negativeSinkExample=compareTo(File):Argument[this] negativeSourceExample=compareTo(File):Parameter[this] // modeled as neutral
|
||||
File pathname // $ negativeSinkExample=compareTo(File):Argument[0] negativeSourceExample=compareTo(File):Parameter[0] // modeled as neutral
|
||||
public int compareTo( // $ negativeSinkExample=compareTo(File):Argument[this] sourceModelCandidate=compareTo(File):Parameter[this] // modeled as neutral for sinks
|
||||
File pathname // $ negativeSinkExample=compareTo(File):Argument[0] sourceModelCandidate=compareTo(File):Parameter[0] // modeled as neutral for sinks
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user