Skip to content

Commit 79cd761

Browse files
authored
Merge pull request #12539 from michaelnebel/modelgenerator/configuration
Java/C#: Re-factor model generator taint tracking configurations to use the new API
2 parents 07f8780 + d258a1c commit 79cd761

15 files changed

+153
-170
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
88
import internal.CaptureModels
9-
import internal.CaptureSummaryFlow
9+
import internal.CaptureSummaryFlowQuery
1010

1111
from DataFlowTargetApi api, string flow
1212
where

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
1010
import internal.CaptureModels
11-
import internal.CaptureSummaryFlow
11+
import internal.CaptureSummaryFlowQuery
1212

1313
from DataFlowTargetApi api, string noflow
1414
where

csharp/ql/src/utils/modelgenerator/CaptureSinkModels.ql

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88

99
import internal.CaptureModels
1010

11-
class Activate extends ActiveConfiguration {
12-
override predicate activateToSinkConfig() { any() }
13-
}
14-
1511
from DataFlowTargetApi api, string sink
1612
where sink = captureSink(api)
1713
select sink order by sink

csharp/ql/src/utils/modelgenerator/CaptureSourceModels.ql

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88

99
import internal.CaptureModels
1010

11-
class Activate extends ActiveConfiguration {
12-
override predicate activateFromSourceConfig() { any() }
13-
}
14-
1511
from DataFlowTargetApi api, string source
1612
where source = captureSource(api)
1713
select source order by source

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
1010
import internal.CaptureModels
11-
import internal.CaptureSummaryFlow
11+
import internal.CaptureSummaryFlowQuery
1212

1313
from DataFlowTargetApi api, string flow
1414
where flow = captureFlow(api) and not api.(FlowSummaryImpl::Public::SummarizedCallable).isManual()

csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll

Lines changed: 66 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,6 @@
55

66
private import CaptureModelsSpecific
77

8-
class ActiveConfiguration extends Unit {
9-
predicate activateThroughFlowConfig() { none() }
10-
11-
predicate activateFromSourceConfig() { none() }
12-
13-
predicate activateToSinkConfig() { none() }
14-
}
15-
168
class DataFlowTargetApi extends TargetApiSpecific {
179
DataFlowTargetApi() { isRelevantForDataFlowModels(this) }
1810
}
@@ -46,6 +38,20 @@ private predicate isRelevantContent(DataFlow::Content c) {
4638
DataFlowPrivate::containerContent(c)
4739
}
4840

41+
/**
42+
* Gets the MaD string representation of the parameter node `p`.
43+
*/
44+
string parameterNodeAsInput(DataFlow::ParameterNode p) {
45+
result = parameterAccess(p.asParameter())
46+
or
47+
result = qualifierString() and p instanceof InstanceParameterNode
48+
}
49+
50+
/**
51+
* Gets the MaD input string representation of `source`.
52+
*/
53+
string asInputArgument(DataFlow::Node source) { result = asInputArgumentSpecific(source) }
54+
4955
/**
5056
* Gets the summary model for `api` with `input`, `output` and `kind`.
5157
*/
@@ -111,61 +117,70 @@ string captureQualifierFlow(TargetApiSpecific api) {
111117

112118
private int accessPathLimit() { result = 2 }
113119

120+
private newtype TTaintState =
121+
TTaintRead(int n) { n in [0 .. accessPathLimit()] } or
122+
TTaintStore(int n) { n in [1 .. accessPathLimit()] }
123+
124+
abstract private class TaintState extends TTaintState {
125+
abstract string toString();
126+
}
127+
114128
/**
115129
* A FlowState representing a tainted read.
116130
*/
117-
private class TaintRead extends DataFlow::FlowState {
131+
private class TaintRead extends TaintState, TTaintRead {
118132
private int step;
119133

120-
TaintRead() { this = "TaintRead(" + step + ")" and step in [0 .. accessPathLimit()] }
134+
TaintRead() { this = TTaintRead(step) }
121135

122136
/**
123137
* Gets the flow state step number.
124138
*/
125139
int getStep() { result = step }
140+
141+
override string toString() { result = "TaintRead(" + step + ")" }
126142
}
127143

128144
/**
129145
* A FlowState representing a tainted write.
130146
*/
131-
private class TaintStore extends DataFlow::FlowState {
147+
private class TaintStore extends TaintState, TTaintStore {
132148
private int step;
133149

134-
TaintStore() { this = "TaintStore(" + step + ")" and step in [1 .. accessPathLimit()] }
150+
TaintStore() { this = TTaintStore(step) }
135151

136152
/**
137153
* Gets the flow state step number.
138154
*/
139155
int getStep() { result = step }
156+
157+
override string toString() { result = "TaintStore(" + step + ")" }
140158
}
141159

142160
/**
143-
* A TaintTracking Configuration used for tracking flow through APIs.
161+
* A data-flow configuration for tracking flow through APIs.
144162
* The sources are the parameters of an API and the sinks are the return values (excluding `this`) and parameters.
145163
*
146164
* This can be used to generate Flow summaries for APIs from parameter to return.
147165
*/
148-
private class ThroughFlowConfig extends TaintTracking::Configuration {
149-
ThroughFlowConfig() {
150-
this = "ThroughFlowConfig" and any(ActiveConfiguration ac).activateThroughFlowConfig()
151-
}
166+
module ThroughFlowConfig implements DataFlow::StateConfigSig {
167+
class FlowState = TaintState;
152168

153-
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
169+
predicate isSource(DataFlow::Node source, FlowState state) {
154170
source instanceof DataFlow::ParameterNode and
155171
source.getEnclosingCallable() instanceof DataFlowTargetApi and
156172
state.(TaintRead).getStep() = 0
157173
}
158174

159-
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
175+
predicate isSink(DataFlow::Node sink, FlowState state) {
160176
sink instanceof DataFlowImplCommon::ReturnNodeExt and
161177
not isOwnInstanceAccessNode(sink) and
162178
not exists(captureQualifierFlow(sink.asExpr().getEnclosingCallable())) and
163179
(state instanceof TaintRead or state instanceof TaintStore)
164180
}
165181

166-
override predicate isAdditionalTaintStep(
167-
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
168-
DataFlow::FlowState state2
182+
predicate isAdditionalFlowStep(
183+
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
169184
) {
170185
exists(DataFlowImplCommon::TypedContent tc |
171186
DataFlowImplCommon::store(node1, tc, node2, _) and
@@ -184,24 +199,28 @@ private class ThroughFlowConfig extends TaintTracking::Configuration {
184199
)
185200
}
186201

187-
override predicate isSanitizer(DataFlow::Node n) {
202+
predicate isBarrier(DataFlow::Node n) {
188203
exists(Type t | t = n.getType() and not isRelevantType(t))
189204
}
190205

191-
override DataFlow::FlowFeature getAFeature() {
206+
predicate isBarrier(DataFlow::Node node, FlowState state) { none() }
207+
208+
DataFlow::FlowFeature getAFeature() {
192209
result instanceof DataFlow::FeatureEqualSourceSinkCallContext
193210
}
194211
}
195212

213+
private module ThroughFlow = TaintTracking::MakeWithState<ThroughFlowConfig>;
214+
196215
/**
197216
* Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter.
198217
*/
199218
string captureThroughFlow(DataFlowTargetApi api) {
200219
exists(
201-
ThroughFlowConfig config, DataFlow::ParameterNode p,
202-
DataFlowImplCommon::ReturnNodeExt returnNodeExt, string input, string output
220+
DataFlow::ParameterNode p, DataFlowImplCommon::ReturnNodeExt returnNodeExt, string input,
221+
string output
203222
|
204-
config.hasFlow(p, returnNodeExt) and
223+
ThroughFlow::hasFlow(p, returnNodeExt) and
205224
returnNodeExt.getEnclosingCallable() = api and
206225
input = parameterNodeAsInput(p) and
207226
output = returnNodeAsOutput(returnNodeExt) and
@@ -211,41 +230,37 @@ string captureThroughFlow(DataFlowTargetApi api) {
211230
}
212231

213232
/**
214-
* A TaintTracking Configuration used for tracking flow through APIs.
233+
* A dataflow configuration used for finding new sources.
215234
* The sources are the already known existing sources and the sinks are the API return nodes.
216235
*
217236
* This can be used to generate Source summaries for an API, if the API expose an already known source
218237
* via its return (then the API itself becomes a source).
219238
*/
220-
private class FromSourceConfiguration extends TaintTracking::Configuration {
221-
FromSourceConfiguration() {
222-
this = "FromSourceConfiguration" and any(ActiveConfiguration ac).activateFromSourceConfig()
223-
}
239+
module FromSourceConfig implements DataFlow::ConfigSig {
240+
predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) }
224241

225-
override predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) }
226-
227-
override predicate isSink(DataFlow::Node sink) {
242+
predicate isSink(DataFlow::Node sink) {
228243
exists(DataFlowTargetApi c |
229244
sink instanceof DataFlowImplCommon::ReturnNodeExt and
230245
sink.getEnclosingCallable() = c
231246
)
232247
}
233248

234-
override DataFlow::FlowFeature getAFeature() {
235-
result instanceof DataFlow::FeatureHasSinkCallContext
236-
}
249+
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSinkCallContext }
237250

238-
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
251+
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
239252
isRelevantTaintStep(node1, node2)
240253
}
241254
}
242255

256+
private module FromSource = TaintTracking::Make<FromSourceConfig>;
257+
243258
/**
244259
* Gets the source model(s) of `api`, if there is flow from an existing known source to the return of `api`.
245260
*/
246261
string captureSource(DataFlowTargetApi api) {
247-
exists(DataFlow::Node source, DataFlow::Node sink, FromSourceConfiguration config, string kind |
248-
config.hasFlow(source, sink) and
262+
exists(DataFlow::Node source, DataFlow::Node sink, string kind |
263+
FromSource::hasFlow(source, sink) and
249264
ExternalFlow::sourceNode(source, kind) and
250265
api = sink.getEnclosingCallable() and
251266
isRelevantSourceKind(kind) and
@@ -254,35 +269,30 @@ string captureSource(DataFlowTargetApi api) {
254269
}
255270

256271
/**
257-
* A TaintTracking Configuration used for tracking flow through APIs.
272+
* A dataflow configuration used for finding new sinks.
258273
* The sources are the parameters of the API and the fields of the enclosing type.
259274
*
260275
* This can be used to generate Sink summaries for APIs, if the API propagates a parameter (or enclosing type field)
261276
* into an existing known sink (then the API itself becomes a sink).
262277
*/
263-
private class PropagateToSinkConfiguration extends TaintTracking::Configuration {
264-
PropagateToSinkConfiguration() {
265-
this = "parameters or fields flowing into sinks" and
266-
any(ActiveConfiguration ac).activateToSinkConfig()
267-
}
278+
module PropagateToSinkConfig implements DataFlow::ConfigSig {
279+
predicate isSource(DataFlow::Node source) { apiSource(source) }
268280

269-
override predicate isSource(DataFlow::Node source) { apiSource(source) }
281+
predicate isSink(DataFlow::Node sink) { ExternalFlow::sinkNode(sink, _) }
270282

271-
override predicate isSink(DataFlow::Node sink) { ExternalFlow::sinkNode(sink, _) }
283+
predicate isBarrier(DataFlow::Node node) { sinkModelSanitizer(node) }
272284

273-
override predicate isSanitizer(DataFlow::Node node) { sinkModelSanitizer(node) }
274-
275-
override DataFlow::FlowFeature getAFeature() {
276-
result instanceof DataFlow::FeatureHasSourceCallContext
277-
}
285+
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
278286
}
279287

288+
private module PropagateToSink = TaintTracking::Make<PropagateToSinkConfig>;
289+
280290
/**
281291
* Gets the sink model(s) of `api`, if there is flow from a parameter to an existing known sink.
282292
*/
283293
string captureSink(DataFlowTargetApi api) {
284-
exists(DataFlow::Node src, DataFlow::Node sink, PropagateToSinkConfiguration config, string kind |
285-
config.hasFlow(src, sink) and
294+
exists(DataFlow::Node src, DataFlow::Node sink, string kind |
295+
PropagateToSink::hasFlow(src, sink) and
286296
ExternalFlow::sinkNode(sink, kind) and
287297
api = src.getEnclosingCallable() and
288298
isRelevantSinkKind(kind) and

csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ private import dotnet
77
private import semmle.code.csharp.commons.Util as Util
88
private import semmle.code.csharp.commons.Collections as Collections
99
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
10-
private import semmle.code.csharp.frameworks.System as System
1110
private import semmle.code.csharp.frameworks.system.linq.Expressions
1211
import semmle.code.csharp.dataflow.ExternalFlow as ExternalFlow
1312
import semmle.code.csharp.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
@@ -110,7 +109,7 @@ predicate isRelevantType(CS::Type t) {
110109
}
111110

112111
/**
113-
* Gets the CSV string representation of the qualifier.
112+
* Gets the MaD string representation of the qualifier.
114113
*/
115114
string qualifierString() { result = "Argument[this]" }
116115

@@ -120,22 +119,15 @@ string parameterAccess(CS::Parameter p) {
120119
else result = "Argument[" + p.getPosition() + "]"
121120
}
122121

123-
/**
124-
* Gets the CSV string representation of the parameter node `p`.
125-
*/
126-
string parameterNodeAsInput(DataFlow::ParameterNode p) {
127-
result = parameterAccess(p.asParameter())
128-
or
129-
result = qualifierString() and p instanceof DataFlowPrivate::InstanceParameterNode
130-
}
122+
class InstanceParameterNode = DataFlowPrivate::InstanceParameterNode;
131123

132124
pragma[nomagic]
133125
private CS::Parameter getParameter(DataFlowImplCommon::ReturnNodeExt node, ParameterPosition pos) {
134126
result = node.getEnclosingCallable().getParameter(pos.getPosition())
135127
}
136128

137129
/**
138-
* Gets the CSV string representation of the the return node `node`.
130+
* Gets the MaD string representation of the the return node `node`.
139131
*/
140132
string returnNodeAsOutput(DataFlowImplCommon::ReturnNodeExt node) {
141133
if node.getKind() instanceof DataFlowImplCommon::ValueReturnKind
@@ -188,9 +180,9 @@ predicate apiSource(DataFlow::Node source) {
188180
}
189181

190182
/**
191-
* Gets the CSV input string representation of `source`.
183+
* Gets the MaD input string representation of `source`.
192184
*/
193-
string asInputArgument(DataFlow::Node source) {
185+
string asInputArgumentSpecific(DataFlow::Node source) {
194186
exists(int pos |
195187
pos = source.(DataFlow::ParameterNode).getParameter().getPosition() and
196188
result = "Argument[" + pos + "]"

csharp/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll renamed to csharp/ql/src/utils/modelgenerator/internal/CaptureSummaryFlowQuery.qll

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
private import CaptureModels
22

3-
private class Activate extends ActiveConfiguration {
4-
override predicate activateThroughFlowConfig() { any() }
5-
}
6-
73
/**
84
* Capture fluent APIs that return `this`.
95
* Example of a fluent API:

java/ql/src/utils/modelgenerator/CaptureNeutralModels.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import internal.CaptureModels
10-
import internal.CaptureSummaryFlow
10+
import internal.CaptureSummaryFlowQuery
1111

1212
from DataFlowTargetApi api, string noflow
1313
where noflow = captureNoFlow(api)

java/ql/src/utils/modelgenerator/CaptureSinkModels.ql

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88

99
import internal.CaptureModels
1010

11-
class Activate extends ActiveConfiguration {
12-
override predicate activateToSinkConfig() { any() }
13-
}
14-
1511
from DataFlowTargetApi api, string sink
1612
where sink = captureSink(api)
1713
select sink order by sink

java/ql/src/utils/modelgenerator/CaptureSourceModels.ql

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88

99
import internal.CaptureModels
1010

11-
class Activate extends ActiveConfiguration {
12-
override predicate activateFromSourceConfig() { any() }
13-
}
14-
1511
from DataFlowTargetApi api, string source
1612
where source = captureSource(api)
1713
select source order by source

0 commit comments

Comments
 (0)