Skip to content

Commit 18a815c

Browse files
authored
Merge pull request #11721 from michaelnebel/csharpjava/refactorprovenance
C#/Java: Re-factor provenance related predicates.
2 parents 006eaf3 + 7e4f7a0 commit 18a815c

File tree

20 files changed

+269
-291
lines changed

20 files changed

+269
-291
lines changed

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -410,11 +410,6 @@ Element interpretElement(
410410
)
411411
}
412412

413-
/**
414-
* Holds if `c` has a `generated` summary.
415-
*/
416-
predicate hasSummary(Callable c, boolean generated) { summaryElement(c, _, _, _, generated) }
417-
418413
cached
419414
private module Cached {
420415
/**

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

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -241,31 +241,39 @@ module Public {
241241
}
242242

243243
/**
244-
* Holds if the summary is auto generated and not manually generated.
244+
* Holds if all the summaries that apply to `this` are auto generated and not manually created.
245245
*/
246-
predicate isAutoGenerated() { none() }
246+
final predicate isAutoGenerated() { this.hasProvenance("generated") and not this.isManual() }
247247

248248
/**
249-
* Holds if the summary has the given provenance where `true` is
250-
* `generated` and `false` is `manual`.
249+
* Holds if there exists a manual summary that applies to `this`.
251250
*/
252-
predicate hasProvenance(boolean generated) { none() }
251+
final predicate isManual() { this.hasProvenance("manual") }
252+
253+
/**
254+
* Holds if there exists a summary that applies to `this` that has provenance `provenance`.
255+
*/
256+
predicate hasProvenance(string provenance) { none() }
253257
}
254258

255259
/** A callable where there is no flow via the callable. */
256260
class NeutralCallable extends SummarizedCallableBase {
257261
NeutralCallable() { neutralElement(this, _) }
258262

259263
/**
260-
* Holds if the neutral is auto generated.
264+
* Holds if the neutral is auto generated.
261265
*/
262-
predicate isAutoGenerated() { neutralElement(this, true) }
266+
predicate isAutoGenerated() { neutralElement(this, "generated") }
263267

264268
/**
265-
* Holds if the neutral has the given provenance where `true` is
266-
* `generated` and `false` is `manual`.
269+
* Holds if there exists a manual neutral that applies to `this`.
267270
*/
268-
predicate hasProvenance(boolean generated) { neutralElement(this, generated) }
271+
final predicate isManual() { this.hasProvenance("manual") }
272+
273+
/**
274+
* Holds if the neutral has provenance `provenance`.
275+
*/
276+
predicate hasProvenance(string provenance) { neutralElement(this, provenance) }
269277
}
270278
}
271279

@@ -997,12 +1005,12 @@ module Private {
9971005
private predicate relevantSummaryElementGenerated(
9981006
AccessPath inSpec, AccessPath outSpec, string kind
9991007
) {
1000-
summaryElement(this, inSpec, outSpec, kind, true) and
1001-
not summaryElement(this, _, _, _, false)
1008+
summaryElement(this, inSpec, outSpec, kind, "generated") and
1009+
not summaryElement(this, _, _, _, "manual")
10021010
}
10031011

10041012
private predicate relevantSummaryElement(AccessPath inSpec, AccessPath outSpec, string kind) {
1005-
summaryElement(this, inSpec, outSpec, kind, false)
1013+
summaryElement(this, inSpec, outSpec, kind, "manual")
10061014
or
10071015
this.relevantSummaryElementGenerated(inSpec, outSpec, kind)
10081016
}
@@ -1021,10 +1029,8 @@ module Private {
10211029
)
10221030
}
10231031

1024-
override predicate isAutoGenerated() { this.relevantSummaryElementGenerated(_, _, _) }
1025-
1026-
override predicate hasProvenance(boolean generated) {
1027-
summaryElement(this, _, _, _, generated)
1032+
override predicate hasProvenance(string provenance) {
1033+
summaryElement(this, _, _, _, provenance)
10281034
}
10291035
}
10301036

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

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -97,69 +97,52 @@ DataFlowType getSyntheticGlobalType(SummaryComponent::SyntheticGlobal sg) {
9797
result = Gvn::getGlobalValueNumber(any(ObjectType t))
9898
}
9999

100-
bindingset[provenance]
101-
private boolean isGenerated(string provenance) {
102-
provenance = "generated" and result = true
103-
or
104-
provenance != "generated" and result = false
105-
}
106-
107100
/**
108101
* Holds if an external flow summary exists for `c` with input specification
109-
* `input`, output specification `output`, kind `kind`, and a flag `generated`
110-
* stating whether the summary is autogenerated.
102+
* `input`, output specification `output`, kind `kind`, and provenance `provenance`.
111103
*/
112-
predicate summaryElement(Callable c, string input, string output, string kind, boolean generated) {
104+
predicate summaryElement(Callable c, string input, string output, string kind, string provenance) {
113105
exists(
114-
string namespace, string type, boolean subtypes, string name, string signature, string ext,
115-
string provenance
106+
string namespace, string type, boolean subtypes, string name, string signature, string ext
116107
|
117108
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance) and
118-
generated = isGenerated(provenance) and
119109
c = interpretElement(namespace, type, subtypes, name, signature, ext)
120110
)
121111
}
122112

123113
/**
124-
* Holds if a neutral model exists for `c`, which means that there is no
125-
* flow through `c`. The flag `generated` states whether the neutral model is autogenerated.
114+
* Holds if a neutral model exists for `c` with provenance `provenace`,
115+
* which means that there is no flow through `c`.
126116
*/
127-
predicate neutralElement(Callable c, boolean generated) {
128-
exists(string namespace, string type, string name, string signature, string provenance |
117+
predicate neutralElement(Callable c, string provenance) {
118+
exists(string namespace, string type, string name, string signature |
129119
neutralModel(namespace, type, name, signature, provenance) and
130-
generated = isGenerated(provenance) and
131120
c = interpretElement(namespace, type, false, name, signature, "")
132121
)
133122
}
134123

135124
/**
136125
* Holds if an external source specification exists for `e` with output specification
137-
* `output`, kind `kind`, and a flag `generated` stating whether the source specification is
138-
* autogenerated.
126+
* `output`, kind `kind`, and provenance `provenance`.
139127
*/
140-
predicate sourceElement(Element e, string output, string kind, boolean generated) {
128+
predicate sourceElement(Element e, string output, string kind, string provenance) {
141129
exists(
142-
string namespace, string type, boolean subtypes, string name, string signature, string ext,
143-
string provenance
130+
string namespace, string type, boolean subtypes, string name, string signature, string ext
144131
|
145132
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance) and
146-
generated = isGenerated(provenance) and
147133
e = interpretElement(namespace, type, subtypes, name, signature, ext)
148134
)
149135
}
150136

151137
/**
152138
* Holds if an external sink specification exists for `e` with input specification
153-
* `input`, kind `kind` and a flag `generated` stating whether the sink specification is
154-
* autogenerated.
139+
* `input`, kind `kind` and provenance `provenance`.
155140
*/
156-
predicate sinkElement(Element e, string input, string kind, boolean generated) {
141+
predicate sinkElement(Element e, string input, string kind, string provenance) {
157142
exists(
158-
string namespace, string type, boolean subtypes, string name, string signature, string ext,
159-
string provenance
143+
string namespace, string type, boolean subtypes, string name, string signature, string ext
160144
|
161145
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance) and
162-
generated = isGenerated(provenance) and
163146
e = interpretElement(namespace, type, subtypes, name, signature, ext)
164147
)
165148
}

csharp/ql/src/utils/modelgenerator/CaptureDiscardedSummaryModels.ql

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
* @id cs/utils/modelgenerator/discarded-summary-models
55
*/
66

7-
import semmle.code.csharp.dataflow.ExternalFlow
7+
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
88
import internal.CaptureModels
99
import internal.CaptureSummaryFlow
1010

1111
from DataFlowTargetApi api, string flow
12-
where flow = captureFlow(api) and hasSummary(api, false)
12+
where
13+
flow = captureFlow(api) and
14+
api.(FlowSummaryImpl::Public::SummarizedCallable).isManual()
1315
select flow order by flow

csharp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
* @tags modelgenerator
77
*/
88

9-
import semmle.code.csharp.dataflow.ExternalFlow
9+
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
1010
import internal.CaptureModels
1111
import internal.CaptureSummaryFlow
1212

1313
from DataFlowTargetApi api, string noflow
1414
where
1515
noflow = captureNoFlow(api) and
16-
not hasSummary(api, false)
16+
not api.(FlowSummaryImpl::Public::SummarizedCallable).isManual()
1717
select noflow order by noflow

csharp/ql/src/utils/modelgenerator/CaptureSummaryModels.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
* @tags modelgenerator
77
*/
88

9-
import semmle.code.csharp.dataflow.ExternalFlow
9+
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
1010
import internal.CaptureModels
1111
import internal.CaptureSummaryFlow
1212

1313
from DataFlowTargetApi api, string flow
14-
where flow = captureFlow(api) and not hasSummary(api, false)
14+
where flow = captureFlow(api) and not api.(FlowSummaryImpl::Public::SummarizedCallable).isManual()
1515
select flow order by flow

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

Lines changed: 29 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -124,17 +124,10 @@ 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-
134127
/** Holds if a source model exists for the given parameters. */
135128
predicate sourceModel(
136129
string namespace, string type, boolean subtypes, string name, string signature, string ext,
137-
string output, string kind, boolean generated
130+
string output, string kind, string provenance
138131
) {
139132
exists(string row |
140133
sourceModel(row) and
@@ -146,14 +139,15 @@ predicate sourceModel(
146139
row.splitAt(";", 4) = signature and
147140
row.splitAt(";", 5) = ext and
148141
row.splitAt(";", 6) = output and
149-
exists(string k | row.splitAt(";", 7) = k and getKind(k, kind, generated))
142+
row.splitAt(";", 7) = kind and
143+
provenance = "manual"
150144
)
151145
}
152146

153147
/** Holds if a sink model exists for the given parameters. */
154148
predicate sinkModel(
155149
string namespace, string type, boolean subtypes, string name, string signature, string ext,
156-
string input, string kind, boolean generated
150+
string input, string kind, string provenance
157151
) {
158152
exists(string row |
159153
sinkModel(row) and
@@ -165,34 +159,30 @@ predicate sinkModel(
165159
row.splitAt(";", 4) = signature and
166160
row.splitAt(";", 5) = ext and
167161
row.splitAt(";", 6) = input and
168-
exists(string k | row.splitAt(";", 7) = k and getKind(k, kind, generated))
162+
row.splitAt(";", 7) = kind and
163+
provenance = "manual"
169164
)
170165
}
171166

172167
/** Holds if a summary model exists for the given parameters. */
173168
predicate summaryModel(
174169
string namespace, string type, boolean subtypes, string name, string signature, string ext,
175-
string input, string output, string kind, boolean generated
170+
string input, string output, string kind, string provenance
176171
) {
177-
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, generated, _)
178-
}
179-
180-
/** Holds if a summary model `row` exists for the given parameters. */
181-
predicate summaryModel(
182-
string namespace, string type, boolean subtypes, string name, string signature, string ext,
183-
string input, string output, string kind, boolean generated, string row
184-
) {
185-
summaryModel(row) and
186-
row.splitAt(";", 0) = namespace and
187-
row.splitAt(";", 1) = type and
188-
row.splitAt(";", 2) = subtypes.toString() and
189-
subtypes = [true, false] and
190-
row.splitAt(";", 3) = name and
191-
row.splitAt(";", 4) = signature and
192-
row.splitAt(";", 5) = ext and
193-
row.splitAt(";", 6) = input and
194-
row.splitAt(";", 7) = output and
195-
exists(string k | row.splitAt(";", 8) = k and getKind(k, kind, generated))
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"
196186
}
197187

198188
/** Holds if `package` have CSV framework coverage. */
@@ -241,25 +231,25 @@ predicate modelCoverage(string package, int pkgs, string kind, string part, int
241231
part = "source" and
242232
n =
243233
strictcount(string subpkg, string type, boolean subtypes, string name, string signature,
244-
string ext, string output, boolean generated |
234+
string ext, string output, string provenance |
245235
canonicalPackageHasASubpackage(package, subpkg) and
246-
sourceModel(subpkg, type, subtypes, name, signature, ext, output, kind, generated)
236+
sourceModel(subpkg, type, subtypes, name, signature, ext, output, kind, provenance)
247237
)
248238
or
249239
part = "sink" and
250240
n =
251241
strictcount(string subpkg, string type, boolean subtypes, string name, string signature,
252-
string ext, string input, boolean generated |
242+
string ext, string input, string provenance |
253243
canonicalPackageHasASubpackage(package, subpkg) and
254-
sinkModel(subpkg, type, subtypes, name, signature, ext, input, kind, generated)
244+
sinkModel(subpkg, type, subtypes, name, signature, ext, input, kind, provenance)
255245
)
256246
or
257247
part = "summary" and
258248
n =
259249
strictcount(string subpkg, string type, boolean subtypes, string name, string signature,
260-
string ext, string input, string output, boolean generated |
250+
string ext, string input, string output, string provenance |
261251
canonicalPackageHasASubpackage(package, subpkg) and
262-
summaryModel(subpkg, type, subtypes, name, signature, ext, input, output, kind, generated)
252+
summaryModel(subpkg, type, subtypes, name, signature, ext, input, output, kind, provenance)
263253
)
264254
)
265255
}
@@ -298,9 +288,8 @@ module CsvValidation {
298288
}
299289

300290
private string getInvalidModelKind() {
301-
exists(string row, string k, string kind | summaryModel(row) |
302-
k = row.splitAt(";", 8) and
303-
getKind(k, kind, _) and
291+
exists(string row, string kind | summaryModel(row) |
292+
kind = row.splitAt(";", 8) and
304293
not kind = ["taint", "value"] and
305294
result = "Invalid kind \"" + kind + "\" in summary model."
306295
)

0 commit comments

Comments
 (0)