Go: Re-factor CSV validation into separate file.

This commit is contained in:
Michael Nebel
2022-08-04 13:27:30 +02:00
parent 9f9129d3c9
commit 37f01fe10e
11 changed files with 122 additions and 105 deletions

View File

@@ -0,0 +1,107 @@
/** Provides a query predicate to check the CSV data for validation errors. */
private import go
private import ExternalFlow
private import internal.FlowSummaryImpl::Private::External
private import internal.AccessPathSyntax
private string getInvalidModelInput() {
exists(string pred, AccessPath input, string part |
sinkModel(_, _, _, _, _, _, input, _) and pred = "sink"
or
summaryModel(_, _, _, _, _, _, input, _, _) and pred = "summary"
|
(
invalidSpecComponent(input, part) and
not part = "" and
not parseArg(part, _)
or
part = input.getToken(_) and
parseParam(part, _)
) and
result = "Unrecognized input specification \"" + part + "\" in " + pred + " model."
)
}
private string getInvalidModelOutput() {
exists(string pred, string output, string part |
sourceModel(_, _, _, _, _, _, output, _) and pred = "source"
or
summaryModel(_, _, _, _, _, _, _, output, _) and pred = "summary"
|
invalidSpecComponent(output, part) and
not part = "" and
not (part = "Parameter" and pred = "source") and
result = "Unrecognized output specification \"" + part + "\" in " + pred + " model."
)
}
private string getInvalidModelKind() { none() }
private string getInvalidModelSubtype() {
exists(string pred, string row, int expect |
sourceModel(row) and expect = 8 and pred = "source"
or
sinkModel(row) and expect = 8 and pred = "sink"
or
summaryModel(row) and expect = 9 and pred = "summary"
|
exists(string b |
b = row.splitAt(";", 2) and
not b = ["true", "false"] and
result = "Invalid boolean \"" + b + "\" in " + pred + " model."
)
)
}
private string getInvalidModelColumnCount() {
exists(string pred, string row, int expect |
sourceModel(row) and expect = 8 and pred = "source"
or
sinkModel(row) and expect = 8 and pred = "sink"
or
summaryModel(row) and expect = 9 and pred = "summary"
|
exists(int cols |
cols = 1 + max(int n | exists(row.splitAt(";", n))) and
cols != expect and
result =
"Wrong number of columns in " + pred + " model row, expected " + expect + ", got " + cols +
"."
)
)
}
private string getInvalidModelSignature() {
exists(string pred, string namespace, string type, string name, string signature, string ext |
sourceModel(namespace, type, _, name, signature, ext, _, _) and pred = "source"
or
sinkModel(namespace, type, _, name, signature, ext, _, _) and pred = "sink"
or
summaryModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "summary"
|
not namespace.regexpMatch("[a-zA-Z0-9_\\./]*") and
result = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
or
not type.regexpMatch("[a-zA-Z0-9_\\$<>]*") and
result = "Dubious type \"" + type + "\" in " + pred + " model."
or
not name.regexpMatch("[a-zA-Z0-9_]*") and
result = "Dubious name \"" + name + "\" in " + pred + " model."
or
not signature.regexpMatch("|\\([a-zA-Z0-9_\\.\\$<>,\\[\\]]*\\)") and
result = "Dubious signature \"" + signature + "\" in " + pred + " model."
or
not ext.regexpMatch("|Annotated") and
result = "Unrecognized extra API graph element \"" + ext + "\" in " + pred + " model."
)
}
/** Holds if some row in a CSV-based flow model appears to contain typos. */
query predicate invalidModelRow(string msg) {
msg =
[
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
getInvalidModelSubtype(), getInvalidModelColumnCount(), getInvalidModelKind()
]
}

View File

@@ -85,12 +85,6 @@ private class BuiltinModel extends SummaryModelCsv {
}
}
private predicate sourceModelCsv(string row) { none() }
private predicate sinkModelCsv(string row) { none() }
private predicate summaryModelCsv(string row) { none() }
/**
* A unit class for adding additional source model rows.
*
@@ -121,20 +115,14 @@ class SummaryModelCsv extends Unit {
abstract predicate row(string row);
}
private predicate sourceModel(string row) {
sourceModelCsv(row) or
any(SourceModelCsv s).row(row)
}
/** Holds if `row` is a source model. */
predicate sourceModel(string row) { any(SourceModelCsv s).row(row) }
private predicate sinkModel(string row) {
sinkModelCsv(row) or
any(SinkModelCsv s).row(row)
}
/** Holds if `row` is a sink model. */
predicate sinkModel(string row) { any(SinkModelCsv s).row(row) }
private predicate summaryModel(string row) {
summaryModelCsv(row) or
any(SummaryModelCsv 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(
@@ -269,84 +257,6 @@ predicate modelCoverage(string package, int pkgs, string kind, string part, int
)
}
/** Provides a query predicate to check the CSV data for validation errors. */
module CsvValidation {
/** Holds if some row in a CSV-based flow model appears to contain typos. */
query predicate invalidModelRow(string msg) {
exists(string pred, string namespace, string type, string name, string signature, string ext |
sourceModel(namespace, type, _, name, signature, ext, _, _) and pred = "source"
or
sinkModel(namespace, type, _, name, signature, ext, _, _) and pred = "sink"
or
summaryModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "summary"
|
not namespace.regexpMatch("[a-zA-Z0-9_\\./]*") and
msg = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
or
not type.regexpMatch("[a-zA-Z0-9_\\$<>]*") and
msg = "Dubious type \"" + type + "\" in " + pred + " model."
or
not name.regexpMatch("[a-zA-Z0-9_]*") and
msg = "Dubious name \"" + name + "\" in " + pred + " model."
or
not signature.regexpMatch("|\\([a-zA-Z0-9_\\.\\$<>,\\[\\]]*\\)") and
msg = "Dubious signature \"" + signature + "\" in " + pred + " model."
or
not ext.regexpMatch("|Annotated") and
msg = "Unrecognized extra API graph element \"" + ext + "\" in " + pred + " model."
)
or
exists(string pred, AccessPath input, string part |
sinkModel(_, _, _, _, _, _, input, _) and pred = "sink"
or
summaryModel(_, _, _, _, _, _, input, _, _) and pred = "summary"
|
(
invalidSpecComponent(input, part) and
not part = "" and
not parseArg(part, _)
or
part = input.getToken(_) and
parseParam(part, _)
) and
msg = "Unrecognized input specification \"" + part + "\" in " + pred + " model."
)
or
exists(string pred, string output, string part |
sourceModel(_, _, _, _, _, _, output, _) and pred = "source"
or
summaryModel(_, _, _, _, _, _, _, output, _) and pred = "summary"
|
invalidSpecComponent(output, part) and
not part = "" and
not (part = "Parameter" and pred = "source") and
msg = "Unrecognized output specification \"" + part + "\" in " + pred + " model."
)
or
exists(string pred, string row, int expect |
sourceModel(row) and expect = 8 and pred = "source"
or
sinkModel(row) and expect = 8 and pred = "sink"
or
summaryModel(row) and expect = 9 and pred = "summary"
|
exists(int cols |
cols = 1 + max(int n | exists(row.splitAt(";", n))) and
cols != expect and
msg =
"Wrong number of columns in " + pred + " model row, expected " + expect + ", got " + cols +
"."
)
or
exists(string b |
b = row.splitAt(";", 2) and
not b = ["true", "false"] and
msg = "Invalid boolean \"" + b + "\" in " + pred + " model."
)
)
}
}
pragma[nomagic]
private predicate elementSpec(
string namespace, string type, boolean subtypes, string name, string signature, string ext

View File

@@ -1,2 +1,2 @@
failures
invalidModelRow
failures

View File

@@ -3,9 +3,9 @@
*/
import go
import semmle.go.dataflow.CsvValidation
import semmle.go.dataflow.ExternalFlow
import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
import CsvValidation
import TestUtilities.InlineFlowTest
class SummaryModelTest extends SummaryModelCsv {

View File

@@ -1,6 +1,6 @@
import go
import semmle.go.dataflow.CsvValidation
import semmle.go.dataflow.ExternalFlow
import CsvValidation
class SinkModelTest extends SinkModelCsv {
override predicate row(string row) {

View File

@@ -1,6 +1,6 @@
import go
import semmle.go.dataflow.ExternalFlow
import CsvValidation
import semmle.go.dataflow.CsvValidation
class SourceModelTest extends SourceModelCsv {
override predicate row(string row) {

View File

@@ -1,7 +1,7 @@
import go
import semmle.go.dataflow.CsvValidation
import semmle.go.dataflow.ExternalFlow
import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
import CsvValidation
class SummaryModelTest extends SummaryModelCsv {
override predicate row(string row) {

View File

@@ -1,2 +1,2 @@
failures
invalidModelRow
failures

View File

@@ -1,6 +1,6 @@
import go
import semmle.go.dataflow.CsvValidation
import semmle.go.dataflow.ExternalFlow
import CsvValidation
import TestUtilities.InlineExpectationsTest
class SummaryModelTest extends SummaryModelCsv {

View File

@@ -1,2 +1,2 @@
failures
invalidModelRow
failures

View File

@@ -1,6 +1,6 @@
import go
import semmle.go.dataflow.CsvValidation
import semmle.go.dataflow.ExternalFlow
import CsvValidation
// import DataFlow::PartialPathGraph
import TestUtilities.InlineExpectationsTest