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:
Max Schaefer
2024-02-16 08:51:54 +00:00
committed by GitHub
5 changed files with 117 additions and 50 deletions

View File

@@ -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()
}

View File

@@ -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()
}