Skip to content

Commit 2d2d32a

Browse files
authored
Merge pull request github#12732 from michaelnebel/csharp/refactorunittests
C#: Re-factor data flow unit tests to use the new API.
2 parents afd577c + c787bb2 commit 2d2d32a

File tree

25 files changed

+131
-1475
lines changed

25 files changed

+131
-1475
lines changed

csharp/ql/test/TestUtilities/InlineFlowTest.qll

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
* Example for a test.ql:
55
* ```ql
66
* import csharp
7-
* import DataFlow::PathGraph
7+
* import DefaultValueFlow::PathGraph
88
* import TestUtilities.InlineFlowTest
99
*
10-
* from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultValueFlowConf conf
11-
* where conf.hasFlowPath(source, sink)
10+
* from DefaultValueFlow::PathNode source, DefaultValueFlow::PathNode sink
11+
* where DefaultValueFlow::flowPath(source, sink)
1212
* select sink, source, sink, "$@", source, source.toString()
13+
*
1314
* ```
1415
*
1516
* To declare expecations, you can use the $hasTaintFlow or $hasValueFlow comments within the test source files.
@@ -56,25 +57,17 @@ private predicate defaultSink(DataFlow::Node sink) {
5657
)
5758
}
5859

59-
class DefaultValueFlowConf extends DataFlow::Configuration {
60-
DefaultValueFlowConf() { this = "qltest:defaultValueFlowConf" }
61-
62-
override predicate isSource(DataFlow::Node n) { defaultSource(n) }
60+
module DefaultFlowConfig implements DataFlow::ConfigSig {
61+
predicate isSource(DataFlow::Node n) { defaultSource(n) }
6362

64-
override predicate isSink(DataFlow::Node n) { defaultSink(n) }
63+
predicate isSink(DataFlow::Node n) { defaultSink(n) }
6564

66-
override int fieldFlowBranchLimit() { result = 1000 }
65+
int fieldFlowBranchLimit() { result = 1000 }
6766
}
6867

69-
class DefaultTaintFlowConf extends TaintTracking::Configuration {
70-
DefaultTaintFlowConf() { this = "qltest:defaultTaintFlowConf" }
68+
module DefaultValueFlow = DataFlow::Global<DefaultFlowConfig>;
7169

72-
override predicate isSource(DataFlow::Node n) { defaultSource(n) }
73-
74-
override predicate isSink(DataFlow::Node n) { defaultSink(n) }
75-
76-
override int fieldFlowBranchLimit() { result = 1000 }
77-
}
70+
module DefaultTaintFlow = TaintTracking::Global<DefaultFlowConfig>;
7871

7972
private string getSourceArgString(DataFlow::Node src) {
8073
defaultSource(src) and
@@ -88,23 +81,19 @@ class InlineFlowTest extends InlineExpectationsTest {
8881

8982
override predicate hasActualResult(Location location, string element, string tag, string value) {
9083
tag = "hasValueFlow" and
91-
exists(DataFlow::Node src, DataFlow::Node sink | getValueFlowConfig().hasFlow(src, sink) |
84+
exists(DataFlow::Node src, DataFlow::Node sink | DefaultValueFlow::flow(src, sink) |
9285
sink.getLocation() = location and
9386
element = sink.toString() and
9487
if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = ""
9588
)
9689
or
9790
tag = "hasTaintFlow" and
9891
exists(DataFlow::Node src, DataFlow::Node sink |
99-
getTaintFlowConfig().hasFlow(src, sink) and not getValueFlowConfig().hasFlow(src, sink)
92+
DefaultTaintFlow::flow(src, sink) and not DefaultValueFlow::flow(src, sink)
10093
|
10194
sink.getLocation() = location and
10295
element = sink.toString() and
10396
if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = ""
10497
)
10598
}
106-
107-
DataFlow::Configuration getValueFlowConfig() { result = any(DefaultValueFlowConf config) }
108-
109-
DataFlow::Configuration getTaintFlowConfig() { result = any(DefaultTaintFlowConf config) }
11099
}

csharp/ql/test/library-tests/cil/dataflow/TaintTracking.ql

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ import semmle.code.csharp.dataflow.TaintTracking3
66
import semmle.code.csharp.dataflow.TaintTracking4
77
import semmle.code.csharp.dataflow.TaintTracking5
88

9-
class FlowConfig extends TaintTracking::Configuration {
10-
FlowConfig() { this = "FlowConfig" }
9+
module FlowConfig implements DataFlow::ConfigSig {
10+
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof Literal }
1111

12-
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof Literal }
13-
14-
override predicate isSink(DataFlow::Node sink) {
12+
predicate isSink(DataFlow::Node sink) {
1513
exists(LocalVariable decl | sink.asExpr() = decl.getInitializer())
1614
}
1715
}
1816

19-
from FlowConfig config, DataFlow::Node source, DataFlow::Node sink
20-
where config.hasFlow(source, sink)
17+
module Flow = TaintTracking::Global<FlowConfig>;
18+
19+
from DataFlow::Node source, DataFlow::Node sink
20+
where Flow::flow(source, sink)
2121
select source, sink

csharp/ql/test/library-tests/csharp7/GlobalTaintTracking.ql

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,18 @@
33
*/
44

55
import csharp
6-
import DataFlow::PathGraph
6+
import Taint::PathGraph
77

8-
class DataflowConfiguration extends TaintTracking::Configuration {
9-
DataflowConfiguration() { this = "taint tracking configuration" }
8+
module TaintConfig implements DataFlow::ConfigSig {
9+
predicate isSource(DataFlow::Node source) { source.asExpr().(Expr).getValue() = "tainted" }
1010

11-
override predicate isSource(DataFlow::Node source) {
12-
source.asExpr().(Expr).getValue() = "tainted"
13-
}
14-
15-
override predicate isSink(DataFlow::Node sink) {
11+
predicate isSink(DataFlow::Node sink) {
1612
exists(LocalVariable v | sink.asExpr() = v.getInitializer())
1713
}
1814
}
1915

20-
from DataFlow::PathNode source, DataFlow::PathNode sink, DataflowConfiguration conf
21-
where conf.hasFlowPath(source, sink)
16+
module Taint = TaintTracking::Global<TaintConfig>;
17+
18+
from Taint::PathNode source, Taint::PathNode sink
19+
where Taint::flowPath(source, sink)
2220
select source, source, sink, "$@", sink, sink.toString()

csharp/ql/test/library-tests/dataflow/async/Async.ql

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import csharp
2-
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph
2+
import Taint::PathGraph
33

44
class MySink extends DataFlow::ExprNode {
55
MySink() {
@@ -19,15 +19,15 @@ class MySource extends DataFlow::ParameterNode {
1919
}
2020
}
2121

22-
class MyConfig extends TaintTracking::Configuration {
23-
MyConfig() { this = "MyConfig" }
22+
module TaintConfig implements DataFlow::ConfigSig {
23+
predicate isSource(DataFlow::Node source) { source instanceof MySource }
2424

25-
override predicate isSource(DataFlow::Node source) { source instanceof MySource }
26-
27-
override predicate isSink(DataFlow::Node sink) { sink instanceof MySink }
25+
predicate isSink(DataFlow::Node sink) { sink instanceof MySink }
2826
}
2927

30-
from MyConfig c, DataFlow::PathNode source, DataFlow::PathNode sink
31-
where c.hasFlowPath(source, sink)
28+
module Taint = TaintTracking::Global<TaintConfig>;
29+
30+
from Taint::PathNode source, Taint::PathNode sink
31+
where Taint::flowPath(source, sink)
3232
select sink.getNode(), source, sink, "$@ flows to here and is used.", source.getNode(),
3333
"User-provided value"

csharp/ql/test/library-tests/dataflow/callablereturnsarg/Common.qll

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,34 +10,38 @@ private predicate outRefDef(DataFlow::ExprNode ne, int outRef) {
1010
)
1111
}
1212

13-
class Configuration extends DataFlow::Configuration {
14-
Configuration() { this = "Configuration" }
13+
module Config implements DataFlow::ConfigSig {
14+
predicate isSource(DataFlow::Node source) { source instanceof DataFlow::ParameterNode }
1515

16-
override predicate isSource(DataFlow::Node source) { source instanceof DataFlow::ParameterNode }
17-
18-
override predicate isSink(DataFlow::Node sink) {
16+
predicate isSink(DataFlow::Node sink) {
1917
any(Callable c).canReturn(sink.asExpr()) or outRefDef(sink, _)
2018
}
2119

22-
override predicate isBarrier(DataFlow::Node node) {
20+
predicate isBarrier(DataFlow::Node node) {
2321
exists(AbstractValues::NullValue nv | node.(GuardedDataFlowNode).mustHaveValue(nv) |
2422
nv.isNull()
2523
)
2624
}
2725
}
2826

29-
predicate flowOutFromParameter(DataFlow::Configuration c, Parameter p) {
30-
exists(DataFlow::ExprNode ne, DataFlow::ParameterNode np |
31-
p.getCallable().canReturn(ne.getExpr()) and
32-
np.getParameter() = p and
33-
c.hasFlow(np, ne)
34-
)
35-
}
27+
module FlowOut<DataFlow::GlobalFlowSig Input> {
28+
predicate flowOutFromParameter(Parameter p) {
29+
exists(DataFlow::ExprNode ne, DataFlow::ParameterNode np |
30+
p.getCallable().canReturn(ne.getExpr()) and
31+
np.getParameter() = p and
32+
Input::flow(np, ne)
33+
)
34+
}
3635

37-
predicate flowOutFromParameterOutOrRef(DataFlow::Configuration c, Parameter p, int outRef) {
38-
exists(DataFlow::ExprNode ne, DataFlow::ParameterNode np |
39-
outRefDef(ne, outRef) and
40-
np.getParameter() = p and
41-
c.hasFlow(np, ne)
42-
)
36+
predicate flowOutFromParameterOutOrRef(Parameter p, int outRef) {
37+
exists(DataFlow::ExprNode ne, DataFlow::ParameterNode np |
38+
outRefDef(ne, outRef) and
39+
np.getParameter() = p and
40+
Input::flow(np, ne)
41+
)
42+
}
4343
}
44+
45+
module Data = FlowOut<DataFlow::Global<Config>>;
46+
47+
module Taint = FlowOut<TaintTracking::Global<Config>>;
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import csharp
22
import Common
33

4-
from Configuration c, Parameter p, int outRefArg
4+
from Parameter p, int outRefArg
55
where
6-
flowOutFromParameter(c, p) and outRefArg = -1
6+
Data::flowOutFromParameter(p) and outRefArg = -1
77
or
8-
flowOutFromParameterOutOrRef(c, p, outRefArg)
8+
Data::flowOutFromParameterOutOrRef(p, outRefArg)
99
select p.getCallable(), p.getPosition(), outRefArg
Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,9 @@
11
import csharp
22
import Common
33

4-
class TaintTrackingConfiguration extends TaintTracking::Configuration {
5-
Configuration c;
6-
7-
TaintTrackingConfiguration() { this = "Taint " + c }
8-
9-
override predicate isSource(DataFlow::Node source) { c.isSource(source) }
10-
11-
override predicate isSink(DataFlow::Node sink) { c.isSink(sink) }
12-
13-
override predicate isSanitizer(DataFlow::Node node) { c.isBarrier(node) }
14-
}
15-
16-
from TaintTrackingConfiguration c, Parameter p, int outRefArg
4+
from Parameter p, int outRefArg
175
where
18-
flowOutFromParameter(c, p) and outRefArg = -1
6+
Taint::flowOutFromParameter(p) and outRefArg = -1
197
or
20-
flowOutFromParameterOutOrRef(c, p, outRefArg)
8+
Taint::flowOutFromParameterOutOrRef(p, outRefArg)
219
select p.getCallable(), p.getPosition(), outRefArg

csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
invalidModelRow
12
edges
23
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:10:29:10:32 | access to local variable arg1 : Object |
34
| ExternalFlow.cs:10:29:10:32 | access to local variable arg1 : Object | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes |
@@ -162,7 +163,6 @@ nodes
162163
| ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | semmle.label | call to method MixedFlowArgs |
163164
| ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object |
164165
subpaths
165-
invalidModelRow
166166
#select
167167
| ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | $@ | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | object creation of type Object : Object |
168168
| ExternalFlow.cs:18:18:18:24 | access to local variable argOut1 | ExternalFlow.cs:15:29:15:40 | object creation of type Object : Object | ExternalFlow.cs:18:18:18:24 | access to local variable argOut1 | $@ | ExternalFlow.cs:15:29:15:40 | object creation of type Object : Object | object creation of type Object : Object |

csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ql

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,23 @@
33
*/
44

55
import csharp
6-
import DataFlow::PathGraph
76
import semmle.code.csharp.dataflow.ExternalFlow
7+
import Taint::PathGraph
88
import ModelValidation
99

10-
class Conf extends TaintTracking::Configuration {
11-
Conf() { this = "ExternalFlow" }
10+
module TaintConfig implements DataFlow::ConfigSig {
11+
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ObjectCreation }
1212

13-
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ObjectCreation }
14-
15-
override predicate isSink(DataFlow::Node sink) {
13+
predicate isSink(DataFlow::Node sink) {
1614
exists(MethodCall mc |
1715
mc.getTarget().hasName("Sink") and
1816
mc.getAnArgument() = sink.asExpr()
1917
)
2018
}
2119
}
2220

21+
module Taint = TaintTracking::Global<TaintConfig>;
22+
2323
/**
2424
* Simulate that methods with summaries are not included in the source code.
2525
* This is relevant for dataflow analysis using summaries tagged as generated.
@@ -28,6 +28,6 @@ private class MyMethod extends Method {
2828
override predicate fromSource() { none() }
2929
}
3030

31-
from DataFlow::PathNode source, DataFlow::PathNode sink, Conf conf
32-
where conf.hasFlowPath(source, sink)
31+
from Taint::PathNode source, Taint::PathNode sink
32+
where Taint::flowPath(source, sink)
3333
select sink, source, sink, "$@", source, source.toString()

0 commit comments

Comments
 (0)