mirror of
https://github.com/github/codeql.git
synced 2026-04-28 18:25:24 +02:00
C#: Re-factor CSV validation into a separate file.
This commit is contained in:
112
csharp/ql/lib/semmle/code/csharp/dataflow/CsvValidation.qll
Normal file
112
csharp/ql/lib/semmle/code/csharp/dataflow/CsvValidation.qll
Normal file
@@ -0,0 +1,112 @@
|
||||
/** Provides a query predicate to check the CSV data for validation errors. */
|
||||
|
||||
import csharp
|
||||
private import internal.AccessPathSyntax
|
||||
private import internal.FlowSummaryImpl::Private::External
|
||||
private import internal.FlowSummaryImplSpecific
|
||||
private import ExternalFlow
|
||||
|
||||
/** 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,
|
||||
string provenance
|
||||
|
|
||||
sourceModel(namespace, type, _, name, signature, ext, _, _, provenance) and pred = "source"
|
||||
or
|
||||
sinkModel(namespace, type, _, name, signature, ext, _, _, provenance) and pred = "sink"
|
||||
or
|
||||
summaryModel(namespace, type, _, name, signature, ext, _, _, _, provenance) and
|
||||
pred = "summary"
|
||||
or
|
||||
negativeSummaryModel(namespace, type, name, signature, provenance) and
|
||||
ext = "" and
|
||||
pred = "nonesummary"
|
||||
|
|
||||
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 member 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("|Attribute") and
|
||||
msg = "Unrecognized extra API graph element \"" + ext + "\" in " + pred + " model."
|
||||
or
|
||||
not provenance = ["manual", "generated"] and
|
||||
msg = "Unrecognized provenance description \"" + provenance + "\" 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 (part = "Argument" and pred = "sink") 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 = ["Argument", "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 = 9 and pred = "source"
|
||||
or
|
||||
sinkModel(row) and expect = 9 and pred = "sink"
|
||||
or
|
||||
summaryModel(row) and expect = 10 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 +
|
||||
" in " + row + "."
|
||||
)
|
||||
or
|
||||
exists(string b |
|
||||
b = row.splitAt(";", 2) and
|
||||
not b = ["true", "false"] and
|
||||
msg = "Invalid boolean \"" + b + "\" in " + pred + " model."
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(string row, string kind | summaryModel(row) |
|
||||
kind = row.splitAt(";", 8) and
|
||||
not kind = ["taint", "value"] and
|
||||
msg = "Invalid kind \"" + kind + "\" in summary model."
|
||||
)
|
||||
or
|
||||
exists(string row, string kind | sinkModel(row) |
|
||||
kind = row.splitAt(";", 7) and
|
||||
not kind = ["code", "sql", "xss", "remote", "html"] and
|
||||
msg = "Invalid kind \"" + kind + "\" in sink model."
|
||||
)
|
||||
or
|
||||
exists(string row, string kind | sourceModel(row) |
|
||||
kind = row.splitAt(";", 7) and
|
||||
not kind = "local" and
|
||||
msg = "Invalid kind \"" + kind + "\" in source model."
|
||||
)
|
||||
}
|
||||
@@ -174,13 +174,17 @@ class NegativeSummaryModelCsv extends Unit {
|
||||
abstract predicate row(string row);
|
||||
}
|
||||
|
||||
private predicate sourceModel(string row) { 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) { 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) { any(SummaryModelCsv s).row(row) }
|
||||
/** Holds if `row` is a summary model. */
|
||||
predicate summaryModel(string row) { any(SummaryModelCsv s).row(row) }
|
||||
|
||||
private predicate negativeSummaryModel(string row) { any(NegativeSummaryModelCsv s).row(row) }
|
||||
/** Holds if `row` is a negative summary model. */
|
||||
predicate negativeSummaryModel(string row) { any(NegativeSummaryModelCsv s).row(row) }
|
||||
|
||||
/** Holds if a source model exists for the given parameters. */
|
||||
predicate sourceModel(
|
||||
@@ -311,115 +315,6 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
|
||||
)
|
||||
}
|
||||
|
||||
/** 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,
|
||||
string provenance
|
||||
|
|
||||
sourceModel(namespace, type, _, name, signature, ext, _, _, provenance) and pred = "source"
|
||||
or
|
||||
sinkModel(namespace, type, _, name, signature, ext, _, _, provenance) and pred = "sink"
|
||||
or
|
||||
summaryModel(namespace, type, _, name, signature, ext, _, _, _, provenance) and
|
||||
pred = "summary"
|
||||
or
|
||||
negativeSummaryModel(namespace, type, name, signature, provenance) and
|
||||
ext = "" and
|
||||
pred = "nonesummary"
|
||||
|
|
||||
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 member 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("|Attribute") and
|
||||
msg = "Unrecognized extra API graph element \"" + ext + "\" in " + pred + " model."
|
||||
or
|
||||
not provenance = ["manual", "generated"] and
|
||||
msg = "Unrecognized provenance description \"" + provenance + "\" 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 (part = "Argument" and pred = "sink") 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 = ["Argument", "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 = 9 and pred = "source"
|
||||
or
|
||||
sinkModel(row) and expect = 9 and pred = "sink"
|
||||
or
|
||||
summaryModel(row) and expect = 10 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 +
|
||||
" in " + row + "."
|
||||
)
|
||||
or
|
||||
exists(string b |
|
||||
b = row.splitAt(";", 2) and
|
||||
not b = ["true", "false"] and
|
||||
msg = "Invalid boolean \"" + b + "\" in " + pred + " model."
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(string row, string kind | summaryModel(row) |
|
||||
kind = row.splitAt(";", 8) and
|
||||
not kind = ["taint", "value"] and
|
||||
msg = "Invalid kind \"" + kind + "\" in summary model."
|
||||
)
|
||||
or
|
||||
exists(string row, string kind | sinkModel(row) |
|
||||
kind = row.splitAt(";", 7) and
|
||||
not kind = ["code", "sql", "xss", "remote", "html"] and
|
||||
not kind.matches("encryption-%") and
|
||||
msg = "Invalid kind \"" + kind + "\" in sink model."
|
||||
)
|
||||
or
|
||||
exists(string row, string kind | sourceModel(row) |
|
||||
kind = row.splitAt(";", 7) and
|
||||
not kind = ["local", "file"] and
|
||||
msg = "Invalid kind \"" + kind + "\" in source model."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate elementSpec(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
||||
) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
invalidModelRow
|
||||
edges
|
||||
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:10:29:10:32 | access to local variable arg1 : Object |
|
||||
| ExternalFlow.cs:10:29:10:32 | access to local variable arg1 : Object | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes |
|
||||
@@ -151,7 +152,6 @@ nodes
|
||||
| ExternalFlow.cs:196:18:196:40 | call to method MixedFlowArgs | semmle.label | call to method MixedFlowArgs |
|
||||
| ExternalFlow.cs:196:38:196:39 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object |
|
||||
subpaths
|
||||
invalidModelRow
|
||||
#select
|
||||
| ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | $@ | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
| ExternalFlow.cs:18:18:18:24 | access to local variable argOut1 | ExternalFlow.cs:15:29:15:40 | object creation of type Object : Object | ExternalFlow.cs:18:18:18:24 | access to local variable argOut1 | $@ | ExternalFlow.cs:15:29:15:40 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.dataflow.ExternalFlow
|
||||
import DataFlow::PathGraph
|
||||
import CsvValidation
|
||||
import semmle.code.csharp.dataflow.CsvValidation
|
||||
import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
class SummaryModelTest extends SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import csharp
|
||||
import DataFlow
|
||||
import semmle.code.csharp.dataflow.CsvValidation
|
||||
import semmle.code.csharp.dataflow.ExternalFlow
|
||||
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
import CsvValidation
|
||||
|
||||
class SinkModelTest extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import csharp
|
||||
import DataFlow
|
||||
import semmle.code.csharp.dataflow.CsvValidation
|
||||
import semmle.code.csharp.dataflow.ExternalFlow
|
||||
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
import CsvValidation
|
||||
|
||||
class SourceModelTest extends SourceModelCsv {
|
||||
override predicate row(string row) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import csharp
|
||||
import DataFlow
|
||||
import semmle.code.csharp.dataflow.CsvValidation
|
||||
import semmle.code.csharp.dataflow.ExternalFlow
|
||||
import semmle.code.csharp.dataflow.FlowSummary
|
||||
import semmle.code.csharp.dataflow.internal.DataFlowDispatch as DataFlowDispatch
|
||||
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
import CsvValidation
|
||||
|
||||
private class SummaryModelTest extends SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
|
||||
Reference in New Issue
Block a user