mirror of
https://github.com/github/codeql.git
synced 2026-06-25 22:57:01 +02:00
Missing manual models were added using the following code added to `FlowSummaryImpl.qll`:
```ql
private predicate testsummaryElement(
Input::SummarizedCallableBase c, string namespace, string type, boolean subtypes, string name,
string signature, string ext, string originalInput, string originalOutput, string kind,
string provenance, string model, boolean isExact
) {
exists(string input, string output, Callable baseCallable |
summaryModel(namespace, type, subtypes, name, signature, ext, originalInput, originalOutput,
kind, provenance, model) and
baseCallable = interpretElement(namespace, type, subtypes, name, signature, ext, isExact) and
(
c.asCallable() = baseCallable and input = originalInput and output = originalOutput
or
correspondingKotlinParameterDefaultsArgSpec(baseCallable, c.asCallable(), originalInput,
input) and
correspondingKotlinParameterDefaultsArgSpec(baseCallable, c.asCallable(), originalOutput,
output)
)
)
}
private predicate testsummaryElement2(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string originalInput, string originalOutput, string kind, string provenance, string model,
string namespace2, string type2
) {
exists(Input::SummarizedCallableBase c |
testsummaryElement(c, namespace2, type2, _, _, _, ext, originalInput, originalOutput, kind,
provenance, model, false) and
testsummaryElement(c, namespace, type, subtypes, name, _, _, _, _, _, provenance, _, true) and
signature = paramsString(c.asCallable()) and
not testsummaryElement(c, _, _, _, _, _, _, originalInput, originalOutput, kind, provenance,
_, true)
)
}
private string getAMissingManualModel(string namespace2, string type2) {
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string originalInput, string originalOutput, string kind, string provenance, string model
|
testsummaryElement2(namespace, type, subtypes, name, signature, ext, originalInput,
originalOutput, kind, provenance, model, namespace2, type2) and
result =
"- [\"" + namespace + "\", \"" + type + "\", True, \"" + name + "\", \"" + signature +
"\", \"\", \"" + originalInput + "\", \"" + originalOutput + "\", \"" + kind + "\", \"" +
provenance + "\"]"
)
}
```
87 lines
2.7 KiB
Plaintext
87 lines
2.7 KiB
Plaintext
/**
|
|
* Provides classes and predicates for reasoning about calls that may invoke one
|
|
* of their arguments.
|
|
*/
|
|
overlay[local?]
|
|
module;
|
|
|
|
import java
|
|
import VirtualDispatch
|
|
|
|
/**
|
|
* Holds if `m` might invoke `runmethod` through a functional interface on the
|
|
* `n`th parameter.
|
|
*/
|
|
private predicate runner(Method m, int n, Method runmethod) {
|
|
m.getParameterType(n).(RefType).getSourceDeclaration().(FunctionalInterface).getRunMethod() =
|
|
runmethod and
|
|
(
|
|
m.isNative()
|
|
or
|
|
exists(Parameter p, MethodCall ma, int j |
|
|
p = m.getParameter(n) and
|
|
ma.getEnclosingCallable() = m and
|
|
runner(pragma[only_bind_into](ma.getMethod().getSourceDeclaration()),
|
|
pragma[only_bind_into](j), _) and
|
|
ma.getArgument(pragma[only_bind_into](j)) = p.getAnAccess()
|
|
)
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Gets an argument of `ma` on which `ma.getMethod()` might invoke `runmethod`
|
|
* through a functional interface. The argument is traced backwards through
|
|
* casts and variable assignments.
|
|
*/
|
|
private Expr getRunnerArgument(MethodCall ma, Method runmethod) {
|
|
exists(Method runner, int param |
|
|
runner(runner, param, runmethod) and
|
|
viableImpl_v2(ma) = runner and
|
|
result = ma.getArgument(param)
|
|
)
|
|
or
|
|
getRunnerArgument(ma, runmethod).(CastingExpr).getExpr() = result
|
|
or
|
|
pragma[only_bind_out](getRunnerArgument(ma, runmethod))
|
|
.(VarAccess)
|
|
.getVariable()
|
|
.getAnAssignedValue() = result
|
|
}
|
|
|
|
/**
|
|
* Gets a method that can be invoked through a functional interface as an
|
|
* argument to `ma`.
|
|
*/
|
|
Method getRunnerTarget(MethodCall ma) {
|
|
exists(Expr action, Method runmethod | action = getRunnerArgument(ma, runmethod) |
|
|
action.(FunctionalExpr).asMethod().getSourceDeclaration() = result
|
|
or
|
|
action.(ClassInstanceExpr).getAnonymousClass().getAMethod().getSourceDeclaration() = result and
|
|
result.overridesOrInstantiates*(runmethod)
|
|
)
|
|
}
|
|
|
|
import semmle.code.java.dataflow.FlowSummary
|
|
|
|
private predicate mayInvokeCallback(SrcMethod m, int n) {
|
|
m.getParameterType(n).(RefType).getSourceDeclaration() instanceof FunctionalInterface and
|
|
(not m.fromSource() or m.isNative() or m.getFile().getAbsolutePath().matches("%/test/stubs/%"))
|
|
}
|
|
|
|
private class SummarizedCallableWithCallback extends SummarizedCallable::Range {
|
|
private int pos;
|
|
|
|
SummarizedCallableWithCallback() { mayInvokeCallback(this.asCallable(), pos) }
|
|
|
|
override predicate propagatesFlow(
|
|
string input, string output, boolean preservesValue, Provenance p, boolean isExact, string model
|
|
) {
|
|
input = "Argument[" + pos + "]" and
|
|
output = "Argument[" + pos + "].Parameter[-1]" and
|
|
preservesValue = true and
|
|
p = "hq-generated" and
|
|
isExact = true and
|
|
model = "heuristic-callback"
|
|
}
|
|
}
|