4
4
* Example for a test.ql:
5
5
* ```ql
6
6
* import csharp
7
- * import DefaultValueFlow::PathGraph
8
7
* import TestUtilities.InlineFlowTest
8
+ * import DefaultFlowTest
9
+ * import PathGraph
9
10
*
10
- * from DefaultValueFlow:: PathNode source, DefaultValueFlow:: PathNode sink
11
- * where DefaultValueFlow:: flowPath(source, sink)
11
+ * from PathNode source, PathNode sink
12
+ * where flowPath(source, sink)
12
13
* select sink, source, sink, "$@", source, source.toString()
13
14
*
14
15
* ```
32
33
* }
33
34
* ```
34
35
*
35
- * If you're not interested in a specific flow type, you can disable either value or taint flow expectations as follows:
36
- * ```ql
37
- * class HasFlowTest extends InlineFlowTest {
38
- * override DataFlow::Configuration getTaintFlowConfig() { none() }
39
- *
40
- * override DataFlow::Configuration getValueFlowConfig() { none() }
41
- * }
42
- * ```
36
+ * If you are only interested in value flow, then instead of importing `DefaultFlowTest`, you can import
37
+ * `ValueFlowTest<DefaultFlowConfig>`. Similarly, if you are only interested in taint flow, then instead of
38
+ * importing `DefaultFlowTest`, you can import `TaintFlowTest<DefaultFlowConfig>`. In both cases
39
+ * `DefaultFlowConfig` can be replaced by another implementation of `DataFlow::ConfigSig`.
43
40
*
44
41
* If you need more fine-grained tuning, consider implementing a test using `InlineExpectationsTest`.
45
42
*/
46
43
47
44
import csharp
48
45
import TestUtilities.InlineExpectationsTest
49
46
50
- private predicate defaultSource ( DataFlow:: Node src ) {
51
- src .asExpr ( ) .( MethodCall ) .getTarget ( ) .getUndecoratedName ( ) = [ "Source" , "Taint" ]
47
+ private predicate defaultSource ( DataFlow:: Node source ) {
48
+ source .asExpr ( ) .( MethodCall ) .getTarget ( ) .getUndecoratedName ( ) = [ "Source" , "Taint" ]
52
49
}
53
50
54
51
private predicate defaultSink ( DataFlow:: Node sink ) {
@@ -58,42 +55,66 @@ private predicate defaultSink(DataFlow::Node sink) {
58
55
}
59
56
60
57
module DefaultFlowConfig implements DataFlow:: ConfigSig {
61
- predicate isSource ( DataFlow:: Node n ) { defaultSource ( n ) }
58
+ predicate isSource ( DataFlow:: Node source ) { defaultSource ( source ) }
62
59
63
- predicate isSink ( DataFlow:: Node n ) { defaultSink ( n ) }
60
+ predicate isSink ( DataFlow:: Node sink ) { defaultSink ( sink ) }
64
61
65
62
int fieldFlowBranchLimit ( ) { result = 1000 }
66
63
}
67
64
68
- module DefaultValueFlow = DataFlow:: Global< DefaultFlowConfig > ;
65
+ private module NoFlowConfig implements DataFlow:: ConfigSig {
66
+ predicate isSource ( DataFlow:: Node source ) { none ( ) }
69
67
70
- module DefaultTaintFlow = TaintTracking:: Global< DefaultFlowConfig > ;
68
+ predicate isSink ( DataFlow:: Node sink ) { none ( ) }
69
+ }
71
70
72
71
private string getSourceArgString ( DataFlow:: Node src ) {
73
72
defaultSource ( src ) and
74
73
src .asExpr ( ) .( MethodCall ) .getAnArgument ( ) .getValue ( ) = result
75
74
}
76
75
77
- class InlineFlowTest extends InlineExpectationsTest {
78
- InlineFlowTest ( ) { this = "HasFlowTest" }
79
-
80
- override string getARelevantTag ( ) { result = [ "hasValueFlow" , "hasTaintFlow" ] }
81
-
82
- override predicate hasActualResult ( Location location , string element , string tag , string value ) {
83
- tag = "hasValueFlow" and
84
- exists ( DataFlow:: Node src , DataFlow:: Node sink | DefaultValueFlow:: flow ( src , sink ) |
85
- sink .getLocation ( ) = location and
86
- element = sink .toString ( ) and
87
- if exists ( getSourceArgString ( src ) ) then value = getSourceArgString ( src ) else value = ""
88
- )
89
- or
90
- tag = "hasTaintFlow" and
91
- exists ( DataFlow:: Node src , DataFlow:: Node sink |
92
- DefaultTaintFlow:: flow ( src , sink ) and not DefaultValueFlow:: flow ( src , sink )
93
- |
94
- sink .getLocation ( ) = location and
95
- element = sink .toString ( ) and
96
- if exists ( getSourceArgString ( src ) ) then value = getSourceArgString ( src ) else value = ""
97
- )
76
+ module FlowTest< DataFlow:: ConfigSig ValueFlowConfig, DataFlow:: ConfigSig TaintFlowConfig> {
77
+ module ValueFlow = DataFlow:: Global< ValueFlowConfig > ;
78
+
79
+ module TaintFlow = TaintTracking:: Global< TaintFlowConfig > ;
80
+
81
+ private module InlineTest implements TestSig {
82
+ string getARelevantTag ( ) { result = [ "hasValueFlow" , "hasTaintFlow" ] }
83
+
84
+ predicate hasActualResult ( Location location , string element , string tag , string value ) {
85
+ tag = "hasValueFlow" and
86
+ exists ( DataFlow:: Node src , DataFlow:: Node sink | ValueFlow:: flow ( src , sink ) |
87
+ sink .getLocation ( ) = location and
88
+ element = sink .toString ( ) and
89
+ if exists ( getSourceArgString ( src ) ) then value = getSourceArgString ( src ) else value = ""
90
+ )
91
+ or
92
+ tag = "hasTaintFlow" and
93
+ exists ( DataFlow:: Node src , DataFlow:: Node sink |
94
+ TaintFlow:: flow ( src , sink ) and not ValueFlow:: flow ( src , sink )
95
+ |
96
+ sink .getLocation ( ) = location and
97
+ element = sink .toString ( ) and
98
+ if exists ( getSourceArgString ( src ) ) then value = getSourceArgString ( src ) else value = ""
99
+ )
100
+ }
98
101
}
102
+
103
+ import MakeTest< InlineTest >
104
+ import DataFlow:: MergePathGraph< ValueFlow:: PathNode , TaintFlow:: PathNode , ValueFlow:: PathGraph , TaintFlow:: PathGraph >
105
+
106
+ predicate flowPath ( PathNode source , PathNode sink ) {
107
+ ValueFlow:: flowPath ( source .asPathNode1 ( ) , sink .asPathNode1 ( ) ) or
108
+ TaintFlow:: flowPath ( source .asPathNode2 ( ) , sink .asPathNode2 ( ) )
109
+ }
110
+ }
111
+
112
+ module DefaultFlowTest = FlowTest< DefaultFlowConfig , DefaultFlowConfig > ;
113
+
114
+ module ValueFlowTest< DataFlow:: ConfigSig ValueFlowConfig> {
115
+ import FlowTest< ValueFlowConfig , NoFlowConfig >
116
+ }
117
+
118
+ module TaintFlowTest< DataFlow:: ConfigSig TaintFlowConfig> {
119
+ import FlowTest< NoFlowConfig , TaintFlowConfig >
99
120
}
0 commit comments