Skip to content

Commit c768f04

Browse files
committed
Go: Introduce generated flag as a part of the kind column for flow summaries
Equivalent of #8628
1 parent dae60c9 commit c768f04

File tree

2 files changed

+52
-39
lines changed

2 files changed

+52
-39
lines changed

go/ql/lib/semmle/go/dataflow/ExternalFlow.qll

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,17 @@ predicate sinkModel(string row) { any(SinkModelCsv s).row(row) }
124124
/** Holds if `row` is a summary model. */
125125
predicate summaryModel(string row) { any(SummaryModelCsv s).row(row) }
126126

127+
bindingset[input]
128+
private predicate getKind(string input, string kind, boolean generated) {
129+
input.splitAt(":", 0) = "generated" and kind = input.splitAt(":", 1) and generated = true
130+
or
131+
not input.matches("%:%") and kind = input and generated = false
132+
}
133+
127134
/** Holds if a source model exists for the given parameters. */
128135
predicate sourceModel(
129136
string namespace, string type, boolean subtypes, string name, string signature, string ext,
130-
string output, string kind
137+
string output, string kind, boolean generated
131138
) {
132139
exists(string row |
133140
sourceModel(row) and
@@ -139,14 +146,14 @@ predicate sourceModel(
139146
row.splitAt(";", 4) = signature and
140147
row.splitAt(";", 5) = ext and
141148
row.splitAt(";", 6) = output and
142-
row.splitAt(";", 7) = kind
149+
exists(string k | row.splitAt(";", 7) = k and getKind(k, kind, generated))
143150
)
144151
}
145152

146153
/** Holds if a sink model exists for the given parameters. */
147154
predicate sinkModel(
148155
string namespace, string type, boolean subtypes, string name, string signature, string ext,
149-
string input, string kind
156+
string input, string kind, boolean generated
150157
) {
151158
exists(string row |
152159
sinkModel(row) and
@@ -158,22 +165,22 @@ predicate sinkModel(
158165
row.splitAt(";", 4) = signature and
159166
row.splitAt(";", 5) = ext and
160167
row.splitAt(";", 6) = input and
161-
row.splitAt(";", 7) = kind
168+
exists(string k | row.splitAt(";", 7) = k and getKind(k, kind, generated))
162169
)
163170
}
164171

165172
/** Holds if a summary model exists for the given parameters. */
166173
predicate summaryModel(
167174
string namespace, string type, boolean subtypes, string name, string signature, string ext,
168-
string input, string output, string kind
175+
string input, string output, string kind, boolean generated
169176
) {
170-
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, _)
177+
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, generated, _)
171178
}
172179

173180
/** Holds if a summary model `row` exists for the given parameters. */
174181
predicate summaryModel(
175182
string namespace, string type, boolean subtypes, string name, string signature, string ext,
176-
string input, string output, string kind, string row
183+
string input, string output, string kind, boolean generated, string row
177184
) {
178185
summaryModel(row) and
179186
row.splitAt(";", 0) = namespace and
@@ -185,14 +192,14 @@ predicate summaryModel(
185192
row.splitAt(";", 5) = ext and
186193
row.splitAt(";", 6) = input and
187194
row.splitAt(";", 7) = output and
188-
row.splitAt(";", 8) = kind
195+
exists(string k | row.splitAt(";", 8) = k and getKind(k, kind, generated))
189196
}
190197

191198
/** Holds if `package` have CSV framework coverage. */
192199
private predicate packageHasCsvCoverage(string package) {
193-
sourceModel(package, _, _, _, _, _, _, _) or
194-
sinkModel(package, _, _, _, _, _, _, _) or
195-
summaryModel(package, _, _, _, _, _, _, _, _)
200+
sourceModel(package, _, _, _, _, _, _, _, _) or
201+
sinkModel(package, _, _, _, _, _, _, _, _) or
202+
summaryModel(package, _, _, _, _, _, _, _, _, _)
196203
}
197204

198205
/**
@@ -234,25 +241,25 @@ predicate modelCoverage(string package, int pkgs, string kind, string part, int
234241
part = "source" and
235242
n =
236243
strictcount(string subpkg, string type, boolean subtypes, string name, string signature,
237-
string ext, string output |
244+
string ext, string output, boolean generated |
238245
canonicalPackageHasASubpackage(package, subpkg) and
239-
sourceModel(subpkg, type, subtypes, name, signature, ext, output, kind)
246+
sourceModel(subpkg, type, subtypes, name, signature, ext, output, kind, generated)
240247
)
241248
or
242249
part = "sink" and
243250
n =
244251
strictcount(string subpkg, string type, boolean subtypes, string name, string signature,
245-
string ext, string input |
252+
string ext, string input, boolean generated |
246253
canonicalPackageHasASubpackage(package, subpkg) and
247-
sinkModel(subpkg, type, subtypes, name, signature, ext, input, kind)
254+
sinkModel(subpkg, type, subtypes, name, signature, ext, input, kind, generated)
248255
)
249256
or
250257
part = "summary" and
251258
n =
252259
strictcount(string subpkg, string type, boolean subtypes, string name, string signature,
253-
string ext, string input, string output |
260+
string ext, string input, string output, boolean generated |
254261
canonicalPackageHasASubpackage(package, subpkg) and
255-
summaryModel(subpkg, type, subtypes, name, signature, ext, input, output, kind)
262+
summaryModel(subpkg, type, subtypes, name, signature, ext, input, output, kind, generated)
256263
)
257264
)
258265
}
@@ -261,9 +268,9 @@ predicate modelCoverage(string package, int pkgs, string kind, string part, int
261268
module CsvValidation {
262269
private string getInvalidModelInput() {
263270
exists(string pred, AccessPath input, string part |
264-
sinkModel(_, _, _, _, _, _, input, _) and pred = "sink"
271+
sinkModel(_, _, _, _, _, _, input, _, _) and pred = "sink"
265272
or
266-
summaryModel(_, _, _, _, _, _, input, _, _) and pred = "summary"
273+
summaryModel(_, _, _, _, _, _, input, _, _, _) and pred = "summary"
267274
|
268275
(
269276
invalidSpecComponent(input, part) and
@@ -279,9 +286,9 @@ module CsvValidation {
279286

280287
private string getInvalidModelOutput() {
281288
exists(string pred, string output, string part |
282-
sourceModel(_, _, _, _, _, _, output, _) and pred = "source"
289+
sourceModel(_, _, _, _, _, _, output, _, _) and pred = "source"
283290
or
284-
summaryModel(_, _, _, _, _, _, _, output, _) and pred = "summary"
291+
summaryModel(_, _, _, _, _, _, _, output, _, _) and pred = "summary"
285292
|
286293
invalidSpecComponent(output, part) and
287294
not part = "" and
@@ -291,8 +298,9 @@ module CsvValidation {
291298
}
292299

293300
private string getInvalidModelKind() {
294-
exists(string row, string kind | summaryModel(row) |
295-
kind = row.splitAt(";", 8) and
301+
exists(string row, string k, string kind | summaryModel(row) |
302+
k = row.splitAt(";", 8) and
303+
getKind(k, kind, _) and
296304
not kind = ["taint", "value"] and
297305
result = "Invalid kind \"" + kind + "\" in summary model."
298306
)
@@ -334,11 +342,11 @@ module CsvValidation {
334342

335343
private string getInvalidModelSignature() {
336344
exists(string pred, string namespace, string type, string name, string signature, string ext |
337-
sourceModel(namespace, type, _, name, signature, ext, _, _) and pred = "source"
345+
sourceModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "source"
338346
or
339-
sinkModel(namespace, type, _, name, signature, ext, _, _) and pred = "sink"
347+
sinkModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "sink"
340348
or
341-
summaryModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "summary"
349+
summaryModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "summary"
342350
|
343351
not namespace.regexpMatch("[a-zA-Z0-9_\\./]*") and
344352
result = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
@@ -371,9 +379,9 @@ pragma[nomagic]
371379
private predicate elementSpec(
372380
string namespace, string type, boolean subtypes, string name, string signature, string ext
373381
) {
374-
sourceModel(namespace, type, subtypes, name, signature, ext, _, _) or
375-
sinkModel(namespace, type, subtypes, name, signature, ext, _, _) or
376-
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _)
382+
sourceModel(namespace, type, subtypes, name, signature, ext, _, _, _) or
383+
sinkModel(namespace, type, subtypes, name, signature, ext, _, _, _) or
384+
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _)
377385
}
378386

379387
private string paramsStringPart(Function f, int i) {
@@ -421,7 +429,9 @@ SourceOrSinkElement interpretElement(
421429
predicate hasExternalSpecification(Function f) {
422430
f = any(SummarizedCallable sc).asFunction()
423431
or
424-
exists(SourceOrSinkElement e | f = e.asEntity() | sourceElement(e, _, _) or sinkElement(e, _, _))
432+
exists(SourceOrSinkElement e | f = e.asEntity() |
433+
sourceElement(e, _, _, _) or sinkElement(e, _, _, _)
434+
)
425435
}
426436

427437
private predicate parseField(AccessPathToken c, DataFlow::FieldContent f) {

go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImplSpecific.qll

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,14 @@ DataFlowType getCallbackReturnType(DataFlowType t, ReturnKind rk) { none() }
8484

8585
/**
8686
* Holds if an external flow summary exists for `c` with input specification
87-
* `input`, output specification `output`, and kind `kind`.
87+
* `input`, output specification `output`, kind `kind`, and a flag `generated`
88+
* stating whether the summary is autogenerated.
8889
*/
89-
predicate summaryElement(DataFlowCallable c, string input, string output, string kind) {
90+
predicate summaryElement(DataFlowCallable c, string input, string output, string kind, boolean generated) {
9091
exists(
9192
string namespace, string type, boolean subtypes, string name, string signature, string ext
9293
|
93-
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind) and
94+
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, generated) and
9495
c.asFunction() = interpretElement(namespace, type, subtypes, name, signature, ext).asEntity()
9596
)
9697
}
@@ -166,26 +167,28 @@ class SourceOrSinkElement extends TSourceOrSinkElement {
166167

167168
/**
168169
* Holds if an external source specification exists for `e` with output specification
169-
* `output` and kind `kind`.
170+
* `output`, kind `kind`, and a flag `generated` stating whether the source specification is
171+
* autogenerated.
170172
*/
171-
predicate sourceElement(SourceOrSinkElement e, string output, string kind) {
173+
predicate sourceElement(SourceOrSinkElement e, string output, string kind, boolean generated) {
172174
exists(
173175
string namespace, string type, boolean subtypes, string name, string signature, string ext
174176
|
175-
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind) and
177+
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, generated) and
176178
e = interpretElement(namespace, type, subtypes, name, signature, ext)
177179
)
178180
}
179181

180182
/**
181183
* Holds if an external sink specification exists for `e` with input specification
182-
* `input` and kind `kind`.
184+
* `input`, kind `kind` and a flag `generated` stating whether the sink specification is
185+
* autogenerated.
183186
*/
184-
predicate sinkElement(SourceOrSinkElement e, string input, string kind) {
187+
predicate sinkElement(SourceOrSinkElement e, string input, string kind, boolean generated) {
185188
exists(
186189
string namespace, string type, boolean subtypes, string name, string signature, string ext
187190
|
188-
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind) and
191+
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, generated) and
189192
e = interpretElement(namespace, type, subtypes, name, signature, ext)
190193
)
191194
}

0 commit comments

Comments
 (0)