mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Go: Re-factor CSV validation into separate file.
This commit is contained in:
107
go/ql/lib/semmle/go/dataflow/CsvValidation.qll
Normal file
107
go/ql/lib/semmle/go/dataflow/CsvValidation.qll
Normal 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()
|
||||
]
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
failures
|
||||
invalidModelRow
|
||||
failures
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
failures
|
||||
invalidModelRow
|
||||
failures
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
failures
|
||||
invalidModelRow
|
||||
failures
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import go
|
||||
import semmle.go.dataflow.CsvValidation
|
||||
import semmle.go.dataflow.ExternalFlow
|
||||
import CsvValidation
|
||||
// import DataFlow::PartialPathGraph
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
|
||||
Reference in New Issue
Block a user