diff --git a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll index 544d73fef26..5d63fb1a14e 100644 --- a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll +++ b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll @@ -96,7 +96,21 @@ private import internal.FlowSummaryImpl::Private::External private import codeql.mad.ModelValidation as SharedModelVal private import codeql.mad.static.MaD as SharedMaD -private module MadInput implements SharedMaD::InputSig { } +private module MadInput implements SharedMaD::InputSig { + string namespaceSegmentSeparator() { result = "/" } + + bindingset[p] + string cleanNamespace(string p) { + exists(string noPrefix | + p = fixedVersionPrefix() + noPrefix + or + not p = fixedVersionPrefix() + any(string s) and + noPrefix = p + | + result = noPrefix.regexpReplaceAll(majorVersionSuffixRegex(), "") + ) + } +} private module MaD = SharedMaD::ModelsAsData; @@ -107,78 +121,6 @@ module FlowExtensions = Extensions; /** Gets the prefix for a group of packages. */ private string groupPrefix() { result = "group:" } -bindingset[p] -private string cleanPackage(string p) { - exists(string noPrefix | - p = fixedVersionPrefix() + noPrefix - or - not p = fixedVersionPrefix() + any(string s) and - noPrefix = p - | - result = noPrefix.regexpReplaceAll(majorVersionSuffixRegex(), "") - ) -} - -private predicate relevantPackage(string package) { - exists(string p | package = cleanPackage(p) | - sourceModel(p, _, _, _, _, _, _, _, _, _) or - sinkModel(p, _, _, _, _, _, _, _, _, _) or - summaryModel(p, _, _, _, _, _, _, _, _, _, _) - ) -} - -private predicate packageLink(string shortpkg, string longpkg) { - relevantPackage(shortpkg) and - relevantPackage(longpkg) and - longpkg.prefix(longpkg.indexOf("/")) = shortpkg -} - -private predicate canonicalPackage(string package) { - relevantPackage(package) and not packageLink(_, package) -} - -private predicate canonicalPkgLink(string package, string subpkg) { - canonicalPackage(package) and - (subpkg = package or packageLink(package, subpkg)) -} - -/** - * Holds if MaD framework coverage of `package` is `n` api endpoints of the - * kind `(kind, part)`, and `pkgs` is the number of subpackages of `package` - * which have MaD framework coverage (including `package` itself). - */ -predicate modelCoverage(string package, int pkgs, string kind, string part, int n) { - pkgs = strictcount(string subpkg | canonicalPkgLink(package, subpkg)) and - ( - part = "source" and - n = - strictcount(string subpkg, string type, boolean subtypes, string name, string signature, - string ext, string output, string provenance, string x | - canonicalPkgLink(package, subpkg) and - subpkg = cleanPackage(x) and - sourceModel(x, type, subtypes, name, signature, ext, output, kind, provenance, _) - ) - or - part = "sink" and - n = - strictcount(string subpkg, string type, boolean subtypes, string name, string signature, - string ext, string input, string provenance, string x | - canonicalPkgLink(package, subpkg) and - subpkg = cleanPackage(x) and - sinkModel(x, type, subtypes, name, signature, ext, input, kind, provenance, _) - ) - or - part = "summary" and - n = - strictcount(string subpkg, string type, boolean subtypes, string name, string signature, - string ext, string input, string output, string provenance, string x | - canonicalPkgLink(package, subpkg) and - subpkg = cleanPackage(x) and - summaryModel(x, type, subtypes, name, signature, ext, input, output, kind, provenance, _) - ) - ) -} - /** Provides a query predicate to check the MaD models for validation errors. */ module ModelValidation { private import codeql.dataflow.internal.AccessPathSyntax as AccessPathSyntax diff --git a/shared/mad/codeql/mad/static/MaD.qll b/shared/mad/codeql/mad/static/MaD.qll index fbd12d909ab..dc1b9b77130 100644 --- a/shared/mad/codeql/mad/static/MaD.qll +++ b/shared/mad/codeql/mad/static/MaD.qll @@ -87,8 +87,12 @@ signature module InputSig { none() } - /** Get the separator used between namespace segments. */ + /** Gets the separator used between namespace segments. */ default string namespaceSegmentSeparator() { result = "." } + + /** Gets a cleaned-up version of the namespace for presentation in model coverage. */ + bindingset[ns] + default string cleanNamespace(string ns) { result = ns } } module ModelsAsData { @@ -278,9 +282,11 @@ module ModelsAsData { } private predicate relevantNamespace(string namespace) { - sourceModel(namespace, _, _, _, _, _, _, _, _, _) or - sinkModel(namespace, _, _, _, _, _, _, _, _, _) or - summaryModel(namespace, _, _, _, _, _, _, _, _, _, _) + exists(string ns | namespace = Input::cleanNamespace(ns) | + sourceModel(ns, _, _, _, _, _, _, _, _, _) or + sinkModel(ns, _, _, _, _, _, _, _, _, _) or + summaryModel(ns, _, _, _, _, _, _, _, _, _, _) + ) } private predicate namespaceLink(string shortns, string longns) { @@ -309,25 +315,28 @@ module ModelsAsData { ( part = "source" and n = - strictcount(string subns, string type, boolean subtypes, string name, string signature, - string ext, string output, string provenance | - canonicalNamespaceLink(namespace, subns) and + strictcount(string subns, string subnsClean, string type, boolean subtypes, string name, + string signature, string ext, string output, string provenance | + canonicalNamespaceLink(namespace, subnsClean) and + subnsClean = Input::cleanNamespace(subns) and sourceModel(subns, type, subtypes, name, signature, ext, output, kind, provenance, _) ) or part = "sink" and n = - strictcount(string subns, string type, boolean subtypes, string name, string signature, - string ext, string input, string provenance | - canonicalNamespaceLink(namespace, subns) and + strictcount(string subns, string subnsClean, string type, boolean subtypes, string name, + string signature, string ext, string input, string provenance | + canonicalNamespaceLink(namespace, subnsClean) and + subnsClean = Input::cleanNamespace(subns) and sinkModel(subns, type, subtypes, name, signature, ext, input, kind, provenance, _) ) 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 + strictcount(string subns, string subnsClean, string type, boolean subtypes, string name, + string signature, string ext, string input, string output, string provenance | + canonicalNamespaceLink(namespace, subnsClean) and + subnsClean = Input::cleanNamespace(subns) and summaryModel(subns, type, subtypes, name, signature, ext, input, output, kind, provenance, _) )