mirror of
https://github.com/github/codeql.git
synced 2026-06-22 21:27:04 +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 + "\"]"
)
}
```
86 lines
3.2 KiB
Plaintext
86 lines
3.2 KiB
Plaintext
private import semmle.code.java.dataflow.FlowSummary
|
|
private import semmle.code.java.dataflow.internal.ModelExclusions
|
|
private import TopJdkApis
|
|
|
|
/**
|
|
* Returns the number of `ModelApi`s with Summary MaD models
|
|
* for a given package and provenance.
|
|
*/
|
|
bindingset[package, apiSubset]
|
|
private int getNumMadModeledApis(string package, string provenance, string apiSubset) {
|
|
provenance in ["generated", "manual", "both"] and
|
|
result =
|
|
count(SummarizedCallable::Range sc |
|
|
callableSubset(sc.asCallable(), apiSubset) and
|
|
package = sc.asCallable().getCompilationUnit().getPackage().getName() and
|
|
sc.asCallable() instanceof ModelApi and
|
|
(
|
|
// "auto-only"
|
|
not sc.hasManualModel() and
|
|
any(Provenance p | sc.propagatesFlow(_, _, _, p, _, _)).isGenerated() and
|
|
provenance = "generated"
|
|
or
|
|
sc.hasManualModel() and
|
|
(
|
|
if any(Provenance p | sc.propagatesFlow(_, _, _, p, _, _)).isGenerated()
|
|
then
|
|
// "both"
|
|
provenance = "both"
|
|
else
|
|
// "manual-only"
|
|
provenance = "manual"
|
|
)
|
|
)
|
|
)
|
|
}
|
|
|
|
/** Returns the total number of `ModelApi`s for a given package. */
|
|
private int getNumApis(string package, string apiSubset) {
|
|
result =
|
|
strictcount(ModelApi api |
|
|
callableSubset(api, apiSubset) and
|
|
package = api.getCompilationUnit().getPackage().getName()
|
|
)
|
|
}
|
|
|
|
/** Holds if the given `callable` belongs to the specified `apiSubset`. */
|
|
private predicate callableSubset(Callable callable, string apiSubset) {
|
|
apiSubset = "topJdkApis" and
|
|
callable instanceof TopJdkApi
|
|
or
|
|
apiSubset = "allApis"
|
|
}
|
|
|
|
/**
|
|
* Provides MaD summary model coverage information for the given `package`
|
|
* on the given `apiSubset`.
|
|
*/
|
|
predicate modelCoverageGenVsMan(
|
|
string package, int generatedOnly, int both, int manualOnly, int non, int all, float coverage,
|
|
float generatedCoverage, float manualCoverage, float manualCoveredByGenerated,
|
|
float generatedCoveredByManual, float match, string apiSubset
|
|
) {
|
|
exists(int generated, int manual |
|
|
// count the number of APIs with generated-only, both, and manual-only MaD models for each package
|
|
generatedOnly = getNumMadModeledApis(package, "generated", apiSubset) and
|
|
both = getNumMadModeledApis(package, "both", apiSubset) and
|
|
manualOnly = getNumMadModeledApis(package, "manual", apiSubset) and
|
|
// calculate the total generated and total manual numbers
|
|
generated = generatedOnly + both and
|
|
manual = manualOnly + both and
|
|
// count the total number of `ModelApi`s for each package
|
|
all = getNumApis(package, apiSubset) and
|
|
non = all - (generatedOnly + both + manualOnly) and
|
|
// Proportion of coverage
|
|
coverage = (generatedOnly + both + manualOnly).(float) / all and
|
|
generatedCoverage = generated.(float) / all and
|
|
manualCoverage = manual.(float) / all and
|
|
// Proportion of manual models covered by generated ones
|
|
manualCoveredByGenerated = both.(float) / (both + manualOnly) and
|
|
// Proportion of generated models covered by manual ones
|
|
generatedCoveredByManual = both.(float) / (both + generatedOnly) and
|
|
// Proportion of data points that match
|
|
match = (both.(float) + non) / all
|
|
)
|
|
}
|