Skip to content

Commit 24ba5cc

Browse files
authored
Merge pull request #9025 from michaelnebel/csharp/generatedrefactor
C#: Provenance column in Models as Data CSV format.
2 parents 2b892bc + b4cb1e5 commit 24ba5cc

File tree

190 files changed

+44588
-44474
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

190 files changed

+44588
-44474
lines changed

csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@
6969
* sources "remote" indicates a default remote flow source, and for summaries
7070
* "taint" indicates a default additional taint step and "value" indicates a
7171
* globally applicable value-preserving step.
72+
* 9. The `provenance` column is a tag to indicate the origin of the summary.
73+
* There are two supported values: "generated" and "manual". "generated" means that
74+
* the model has been emitted by the model generator tool and "manual" means
75+
* that the model has been written by hand. This information is used in a heuristic
76+
* for dataflow analysis to determine, if a model or source code should be used for
77+
* determining flow.
7278
*/
7379

7480
import csharp
@@ -163,17 +169,10 @@ private predicate sinkModel(string row) { any(SinkModelCsv s).row(row) }
163169

164170
private predicate summaryModel(string row) { any(SummaryModelCsv s).row(row) }
165171

166-
bindingset[input]
167-
private predicate getKind(string input, string kind, boolean generated) {
168-
input.splitAt(":", 0) = "generated" and kind = input.splitAt(":", 1) and generated = true
169-
or
170-
not input.matches("%:%") and kind = input and generated = false
171-
}
172-
173172
/** Holds if a source model exists for the given parameters. */
174173
predicate sourceModel(
175174
string namespace, string type, boolean subtypes, string name, string signature, string ext,
176-
string output, string kind, boolean generated
175+
string output, string kind, string provenance
177176
) {
178177
exists(string row |
179178
sourceModel(row) and
@@ -185,14 +184,15 @@ predicate sourceModel(
185184
row.splitAt(";", 4) = signature and
186185
row.splitAt(";", 5) = ext and
187186
row.splitAt(";", 6) = output and
188-
exists(string k | row.splitAt(";", 7) = k and getKind(k, kind, generated))
187+
row.splitAt(";", 7) = kind and
188+
row.splitAt(";", 8) = provenance
189189
)
190190
}
191191

192192
/** Holds if a sink model exists for the given parameters. */
193193
predicate sinkModel(
194194
string namespace, string type, boolean subtypes, string name, string signature, string ext,
195-
string input, string kind, boolean generated
195+
string input, string kind, string provenance
196196
) {
197197
exists(string row |
198198
sinkModel(row) and
@@ -204,14 +204,15 @@ predicate sinkModel(
204204
row.splitAt(";", 4) = signature and
205205
row.splitAt(";", 5) = ext and
206206
row.splitAt(";", 6) = input and
207-
exists(string k | row.splitAt(";", 7) = k and getKind(k, kind, generated))
207+
row.splitAt(";", 7) = kind and
208+
row.splitAt(";", 8) = provenance
208209
)
209210
}
210211

211212
/** Holds if a summary model exists for the given parameters. */
212213
predicate summaryModel(
213214
string namespace, string type, boolean subtypes, string name, string signature, string ext,
214-
string input, string output, string kind, boolean generated
215+
string input, string output, string kind, string provenance
215216
) {
216217
exists(string row |
217218
summaryModel(row) and
@@ -224,7 +225,8 @@ predicate summaryModel(
224225
row.splitAt(";", 5) = ext and
225226
row.splitAt(";", 6) = input and
226227
row.splitAt(";", 7) = output and
227-
exists(string k | row.splitAt(";", 8) = k and getKind(k, kind, generated))
228+
row.splitAt(";", 8) = kind and
229+
row.splitAt(";", 9) = provenance
228230
)
229231
}
230232

@@ -259,25 +261,25 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
259261
part = "source" and
260262
n =
261263
strictcount(string subns, string type, boolean subtypes, string name, string signature,
262-
string ext, string output, boolean generated |
264+
string ext, string output, string provenance |
263265
canonicalNamespaceLink(namespace, subns) and
264-
sourceModel(subns, type, subtypes, name, signature, ext, output, kind, generated)
266+
sourceModel(subns, type, subtypes, name, signature, ext, output, kind, provenance)
265267
)
266268
or
267269
part = "sink" and
268270
n =
269271
strictcount(string subns, string type, boolean subtypes, string name, string signature,
270-
string ext, string input, boolean generated |
272+
string ext, string input, string provenance |
271273
canonicalNamespaceLink(namespace, subns) and
272-
sinkModel(subns, type, subtypes, name, signature, ext, input, kind, generated)
274+
sinkModel(subns, type, subtypes, name, signature, ext, input, kind, provenance)
273275
)
274276
or
275277
part = "summary" and
276278
n =
277279
strictcount(string subns, string type, boolean subtypes, string name, string signature,
278-
string ext, string input, string output, boolean generated |
280+
string ext, string input, string output, string provenance |
279281
canonicalNamespaceLink(namespace, subns) and
280-
summaryModel(subns, type, subtypes, name, signature, ext, input, output, kind, generated)
282+
summaryModel(subns, type, subtypes, name, signature, ext, input, output, kind, provenance)
281283
)
282284
)
283285
}
@@ -286,12 +288,16 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
286288
module CsvValidation {
287289
/** Holds if some row in a CSV-based flow model appears to contain typos. */
288290
query predicate invalidModelRow(string msg) {
289-
exists(string pred, string namespace, string type, string name, string signature, string ext |
290-
sourceModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "source"
291+
exists(
292+
string pred, string namespace, string type, string name, string signature, string ext,
293+
string provenance
294+
|
295+
sourceModel(namespace, type, _, name, signature, ext, _, _, provenance) and pred = "source"
291296
or
292-
sinkModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "sink"
297+
sinkModel(namespace, type, _, name, signature, ext, _, _, provenance) and pred = "sink"
293298
or
294-
summaryModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "summary"
299+
summaryModel(namespace, type, _, name, signature, ext, _, _, _, provenance) and
300+
pred = "summary"
295301
|
296302
not namespace.regexpMatch("[a-zA-Z0-9_\\.]+") and
297303
msg = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
@@ -307,6 +313,9 @@ module CsvValidation {
307313
or
308314
not ext.regexpMatch("|Attribute") and
309315
msg = "Unrecognized extra API graph element \"" + ext + "\" in " + pred + " model."
316+
or
317+
not provenance = ["manual", "generated"] and
318+
msg = "Unrecognized provenance description \"" + provenance + "\" in " + pred + " model."
310319
)
311320
or
312321
exists(string pred, AccessPath input, string part |
@@ -338,18 +347,18 @@ module CsvValidation {
338347
)
339348
or
340349
exists(string pred, string row, int expect |
341-
sourceModel(row) and expect = 8 and pred = "source"
350+
sourceModel(row) and expect = 9 and pred = "source"
342351
or
343-
sinkModel(row) and expect = 8 and pred = "sink"
352+
sinkModel(row) and expect = 9 and pred = "sink"
344353
or
345-
summaryModel(row) and expect = 9 and pred = "summary"
354+
summaryModel(row) and expect = 10 and pred = "summary"
346355
|
347356
exists(int cols |
348357
cols = 1 + max(int n | exists(row.splitAt(";", n))) and
349358
cols != expect and
350359
msg =
351360
"Wrong number of columns in " + pred + " model row, expected " + expect + ", got " + cols +
352-
"."
361+
" in " + row + "."
353362
)
354363
or
355364
exists(string b |
@@ -359,23 +368,20 @@ module CsvValidation {
359368
)
360369
)
361370
or
362-
exists(string row, string k, string kind | summaryModel(row) |
363-
k = row.splitAt(";", 8) and
364-
getKind(k, kind, _) and
371+
exists(string row, string kind | summaryModel(row) |
372+
kind = row.splitAt(";", 8) and
365373
not kind = ["taint", "value"] and
366374
msg = "Invalid kind \"" + kind + "\" in summary model."
367375
)
368376
or
369-
exists(string row, string k, string kind | sinkModel(row) |
370-
k = row.splitAt(";", 7) and
371-
getKind(k, kind, _) and
377+
exists(string row, string kind | sinkModel(row) |
378+
kind = row.splitAt(";", 7) and
372379
not kind = ["code", "sql", "xss", "remote", "html"] and
373380
msg = "Invalid kind \"" + kind + "\" in sink model."
374381
)
375382
or
376-
exists(string row, string k, string kind | sourceModel(row) |
377-
k = row.splitAt(";", 7) and
378-
getKind(k, kind, _) and
383+
exists(string row, string kind | sourceModel(row) |
384+
kind = row.splitAt(";", 7) and
379385
not kind = "local" and
380386
msg = "Invalid kind \"" + kind + "\" in source model."
381387
)

csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,13 +1116,13 @@ module Private {
11161116
preservesValue = false and result = "taint"
11171117
}
11181118

1119-
private string renderGenerated(RelevantSummarizedCallable c) {
1120-
if c.(SummarizedCallable).isAutoGenerated() then result = "generated:" else result = ""
1119+
private string renderProvenance(RelevantSummarizedCallable c) {
1120+
if c.(SummarizedCallable).isAutoGenerated() then result = "generated" else result = "manual"
11211121
}
11221122

11231123
/**
11241124
* A query predicate for outputting flow summaries in semi-colon separated format in QL tests.
1125-
* The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;(generated:)?kind",
1125+
* The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance"",
11261126
* ext is hardcoded to empty.
11271127
*/
11281128
query predicate summary(string csv) {
@@ -1133,7 +1133,7 @@ module Private {
11331133
c.relevantSummary(input, output, preservesValue) and
11341134
csv =
11351135
c.getCallableCsv() + getComponentStackCsv(input) + ";" + getComponentStackCsv(output) +
1136-
";" + renderGenerated(c) + renderKind(preservesValue)
1136+
";" + renderKind(preservesValue) + ";" + renderProvenance(c)
11371137
)
11381138
}
11391139
}

csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImplSpecific.qll

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,16 +91,25 @@ DataFlowType getCallbackReturnType(DataFlowType t, ReturnKind rk) {
9191
)
9292
}
9393

94+
bindingset[provenance]
95+
private boolean isGenerated(string provenance) {
96+
provenance = "generated" and result = true
97+
or
98+
provenance != "generated" and result = false
99+
}
100+
94101
/**
95102
* Holds if an external flow summary exists for `c` with input specification
96103
* `input`, output specification `output`, kind `kind`, and a flag `generated`
97104
* stating whether the summary is autogenerated.
98105
*/
99106
predicate summaryElement(Callable c, string input, string output, string kind, boolean generated) {
100107
exists(
101-
string namespace, string type, boolean subtypes, string name, string signature, string ext
108+
string namespace, string type, boolean subtypes, string name, string signature, string ext,
109+
string provenance
102110
|
103-
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, generated) and
111+
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance) and
112+
generated = isGenerated(provenance) and
104113
c = interpretElement(namespace, type, subtypes, name, signature, ext)
105114
)
106115
}
@@ -112,9 +121,11 @@ predicate summaryElement(Callable c, string input, string output, string kind, b
112121
*/
113122
predicate sourceElement(Element e, string output, string kind, boolean generated) {
114123
exists(
115-
string namespace, string type, boolean subtypes, string name, string signature, string ext
124+
string namespace, string type, boolean subtypes, string name, string signature, string ext,
125+
string provenance
116126
|
117-
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, generated) and
127+
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance) and
128+
generated = isGenerated(provenance) and
118129
e = interpretElement(namespace, type, subtypes, name, signature, ext)
119130
)
120131
}
@@ -126,9 +137,11 @@ predicate sourceElement(Element e, string output, string kind, boolean generated
126137
*/
127138
predicate sinkElement(Element e, string input, string kind, boolean generated) {
128139
exists(
129-
string namespace, string type, boolean subtypes, string name, string signature, string ext
140+
string namespace, string type, boolean subtypes, string name, string signature, string ext,
141+
string provenance
130142
|
131-
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, generated) and
143+
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance) and
144+
generated = isGenerated(provenance) and
132145
e = interpretElement(namespace, type, subtypes, name, signature, ext)
133146
)
134147
}

csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ module EntityFramework {
240240
private class SystemDataEntityDbSetSqlQuerySinkModelCsv extends SinkModelCsv {
241241
override predicate row(string row) {
242242
row =
243-
"System.Data.Entity;DbSet;false;SqlQuery;(System.String,System.Object[]);;Argument[0];sql"
243+
"System.Data.Entity;DbSet;false;SqlQuery;(System.String,System.Object[]);;Argument[0];sql;manual"
244244
}
245245
}
246246

@@ -249,14 +249,14 @@ module EntityFramework {
249249
override predicate row(string row) {
250250
row =
251251
[
252-
"System.Data.Entity;Database;false;SqlQuery;(System.Type,System.String,System.Object[]);;Argument[1];sql",
253-
"System.Data.Entity;Database;false;SqlQuery<>;(System.String,System.Object[]);;Argument[0];sql",
254-
"System.Data.Entity;Database;false;ExecuteSqlCommand;(System.String,System.Object[]);;Argument[0];sql",
255-
"System.Data.Entity;Database;false;ExecuteSqlCommand;(System.Data.Entity.TransactionalBehavior,System.String,System.Object[]);;Argument[1];sql",
256-
"System.Data.Entity;Database;false;ExecuteSqlCommandAsync;(System.Data.Entity.TransactionalBehavior,System.String,System.Threading.CancellationToken,System.Object[]);;Argument[1];sql",
257-
"System.Data.Entity;Database;false;ExecuteSqlCommandAsync;(System.String,System.Threading.CancellationToken,System.Object[]);;Argument[0];sql",
258-
"System.Data.Entity;Database;false;ExecuteSqlCommandAsync;(System.String,System.Object[]);;Argument[0];sql",
259-
"System.Data.Entity;Database;false;ExecuteSqlCommandAsync;(System.Data.Entity.TransactionalBehavior,System.String,System.Object[]);;Argument[1];sql"
252+
"System.Data.Entity;Database;false;SqlQuery;(System.Type,System.String,System.Object[]);;Argument[1];sql;manual",
253+
"System.Data.Entity;Database;false;SqlQuery<>;(System.String,System.Object[]);;Argument[0];sql;manual",
254+
"System.Data.Entity;Database;false;ExecuteSqlCommand;(System.String,System.Object[]);;Argument[0];sql;manual",
255+
"System.Data.Entity;Database;false;ExecuteSqlCommand;(System.Data.Entity.TransactionalBehavior,System.String,System.Object[]);;Argument[1];sql;manual",
256+
"System.Data.Entity;Database;false;ExecuteSqlCommandAsync;(System.Data.Entity.TransactionalBehavior,System.String,System.Threading.CancellationToken,System.Object[]);;Argument[1];sql;manual",
257+
"System.Data.Entity;Database;false;ExecuteSqlCommandAsync;(System.String,System.Threading.CancellationToken,System.Object[]);;Argument[0];sql;manual",
258+
"System.Data.Entity;Database;false;ExecuteSqlCommandAsync;(System.String,System.Object[]);;Argument[0];sql;manual",
259+
"System.Data.Entity;Database;false;ExecuteSqlCommandAsync;(System.Data.Entity.TransactionalBehavior,System.String,System.Object[]);;Argument[1];sql;manual"
260260
]
261261
}
262262
}
@@ -266,7 +266,7 @@ module EntityFramework {
266266
override predicate row(string row) {
267267
row =
268268
[
269-
"Microsoft.EntityFrameworkCore;RelationalQueryableExtensions;false;FromSqlRaw<>;(Microsoft.EntityFrameworkCore.DbSet<TEntity>,System.String,System.Object[]);;Argument[1];sql",
269+
"Microsoft.EntityFrameworkCore;RelationalQueryableExtensions;false;FromSqlRaw<>;(Microsoft.EntityFrameworkCore.DbSet<TEntity>,System.String,System.Object[]);;Argument[1];sql;manual",
270270
]
271271
}
272272
}
@@ -276,11 +276,11 @@ module EntityFramework {
276276
override predicate row(string row) {
277277
row =
278278
[
279-
"Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;false;ExecuteSqlRaw;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Collections.Generic.IEnumerable<System.Object>);;Argument[1];sql",
280-
"Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;false;ExecuteSqlRaw;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Object[]);;Argument[1];sql",
281-
"Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;false;ExecuteSqlRawAsync;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Threading.CancellationToken);;Argument[1];sql",
282-
"Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;false;ExecuteSqlRawAsync;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Object[]);;Argument[1];sql",
283-
"Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;false;ExecuteSqlRawAsync;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Collections.Generic.IEnumerable<System.Object>,System.Threading.CancellationToken);;Argument[1];sql",
279+
"Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;false;ExecuteSqlRaw;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Collections.Generic.IEnumerable<System.Object>);;Argument[1];sql;manual",
280+
"Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;false;ExecuteSqlRaw;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Object[]);;Argument[1];sql;manual",
281+
"Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;false;ExecuteSqlRawAsync;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Threading.CancellationToken);;Argument[1];sql;manual",
282+
"Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;false;ExecuteSqlRawAsync;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Object[]);;Argument[1];sql;manual",
283+
"Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;false;ExecuteSqlRawAsync;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Collections.Generic.IEnumerable<System.Object>,System.Threading.CancellationToken);;Argument[1];sql;manual",
284284
]
285285
}
286286
}

0 commit comments

Comments
 (0)