From 663d091776bb16c16732eba041a59a77691f8bbd Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 15 Nov 2022 10:33:13 +0100 Subject: [PATCH] Java: Invert dependencies and use the extensible predicates. --- .../code/java/dataflow/ExternalFlow.qll | 121 +++++++++++------- 1 file changed, 77 insertions(+), 44 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index 6bd13135c1b..520890146a0 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -161,41 +161,57 @@ private module Frameworks { } /** + * DEPRECATED: Define source models as data extensions instead. + * * A unit class for adding additional source model rows. * * Extend this class to add additional source definitions. */ -class SourceModelCsv extends Unit { +class SourceModelCsv = SourceModelCsvInternal; + +private class SourceModelCsvInternal extends Unit { /** Holds if `row` specifies a source definition. */ abstract predicate row(string row); } /** + * DEPRECATED: Define sink models as data extensions instead. + * * A unit class for adding additional sink model rows. * * Extend this class to add additional sink definitions. */ -class SinkModelCsv extends Unit { +class SinkModelCsv = SinkModelCsvInternal; + +private class SinkModelCsvInternal extends Unit { /** Holds if `row` specifies a sink definition. */ abstract predicate row(string row); } /** + * DEPRECATED: Define summary models as data extensions instead. + * * A unit class for adding additional summary model rows. * * Extend this class to add additional flow summary definitions. */ -class SummaryModelCsv extends Unit { +class SummaryModelCsv = SummaryModelCsvInternal; + +private class SummaryModelCsvInternal extends Unit { /** Holds if `row` specifies a summary definition. */ abstract predicate row(string row); } /** - * A unit class for adding negative summary model rows. + * DEPRECATED: Define negative summary models as data extensions instead. * - * Extend this class to add additional flow summary definitions. + * A unit class for adding additional negative summary model rows. + * + * Extend this class to add additional negative summary definitions. */ -class NegativeSummaryModelCsv extends Unit { +class NegativeSummaryModelCsv = NegativeSummaryModelCsvInternal; + +private class NegativeSummaryModelCsvInternal extends Unit { /** Holds if `row` specifies a negative summary definition. */ abstract predicate row(string row); } @@ -420,17 +436,15 @@ private class SummaryModelCsvBase extends SummaryModelCsv { } } -/** Holds if `row` is a source model. */ -predicate sourceModel(string row) { any(SourceModelCsv s).row(row) } +private predicate sourceModelInternal(string row) { any(SourceModelCsvInternal s).row(row) } -/** Holds if `row` is a sink model. */ -predicate sinkModel(string row) { any(SinkModelCsv s).row(row) } +private predicate summaryModelInternal(string row) { any(SummaryModelCsvInternal s).row(row) } -/** Holds if `row` is a summary model. */ -predicate summaryModel(string row) { any(SummaryModelCsv s).row(row) } +private predicate sinkModelInternal(string row) { any(SinkModelCsvInternal s).row(row) } -/** Holds if `row` is negative summary model. */ -predicate negativeSummaryModel(string row) { any(NegativeSummaryModelCsv s).row(row) } +private predicate negativeSummaryModelInternal(string row) { + any(NegativeSummaryModelCsvInternal s).row(row) +} /** * Holds if a source model exists for the given parameters. @@ -446,7 +460,7 @@ predicate sourceModel( string output, string kind, string provenance ) { exists(string row | - sourceModel(row) and + sourceModelInternal(row) and row.splitAt(";", 0) = package and row.splitAt(";", 1) = type and row.splitAt(";", 2) = subtypes.toString() and @@ -458,6 +472,8 @@ predicate sourceModel( row.splitAt(";", 7) = kind and row.splitAt(";", 8) = provenance ) + or + extSourceModel(package, type, subtypes, name, signature, ext, output, kind, provenance) } /** Holds if a sink model exists for the given parameters. */ @@ -472,7 +488,7 @@ predicate sinkModel( string input, string kind, string provenance ) { exists(string row | - sinkModel(row) and + sinkModelInternal(row) and row.splitAt(";", 0) = package and row.splitAt(";", 1) = type and row.splitAt(";", 2) = subtypes.toString() and @@ -484,6 +500,8 @@ predicate sinkModel( row.splitAt(";", 7) = kind and row.splitAt(";", 8) = provenance ) + or + extSinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance) } /** Holds if a summary model exists for the given parameters. */ @@ -497,26 +515,42 @@ predicate summaryModel( string package, string type, boolean subtypes, string name, string signature, string ext, string input, string output, string kind, string provenance ) { - summaryModel(package, type, subtypes, name, signature, ext, input, output, kind, provenance, _) + exists(string row | + summaryModelInternal(row) and + row.splitAt(";", 0) = package 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 + row.splitAt(";", 9) = provenance + ) + or + extSummaryModel(package, type, subtypes, name, signature, ext, input, output, kind, provenance) } /** Holds if a summary model `row` exists for the given parameters. */ +bindingset[row] predicate summaryModel( string package, string type, boolean subtypes, string name, string signature, string ext, string input, string output, string kind, string provenance, string row ) { - summaryModel(row) and - row.splitAt(";", 0) = package 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 - row.splitAt(";", 9) = provenance + summaryModel(package, type, subtypes, name, signature, ext, input, output, kind, provenance) and + row = + package + ";" // + + type + ";" // + + subtypes.toString() + ";" // + + name + ";" // + + signature + ";" // + + ext + ";" // + + input + ";" // + + output + ";" // + + kind + ";" // + + provenance } /** Holds if a summary model exists indicating there is no flow for the given parameters. */ @@ -529,19 +563,21 @@ predicate negativeSummaryModel( string package, string type, string name, string signature, string provenance ) { exists(string row | - negativeSummaryModel(row) and + negativeSummaryModelInternal(row) and row.splitAt(";", 0) = package and row.splitAt(";", 1) = type and row.splitAt(";", 2) = name and row.splitAt(";", 3) = signature and row.splitAt(";", 4) = provenance ) + or + extNegativeSummaryModel(package, type, name, signature, provenance) } private predicate relevantPackage(string package) { sourceModel(package, _, _, _, _, _, _, _, _) or sinkModel(package, _, _, _, _, _, _, _, _) or - summaryModel(package, _, _, _, _, _, _, _, _, _, _) + summaryModel(package, _, _, _, _, _, _, _, _, _) } private predicate packageLink(string shortpkg, string longpkg) { @@ -627,14 +663,12 @@ module ModelValidation { } private string getInvalidModelKind() { - exists(string row, string kind | summaryModel(row) | - kind = row.splitAt(";", 8) and + exists(string kind | summaryModel(_, _, _, _, _, _, _, _, kind, _) | not kind = ["taint", "value"] and result = "Invalid kind \"" + kind + "\" in summary model." ) or - exists(string row, string kind | sinkModel(row) | - kind = row.splitAt(";", 7) and + exists(string kind | sinkModel(_, _, _, _, _, _, _, kind, _) | not kind = [ "open-url", "jndi-injection", "ldap", "sql", "jdbc-url", "logging", "mvel", "xpath", @@ -648,8 +682,7 @@ module ModelValidation { result = "Invalid kind \"" + kind + "\" in sink model." ) or - exists(string row, string kind | sourceModel(row) | - kind = row.splitAt(";", 7) and + exists(string kind | sourceModel(_, _, _, _, _, _, _, kind, _) | not kind = ["remote", "contentprovider", "android-widget", "android-external-storage-dir"] and not kind.matches("qltest%") and result = "Invalid kind \"" + kind + "\" in source model." @@ -658,11 +691,11 @@ module ModelValidation { private string getInvalidModelSubtype() { exists(string pred, string row | - sourceModel(row) and pred = "source" + sourceModelInternal(row) and pred = "source" or - sinkModel(row) and pred = "sink" + sinkModelInternal(row) and pred = "sink" or - summaryModel(row) and pred = "summary" + summaryModelInternal(row) and pred = "summary" | exists(string b | b = row.splitAt(";", 2) and @@ -674,13 +707,13 @@ module ModelValidation { private string getInvalidModelColumnCount() { exists(string pred, string row, int expect | - sourceModel(row) and expect = 9 and pred = "source" + sourceModelInternal(row) and expect = 9 and pred = "source" or - sinkModel(row) and expect = 9 and pred = "sink" + sinkModelInternal(row) and expect = 9 and pred = "sink" or - summaryModel(row) and expect = 10 and pred = "summary" + summaryModelInternal(row) and expect = 10 and pred = "summary" or - negativeSummaryModel(row) and expect = 5 and pred = "negative summary" + negativeSummaryModelInternal(row) and expect = 5 and pred = "negative summary" | exists(int cols | cols = 1 + max(int n | exists(row.splitAt(";", n))) and