1
1
/**
2
2
* INTERNAL use only. This is an experimental API subject to change without notice.
3
3
*
4
- * Provides classes and predicates for dealing with flow models specified in CSV format.
4
+ * Provides classes and predicates for dealing with MaD flow models specified
5
+ * in data extensions and CSV format.
5
6
*
6
7
* The CSV specification has the following columns:
7
8
* - Sources:
8
- * `namespace ; type; subtypes; name; signature; ext; output; kind`
9
+ * `package ; type; subtypes; name; signature; ext; output; kind; provenance `
9
10
* - Sinks:
10
- * `namespace ; type; subtypes; name; signature; ext; input; kind`
11
+ * `package ; type; subtypes; name; signature; ext; input; kind; provenance `
11
12
* - Summaries:
12
- * `namespace ; type; subtypes; name; signature; ext; input; output; kind`
13
+ * `package ; type; subtypes; name; signature; ext; input; output; kind; provenance `
13
14
*
14
15
* The interpretation of a row is similar to API-graphs with a left-to-right
15
16
* reading.
16
- * 1. The `namespace ` column selects a package.
17
+ * 1. The `package ` column selects a package.
17
18
* 2. The `type` column selects a type within that package.
18
19
* 3. The `subtypes` is a boolean that indicates whether to jump to an
19
20
* arbitrary subtype of that type.
61
62
*/
62
63
63
64
private import go
65
+ private import ExternalFlowExtensions as Extensions
64
66
private import internal.DataFlowPrivate
65
67
private import internal.FlowSummaryImpl:: Private:: External
66
68
private import internal.FlowSummaryImplSpecific
@@ -75,155 +77,54 @@ private module Frameworks {
75
77
private import semmle.go.frameworks.Stdlib
76
78
}
77
79
78
- private class BuiltinModel extends SummaryModelCsv {
79
- override predicate row ( string row ) {
80
- row =
81
- [
82
- ";;false;append;;;Argument[0].ArrayElement;ReturnValue.ArrayElement;value" ,
83
- ";;false;append;;;Argument[1];ReturnValue.ArrayElement;value"
84
- ]
85
- }
86
- }
87
-
88
- /**
89
- * A unit class for adding additional source model rows.
90
- *
91
- * Extend this class to add additional source definitions.
92
- */
93
- class SourceModelCsv extends Unit {
94
- /** Holds if `row` specifies a source definition. */
95
- abstract predicate row ( string row ) ;
96
- }
97
-
98
- /**
99
- * A unit class for adding additional sink model rows.
100
- *
101
- * Extend this class to add additional sink definitions.
102
- */
103
- class SinkModelCsv extends Unit {
104
- /** Holds if `row` specifies a sink definition. */
105
- abstract predicate row ( string row ) ;
106
- }
107
-
108
- /**
109
- * A unit class for adding additional summary model rows.
110
- *
111
- * Extend this class to add additional flow summary definitions.
112
- */
113
- class SummaryModelCsv extends Unit {
114
- /** Holds if `row` specifies a summary definition. */
115
- abstract predicate row ( string row ) ;
116
- }
117
-
118
- /** Holds if `row` is a source model. */
119
- predicate sourceModel ( string row ) { any ( SourceModelCsv s ) .row ( row ) }
120
-
121
- /** Holds if `row` is a sink model. */
122
- predicate sinkModel ( string row ) { any ( SinkModelCsv s ) .row ( row ) }
123
-
124
- /** Holds if `row` is a summary model. */
125
- predicate summaryModel ( string row ) { any ( SummaryModelCsv s ) .row ( row ) }
126
-
127
80
/** Holds if a source model exists for the given parameters. */
128
- predicate sourceModel (
129
- string namespace , string type , boolean subtypes , string name , string signature , string ext ,
130
- string output , string kind , string provenance
131
- ) {
132
- exists ( string row |
133
- sourceModel ( row ) and
134
- row .splitAt ( ";" , 0 ) = namespace and
135
- row .splitAt ( ";" , 1 ) = type and
136
- row .splitAt ( ";" , 2 ) = subtypes .toString ( ) and
137
- subtypes = [ true , false ] and
138
- row .splitAt ( ";" , 3 ) = name and
139
- row .splitAt ( ";" , 4 ) = signature and
140
- row .splitAt ( ";" , 5 ) = ext and
141
- row .splitAt ( ";" , 6 ) = output and
142
- row .splitAt ( ";" , 7 ) = kind and
143
- provenance = "manual"
144
- )
145
- }
81
+ predicate sourceModel = Extensions:: sourceModel / 9 ;
146
82
147
83
/** Holds if a sink model exists for the given parameters. */
148
- predicate sinkModel (
149
- string namespace , string type , boolean subtypes , string name , string signature , string ext ,
150
- string input , string kind , string provenance
151
- ) {
152
- exists ( string row |
153
- sinkModel ( row ) and
154
- row .splitAt ( ";" , 0 ) = namespace and
155
- row .splitAt ( ";" , 1 ) = type and
156
- row .splitAt ( ";" , 2 ) = subtypes .toString ( ) and
157
- subtypes = [ true , false ] and
158
- row .splitAt ( ";" , 3 ) = name and
159
- row .splitAt ( ";" , 4 ) = signature and
160
- row .splitAt ( ";" , 5 ) = ext and
161
- row .splitAt ( ";" , 6 ) = input and
162
- row .splitAt ( ";" , 7 ) = kind and
163
- provenance = "manual"
164
- )
165
- }
84
+ predicate sinkModel = Extensions:: sinkModel / 9 ;
166
85
167
86
/** Holds if a summary model exists for the given parameters. */
168
- predicate summaryModel (
169
- string namespace , string type , boolean subtypes , string name , string signature , string ext ,
170
- string input , string output , string kind , string provenance
171
- ) {
172
- exists ( string row |
173
- summaryModel ( row ) and
174
- row .splitAt ( ";" , 0 ) = namespace and
175
- row .splitAt ( ";" , 1 ) = type and
176
- row .splitAt ( ";" , 2 ) = subtypes .toString ( ) and
177
- subtypes = [ true , false ] and
178
- row .splitAt ( ";" , 3 ) = name and
179
- row .splitAt ( ";" , 4 ) = signature and
180
- row .splitAt ( ";" , 5 ) = ext and
181
- row .splitAt ( ";" , 6 ) = input and
182
- row .splitAt ( ";" , 7 ) = output and
183
- row .splitAt ( ";" , 8 ) = kind
184
- ) and
185
- provenance = "manual"
186
- }
87
+ predicate summaryModel = Extensions:: summaryModel / 10 ;
187
88
188
- /** Holds if `package` have CSV framework coverage. */
189
- private predicate packageHasCsvCoverage ( string package ) {
89
+ /** Holds if `package` have MaD framework coverage. */
90
+ private predicate packageHasMaDCoverage ( string package ) {
190
91
sourceModel ( package , _, _, _, _, _, _, _, _) or
191
92
sinkModel ( package , _, _, _, _, _, _, _, _) or
192
93
summaryModel ( package , _, _, _, _, _, _, _, _, _)
193
94
}
194
95
195
96
/**
196
- * Holds if `package` and `subpkg` have CSV framework coverage and `subpkg`
97
+ * Holds if `package` and `subpkg` have MaD framework coverage and `subpkg`
197
98
* is a subpackage of `package`.
198
99
*/
199
100
private predicate packageHasASubpackage ( string package , string subpkg ) {
200
- packageHasCsvCoverage ( package ) and
201
- packageHasCsvCoverage ( subpkg ) and
101
+ packageHasMaDCoverage ( package ) and
102
+ packageHasMaDCoverage ( subpkg ) and
202
103
subpkg .prefix ( subpkg .indexOf ( "." ) ) = package
203
104
}
204
105
205
106
/**
206
- * Holds if `package` has CSV framework coverage and it is not a subpackage of
207
- * any other package with CSV framework coverage.
107
+ * Holds if `package` has MaD framework coverage and it is not a subpackage of
108
+ * any other package with MaD framework coverage.
208
109
*/
209
110
private predicate canonicalPackage ( string package ) {
210
- packageHasCsvCoverage ( package ) and not packageHasASubpackage ( _, package )
111
+ packageHasMaDCoverage ( package ) and not packageHasASubpackage ( _, package )
211
112
}
212
113
213
114
/**
214
- * Holds if `package` and `subpkg` have CSV framework coverage, `subpkg` is a
115
+ * Holds if `package` and `subpkg` have MaD framework coverage, `subpkg` is a
215
116
* subpackage of `package` (or they are the same), and `package` is not a
216
- * subpackage of any other package with CSV framework coverage.
117
+ * subpackage of any other package with MaD framework coverage.
217
118
*/
218
119
private predicate canonicalPackageHasASubpackage ( string package , string subpkg ) {
219
120
canonicalPackage ( package ) and
220
121
( subpkg = package or packageHasASubpackage ( package , subpkg ) )
221
122
}
222
123
223
124
/**
224
- * Holds if CSV framework coverage of `package` is `n` api endpoints of the
125
+ * Holds if MaD framework coverage of `package` is `n` api endpoints of the
225
126
* kind `(kind, part)`, and `pkgs` is the number of subpackages of `package`
226
- * which have CSV framework coverage (including `package` itself).
127
+ * which have MaD framework coverage (including `package` itself).
227
128
*/
228
129
predicate modelCoverage ( string package , int pkgs , string kind , string part , int n ) {
229
130
pkgs = strictcount ( string subpkg | canonicalPackageHasASubpackage ( package , subpkg ) ) and
@@ -254,8 +155,8 @@ predicate modelCoverage(string package, int pkgs, string kind, string part, int
254
155
)
255
156
}
256
157
257
- /** Provides a query predicate to check the CSV data for validation errors. */
258
- module CsvValidation {
158
+ /** Provides a query predicate to check the MaD models for validation errors. */
159
+ module ModelValidation {
259
160
private string getInvalidModelInput ( ) {
260
161
exists ( string pred , AccessPath input , string part |
261
162
sinkModel ( _, _, _, _, _, _, input , _, _) and pred = "sink"
@@ -288,57 +189,25 @@ module CsvValidation {
288
189
}
289
190
290
191
private string getInvalidModelKind ( ) {
291
- exists ( string row , string kind | summaryModel ( row ) |
292
- kind = row .splitAt ( ";" , 8 ) and
192
+ exists ( string kind | summaryModel ( _, _, _, _, _, _, _, _, kind , _) |
293
193
not kind = [ "taint" , "value" ] and
294
194
result = "Invalid kind \"" + kind + "\" in summary model."
295
195
)
296
196
}
297
197
298
- private string getInvalidModelSubtype ( ) {
299
- exists ( string pred , string row |
300
- sourceModel ( row ) and pred = "source"
301
- or
302
- sinkModel ( row ) and pred = "sink"
303
- or
304
- summaryModel ( row ) and pred = "summary"
305
- |
306
- exists ( string b |
307
- b = row .splitAt ( ";" , 2 ) and
308
- not b = [ "true" , "false" ] and
309
- result = "Invalid boolean \"" + b + "\" in " + pred + " model."
310
- )
311
- )
312
- }
313
-
314
- private string getInvalidModelColumnCount ( ) {
315
- exists ( string pred , string row , int expect |
316
- sourceModel ( row ) and expect = 8 and pred = "source"
317
- or
318
- sinkModel ( row ) and expect = 8 and pred = "sink"
319
- or
320
- summaryModel ( row ) and expect = 9 and pred = "summary"
321
- |
322
- exists ( int cols |
323
- cols = 1 + max ( int n | exists ( row .splitAt ( ";" , n ) ) ) and
324
- cols != expect and
325
- result =
326
- "Wrong number of columns in " + pred + " model row, expected " + expect + ", got " + cols +
327
- "."
328
- )
329
- )
330
- }
331
-
332
198
private string getInvalidModelSignature ( ) {
333
- exists ( string pred , string namespace , string type , string name , string signature , string ext |
334
- sourceModel ( namespace , type , _, name , signature , ext , _, _, _) and pred = "source"
199
+ exists (
200
+ string pred , string package , string type , string name , string signature , string ext ,
201
+ string provenance
202
+ |
203
+ sourceModel ( package , type , _, name , signature , ext , _, _, provenance ) and pred = "source"
335
204
or
336
- sinkModel ( namespace , type , _, name , signature , ext , _, _, _ ) and pred = "sink"
205
+ sinkModel ( package , type , _, name , signature , ext , _, _, provenance ) and pred = "sink"
337
206
or
338
- summaryModel ( namespace , type , _, name , signature , ext , _, _, _, _ ) and pred = "summary"
207
+ summaryModel ( package , type , _, name , signature , ext , _, _, _, provenance ) and pred = "summary"
339
208
|
340
- not namespace .regexpMatch ( "[a-zA-Z0-9_\\./]*" ) and
341
- result = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
209
+ not package .regexpMatch ( "[a-zA-Z0-9_\\./]*" ) and
210
+ result = "Dubious package \"" + package + "\" in " + pred + " model."
342
211
or
343
212
not type .regexpMatch ( "[a-zA-Z0-9_\\$<>]*" ) and
344
213
result = "Dubious type \"" + type + "\" in " + pred + " model."
@@ -351,26 +220,29 @@ module CsvValidation {
351
220
or
352
221
not ext .regexpMatch ( "|Annotated" ) and
353
222
result = "Unrecognized extra API graph element \"" + ext + "\" in " + pred + " model."
223
+ or
224
+ not provenance = [ "manual" , "generated" ] and
225
+ result = "Unrecognized provenance description \"" + provenance + "\" in " + pred + " model."
354
226
)
355
227
}
356
228
357
- /** Holds if some row in a CSV-based flow model appears to contain typos. */
229
+ /** Holds if some row in a MaD flow model appears to contain typos. */
358
230
query predicate invalidModelRow ( string msg ) {
359
231
msg =
360
232
[
361
233
getInvalidModelSignature ( ) , getInvalidModelInput ( ) , getInvalidModelOutput ( ) ,
362
- getInvalidModelSubtype ( ) , getInvalidModelColumnCount ( ) , getInvalidModelKind ( )
234
+ getInvalidModelKind ( )
363
235
]
364
236
}
365
237
}
366
238
367
239
pragma [ nomagic]
368
240
private predicate elementSpec (
369
- string namespace , string type , boolean subtypes , string name , string signature , string ext
241
+ string package , string type , boolean subtypes , string name , string signature , string ext
370
242
) {
371
- sourceModel ( namespace , type , subtypes , name , signature , ext , _, _, _) or
372
- sinkModel ( namespace , type , subtypes , name , signature , ext , _, _, _) or
373
- summaryModel ( namespace , type , subtypes , name , signature , ext , _, _, _, _)
243
+ sourceModel ( package , type , subtypes , name , signature , ext , _, _, _) or
244
+ sinkModel ( package , type , subtypes , name , signature , ext , _, _, _) or
245
+ summaryModel ( package , type , subtypes , name , signature , ext , _, _, _, _)
374
246
}
375
247
376
248
private string paramsStringPart ( Function f , int i ) {
@@ -466,7 +338,7 @@ predicate parseContent(string component, DataFlow::Content content) {
466
338
cached
467
339
private module Cached {
468
340
/**
469
- * Holds if `node` is specified as a source with the given kind in a CSV flow
341
+ * Holds if `node` is specified as a source with the given kind in a MaD flow
470
342
* model.
471
343
*/
472
344
cached
@@ -475,7 +347,7 @@ private module Cached {
475
347
}
476
348
477
349
/**
478
- * Holds if `node` is specified as a sink with the given kind in a CSV flow
350
+ * Holds if `node` is specified as a sink with the given kind in a MaD flow
479
351
* model.
480
352
*/
481
353
cached
0 commit comments