Merge pull request #21011 from aschackmull/mad/shared-externalflow

Java/C++/Go/C#: Share parts of ExternalFlow.qll
This commit is contained in:
Tom Hvitved
2025-12-15 20:27:04 +01:00
committed by GitHub
15 changed files with 636 additions and 639 deletions

View File

@@ -9,6 +9,14 @@ extensions:
pack: codeql/cpp-all
extensible: sinkModel
data: []
- addsTo:
pack: codeql/cpp-all
extensible: barrierModel
data: []
- addsTo:
pack: codeql/cpp-all
extensible: barrierGuardModel
data: []
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel

View File

@@ -101,9 +101,10 @@ private import internal.FlowSummaryImpl
private import internal.FlowSummaryImpl::Public
private import internal.FlowSummaryImpl::Private
private import internal.FlowSummaryImpl::Private::External
private import internal.ExternalFlowExtensions as Extensions
private import internal.ExternalFlowExtensions::Extensions as Extensions
private import codeql.mad.ModelValidation as SharedModelVal
private import codeql.util.Unit
private import codeql.mad.static.ModelsAsData as SharedMaD
/**
* A unit class for adding additional source model rows.
@@ -144,134 +145,81 @@ predicate sinkModel(string row) { any(SinkModelCsv s).row(row) }
/** Holds if `row` is a summary model. */
predicate summaryModel(string row) { any(SummaryModelCsv s).row(row) }
/** Holds if a source model exists for the given parameters. */
predicate sourceModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string output, string kind, string provenance, string model
) {
exists(string row |
sourceModel(row) and
row.splitAt(";", 0) = namespace and
row.splitAt(";", 1) = type and
row.splitAt(";", 2) = subtypes.toString() and
subtypes = [true, false] and
row.splitAt(";", 3) = name and
row.splitAt(";", 4) = signature and
row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = output and
row.splitAt(";", 7) = kind
) and
provenance = "manual" and
model = ""
or
exists(QlBuiltins::ExtensionId madId |
Extensions::sourceModel(namespace, type, subtypes, name, signature, ext, output, kind,
provenance, madId) and
model = "MaD:" + madId.toString()
)
private module MadInput implements SharedMaD::InputSig {
/** Holds if a source model exists for the given parameters. */
predicate additionalSourceModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string output, string kind, string provenance, string model
) {
exists(string row |
sourceModel(row) and
row.splitAt(";", 0) = namespace and
row.splitAt(";", 1) = type and
row.splitAt(";", 2) = subtypes.toString() and
subtypes = [true, false] and
row.splitAt(";", 3) = name and
row.splitAt(";", 4) = signature and
row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = output and
row.splitAt(";", 7) = kind
) and
provenance = "manual" and
model = ""
}
/** Holds if a sink model exists for the given parameters. */
predicate additionalSinkModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string kind, string provenance, string model
) {
exists(string row |
sinkModel(row) and
row.splitAt(";", 0) = namespace and
row.splitAt(";", 1) = type and
row.splitAt(";", 2) = subtypes.toString() and
subtypes = [true, false] and
row.splitAt(";", 3) = name and
row.splitAt(";", 4) = signature and
row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = input and
row.splitAt(";", 7) = kind
) and
provenance = "manual" and
model = ""
}
/**
* Holds if a summary model exists for the given parameters.
*
* This predicate does not expand `@` to `*`s.
*/
predicate additionalSummaryModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string output, string kind, string provenance, string model
) {
exists(string row |
summaryModel(row) and
row.splitAt(";", 0) = namespace and
row.splitAt(";", 1) = type and
row.splitAt(";", 2) = subtypes.toString() and
subtypes = [true, false] and
row.splitAt(";", 3) = name and
row.splitAt(";", 4) = signature and
row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = input and
row.splitAt(";", 7) = output and
row.splitAt(";", 8) = kind
) and
provenance = "manual" and
model = ""
}
string namespaceSegmentSeparator() { result = "::" }
}
/** Holds if a sink model exists for the given parameters. */
predicate sinkModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string kind, string provenance, string model
) {
exists(string row |
sinkModel(row) and
row.splitAt(";", 0) = namespace and
row.splitAt(";", 1) = type and
row.splitAt(";", 2) = subtypes.toString() and
subtypes = [true, false] and
row.splitAt(";", 3) = name and
row.splitAt(";", 4) = signature and
row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = input and
row.splitAt(";", 7) = kind
) and
provenance = "manual" and
model = ""
or
exists(QlBuiltins::ExtensionId madId |
Extensions::sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance,
madId) and
model = "MaD:" + madId.toString()
)
}
private module MaD = SharedMaD::ModelsAsData<Extensions, MadInput>;
/**
* Holds if a summary model exists for the given parameters.
*
* This predicate does not expand `@` to `*`s.
*/
private predicate summaryModel0(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string output, string kind, string provenance, string model
) {
exists(string row |
summaryModel(row) and
row.splitAt(";", 0) = namespace and
row.splitAt(";", 1) = type and
row.splitAt(";", 2) = subtypes.toString() and
subtypes = [true, false] and
row.splitAt(";", 3) = name and
row.splitAt(";", 4) = signature and
row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = input and
row.splitAt(";", 7) = output and
row.splitAt(";", 8) = kind
) and
provenance = "manual" and
model = ""
or
exists(QlBuiltins::ExtensionId madId |
Extensions::summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind,
provenance, madId) and
model = "MaD:" + madId.toString()
)
}
/**
* Holds if the given extension tuple `madId` should pretty-print as `model`.
*
* This predicate should only be used in tests.
*/
predicate interpretModelForTest(QlBuiltins::ExtensionId madId, string model) {
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string output, string kind, string provenance
|
Extensions::sourceModel(namespace, type, subtypes, name, signature, ext, output, kind,
provenance, madId)
|
model =
"Source: " + namespace + "; " + type + "; " + subtypes + "; " + name + "; " + signature + "; "
+ ext + "; " + output + "; " + kind + "; " + provenance
)
or
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string kind, string provenance
|
Extensions::sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance,
madId)
|
model =
"Sink: " + namespace + "; " + type + "; " + subtypes + "; " + name + "; " + signature + "; " +
ext + "; " + input + "; " + kind + "; " + provenance
)
or
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string output, string kind, string provenance
|
Extensions::summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind,
provenance, madId)
|
model =
"Summary: " + namespace + "; " + type + "; " + subtypes + "; " + name + "; " + signature +
"; " + ext + "; " + input + "; " + output + "; " + kind + "; " + provenance
)
}
import MaD
/**
* Holds if `input` is `input0`, but with all occurrences of `@` replaced
@@ -294,69 +242,13 @@ predicate summaryModel(
string input, string output, string kind, string provenance, string model
) {
exists(string input0, string output0 |
summaryModel0(namespace, type, subtypes, name, signature, ext, input0, output0, kind,
MaD::summaryModel(namespace, type, subtypes, name, signature, ext, input0, output0, kind,
provenance, model) and
expandInputAndOutput(input0, input, output0, output,
[0 .. Private::getMaxElementContentIndirectionIndex() - 1])
)
}
private predicate relevantNamespace(string namespace) {
sourceModel(namespace, _, _, _, _, _, _, _, _, _) or
sinkModel(namespace, _, _, _, _, _, _, _, _, _) or
summaryModel(namespace, _, _, _, _, _, _, _, _, _, _)
}
private predicate namespaceLink(string shortns, string longns) {
relevantNamespace(shortns) and
relevantNamespace(longns) and
longns.prefix(longns.indexOf("::")) = shortns
}
private predicate canonicalNamespace(string namespace) {
relevantNamespace(namespace) and not namespaceLink(_, namespace)
}
private predicate canonicalNamespaceLink(string namespace, string subns) {
canonicalNamespace(namespace) and
(subns = namespace or namespaceLink(namespace, subns))
}
/**
* Holds if MaD framework coverage of `namespace` is `n` api endpoints of the
* kind `(kind, part)`, and `namespaces` is the number of subnamespaces of
* `namespace` which have MaD framework coverage (including `namespace`
* itself).
*/
predicate modelCoverage(string namespace, int namespaces, string kind, string part, int n) {
namespaces = strictcount(string subns | canonicalNamespaceLink(namespace, subns)) and
(
part = "source" and
n =
strictcount(string subns, string type, boolean subtypes, string name, string signature,
string ext, string output, string provenance, string model |
canonicalNamespaceLink(namespace, subns) and
sourceModel(subns, type, subtypes, name, signature, ext, output, kind, provenance, model)
)
or
part = "sink" and
n =
strictcount(string subns, string type, boolean subtypes, string name, string signature,
string ext, string input, string provenance, string model |
canonicalNamespaceLink(namespace, subns) and
sinkModel(subns, type, subtypes, name, signature, ext, input, kind, provenance, model)
)
or
part = "summary" and
n =
strictcount(string subns, string type, boolean subtypes, string name, string signature,
string ext, string input, string output, string provenance |
canonicalNamespaceLink(namespace, subns) and
summaryModel(subns, type, subtypes, name, signature, ext, input, output, kind, provenance, _)
)
)
}
/** Provides a query predicate to check the CSV data for validation errors. */
module CsvValidation {
private string getInvalidModelInput() {

View File

@@ -2,6 +2,8 @@
* This module provides extensible predicates for defining MaD models.
*/
private import codeql.mad.static.ModelsAsData as SharedMaD
/**
* Holds if an external source model exists for the given parameters.
*/
@@ -18,6 +20,22 @@ extensible predicate sinkModel(
string input, string kind, string provenance, QlBuiltins::ExtensionId madId
);
/**
* Holds if a barrier model exists for the given parameters.
*/
extensible predicate barrierModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string output, string kind, string provenance, QlBuiltins::ExtensionId madId
);
/**
* Holds if a barrier guard model exists for the given parameters.
*/
extensible predicate barrierGuardModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string acceptingvalue, string kind, string provenance, QlBuiltins::ExtensionId madId
);
/**
* Holds if an external summary model exists for the given parameters.
*/
@@ -25,3 +43,16 @@ extensible predicate summaryModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string output, string kind, string provenance, QlBuiltins::ExtensionId madId
);
/**
* Holds if a neutral model exists for the given parameters.
*/
extensible predicate neutralModel(
string namespace, string type, string name, string signature, string kind, string provenance
);
module Extensions implements SharedMaD::ExtensionsSig {
import ExternalFlowExtensions
predicate namespaceGrouping(string group, string namespace) { none() }
}