@@ -2,7 +2,7 @@ private import codeql.util.Unit
2
2
private import rust
3
3
private import rust as R
4
4
private import codeql.rust.dataflow.DataFlow
5
- private import codeql.rust.dataflow.internal.DataFlowImpl
5
+ private import codeql.rust.dataflow.internal.DataFlowImpl as DataFlowImpl
6
6
private import codeql.rust.dataflow.internal.Node as Node
7
7
private import codeql.rust.dataflow.internal.Content
8
8
private import codeql.rust.dataflow.FlowSource as FlowSource
@@ -11,7 +11,25 @@ private import codeql.rust.dataflow.internal.TaintTrackingImpl
11
11
private import codeql.mad.modelgenerator.internal.ModelGeneratorImpl
12
12
private import codeql.rust.dataflow.internal.FlowSummaryImpl as FlowSummary
13
13
14
- module ModelGeneratorInput implements ModelGeneratorInputSig< Location , RustDataFlow > {
14
+ private predicate relevant ( Function api ) {
15
+ // Only include functions that have a resolved path.
16
+ api .hasCrateOrigin ( ) and
17
+ api .hasExtendedCanonicalPath ( ) and
18
+ (
19
+ // This excludes closures (these are not exported API endpoints) and
20
+ // functions without a `pub` visiblity. A function can be `pub` without
21
+ // ultimately being exported by a crate, so this is an overapproximation.
22
+ api .hasVisibility ( )
23
+ or
24
+ // If a method implements a public trait it is exposed through the trait.
25
+ // We overapproximate this by including all trait method implementations.
26
+ exists ( Impl impl | impl .hasTrait ( ) and impl .getAssocItemList ( ) .getAssocItem ( _) = api )
27
+ )
28
+ }
29
+
30
+ module ModelGeneratorCommonInput implements
31
+ ModelGeneratorCommonInputSig< Location , DataFlowImpl:: RustDataFlow >
32
+ {
15
33
// NOTE: We are not using type information for now.
16
34
class Type = Unit ;
17
35
@@ -23,55 +41,10 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
23
41
Type getType ( ) { any ( ) }
24
42
}
25
43
26
- Callable getAsExprEnclosingCallable ( NodeExtended node ) { result = node .asExpr ( ) .getScope ( ) }
27
-
28
44
Callable getEnclosingCallable ( NodeExtended node ) {
29
45
result = node .( Node:: Node ) .getEnclosingCallable ( ) .asCfgScope ( )
30
46
}
31
47
32
- Parameter asParameter ( NodeExtended node ) { result = node .asParameter ( ) }
33
-
34
- private predicate relevant ( Function api ) {
35
- // Only include functions that have a resolved path.
36
- api .hasCrateOrigin ( ) and
37
- api .hasExtendedCanonicalPath ( ) and
38
- (
39
- // This excludes closures (these are not exported API endpoints) and
40
- // functions without a `pub` visiblity. A function can be `pub` without
41
- // ultimately being exported by a crate, so this is an overapproximation.
42
- api .hasVisibility ( )
43
- or
44
- // If a method implements a public trait it is exposed through the trait.
45
- // We overapproximate this by including all trait method implementations.
46
- exists ( Impl impl | impl .hasTrait ( ) and impl .getAssocItemList ( ) .getAssocItem ( _) = api )
47
- )
48
- }
49
-
50
- predicate isUninterestingForDataFlowModels ( Callable api ) { none ( ) }
51
-
52
- predicate isUninterestingForHeuristicDataFlowModels ( Callable api ) { none ( ) }
53
-
54
- class SourceOrSinkTargetApi extends Callable {
55
- SourceOrSinkTargetApi ( ) { relevant ( this ) }
56
- }
57
-
58
- class SinkTargetApi extends SourceOrSinkTargetApi { }
59
-
60
- class SourceTargetApi extends SourceOrSinkTargetApi { }
61
-
62
- class SummaryTargetApi extends Callable {
63
- private Callable lift ;
64
-
65
- SummaryTargetApi ( ) {
66
- lift = this and
67
- relevant ( this )
68
- }
69
-
70
- Callable lift ( ) { result = lift }
71
-
72
- predicate isRelevant ( ) { relevant ( this ) }
73
- }
74
-
75
48
predicate isRelevantType ( Type t ) { any ( ) }
76
49
77
50
/**
@@ -82,7 +55,9 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
82
55
string qualifierString ( ) { result = "Argument[self]" }
83
56
84
57
string parameterAccess ( R:: ParamBase p ) {
85
- result = "Argument[" + any ( ParameterPosition pos | p = pos .getParameterIn ( _) ) .toString ( ) + "]"
58
+ result =
59
+ "Argument[" + any ( DataFlowImpl:: ParameterPosition pos | p = pos .getParameterIn ( _) ) .toString ( ) +
60
+ "]"
86
61
}
87
62
88
63
string parameterContentAccess ( R:: ParamBase p ) { result = parameterAccess ( p ) }
@@ -92,12 +67,12 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
92
67
}
93
68
94
69
bindingset [ c]
95
- string paramReturnNodeAsOutput ( Callable c , ParameterPosition pos ) {
70
+ string paramReturnNodeAsOutput ( Callable c , DataFlowImpl :: ParameterPosition pos ) {
96
71
result = paramReturnNodeAsContentOutput ( c , pos )
97
72
}
98
73
99
74
bindingset [ c]
100
- string paramReturnNodeAsContentOutput ( Callable c , ParameterPosition pos ) {
75
+ string paramReturnNodeAsContentOutput ( Callable c , DataFlowImpl :: ParameterPosition pos ) {
101
76
result = parameterContentAccess ( c .getParamList ( ) .getParam ( pos .getPosition ( ) ) )
102
77
or
103
78
pos .isSelf ( ) and result = qualifierString ( )
@@ -107,40 +82,51 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
107
82
result = ret .( Node:: Node ) .getEnclosingCallable ( ) .asCfgScope ( )
108
83
}
109
84
110
- predicate isOwnInstanceAccessNode ( RustDataFlow:: ReturnNode node ) {
85
+ predicate isOwnInstanceAccessNode ( DataFlowImpl :: RustDataFlow:: ReturnNode node ) {
111
86
// This is probably not relevant to implement for Rust, as we only use
112
87
// `captureMixedFlow` which doesn't explicitly distinguish between
113
88
// functions that return `self` and those that don't.
114
89
none ( )
115
90
}
116
91
117
- predicate sinkModelSanitizer ( DataFlow:: Node node ) { none ( ) }
92
+ predicate containerContent ( DataFlow:: ContentSet c ) {
93
+ c .( SingletonContentSet ) .getContent ( ) instanceof ElementContent
94
+ }
118
95
119
- /**
120
- * Holds if `source` is an API entrypoint, i.e., a source of input where data
121
- * can flow in to a library. This is used for creating sink models, as we
122
- * only want to mark functions as sinks if input to the function can reach
123
- * (from an input source) a known sink.
124
- */
125
- predicate apiSource ( DataFlow:: Node source ) { source instanceof DataFlow:: ParameterNode }
96
+ string partialModelRow ( Callable api , int i ) {
97
+ i = 0 and result = api .( Function ) .getCrateOrigin ( ) // crate
98
+ or
99
+ i = 1 and result = api .( Function ) .getExtendedCanonicalPath ( ) // name
100
+ }
126
101
127
- bindingset [ sourceEnclosing , api]
128
- predicate irrelevantSourceSinkApi ( Callable sourceEnclosing , SourceTargetApi api ) { none ( ) }
102
+ string partialNeutralModelRow ( Callable api , int i ) { result = partialModelRow ( api , i ) }
103
+ }
129
104
130
- string getInputArgument ( DataFlow:: Node source ) {
131
- result = "Argument[" + source .( Node:: SourceParameterNode ) .getPosition ( ) .toString ( ) + "]"
132
- }
105
+ private import ModelGeneratorCommonInput
106
+ private import MakeModelGeneratorFactory< Location , DataFlowImpl:: RustDataFlow , RustTaintTracking , ModelGeneratorCommonInput >
133
107
134
- bindingset [ kind]
135
- predicate isRelevantSinkKind ( string kind ) { any ( ) }
108
+ private module SummaryModelGeneratorInput implements SummaryModelGeneratorInputSig {
109
+ class SummaryTargetApi extends Callable {
110
+ private Callable lift ;
136
111
137
- bindingset [ kind]
138
- predicate isRelevantSourceKind ( string kind ) { any ( ) }
112
+ SummaryTargetApi ( ) {
113
+ lift = this and
114
+ relevant ( this )
115
+ }
139
116
140
- predicate containerContent ( DataFlow:: ContentSet c ) {
141
- c .( SingletonContentSet ) .getContent ( ) instanceof ElementContent
117
+ Callable lift ( ) { result = lift }
118
+
119
+ predicate isRelevant ( ) { relevant ( this ) }
142
120
}
143
121
122
+ Callable getAsExprEnclosingCallable ( NodeExtended node ) { result = node .asExpr ( ) .getScope ( ) }
123
+
124
+ Parameter asParameter ( NodeExtended node ) { result = node .asParameter ( ) }
125
+
126
+ predicate isUninterestingForDataFlowModels ( Callable api ) { none ( ) }
127
+
128
+ predicate isUninterestingForHeuristicDataFlowModels ( Callable api ) { none ( ) }
129
+
144
130
predicate isAdditionalContentFlowStep ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) { none ( ) }
145
131
146
132
predicate isField ( DataFlow:: ContentSet c ) {
@@ -159,7 +145,7 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
159
145
private string encodeContent ( ContentSet cs , string arg ) {
160
146
result = FlowSummary:: Input:: encodeContent ( cs , arg )
161
147
or
162
- exists ( Content c | cs = TSingletonContentSet ( c ) |
148
+ exists ( Content c | cs = DataFlowImpl :: TSingletonContentSet ( c ) |
163
149
exists ( int pos |
164
150
pos = c .( FunctionCallArgumentContent ) .getPosition ( ) and
165
151
result = "Parameter" and
@@ -176,18 +162,47 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
176
162
if arg = "" then result = name else result = name + "[" + arg + "]"
177
163
)
178
164
}
165
+ }
179
166
180
- string partialModelRow ( Callable api , int i ) {
181
- i = 0 and result = api .( Function ) .getCrateOrigin ( ) // crate
182
- or
183
- i = 1 and result = api .( Function ) .getExtendedCanonicalPath ( ) // name
167
+ private module SourceModelGeneratorInput implements SourceModelGeneratorInputSig {
168
+ class SourceTargetApi extends Callable {
169
+ SourceTargetApi ( ) { relevant ( this ) }
184
170
}
185
171
186
- string partialNeutralModelRow ( Callable api , int i ) { result = partialModelRow ( api , i ) }
172
+ bindingset [ sourceEnclosing, api]
173
+ predicate irrelevantSourceSinkApi ( Callable sourceEnclosing , SourceTargetApi api ) { none ( ) }
174
+
175
+ bindingset [ kind]
176
+ predicate isRelevantSourceKind ( string kind ) { any ( ) }
187
177
188
178
predicate sourceNode ( DataFlow:: Node node , string kind ) { FlowSource:: sourceNode ( node , kind ) }
179
+ }
180
+
181
+ private module SinkModelGeneratorInput implements SinkModelGeneratorInputSig {
182
+ class SinkTargetApi extends Callable {
183
+ SinkTargetApi ( ) { relevant ( this ) }
184
+ }
185
+
186
+ predicate sinkModelSanitizer ( DataFlow:: Node node ) { none ( ) }
187
+
188
+ /**
189
+ * Holds if `source` is an API entrypoint, i.e., a source of input where data
190
+ * can flow in to a library. This is used for creating sink models, as we
191
+ * only want to mark functions as sinks if input to the function can reach
192
+ * (from an input source) a known sink.
193
+ */
194
+ predicate apiSource ( DataFlow:: Node source ) { source instanceof DataFlow:: ParameterNode }
195
+
196
+ string getInputArgument ( DataFlow:: Node source ) {
197
+ result = "Argument[" + source .( Node:: SourceParameterNode ) .getPosition ( ) .toString ( ) + "]"
198
+ }
199
+
200
+ bindingset [ kind]
201
+ predicate isRelevantSinkKind ( string kind ) { any ( ) }
189
202
190
203
predicate sinkNode ( DataFlow:: Node node , string kind ) { FlowSink:: sinkNode ( node , kind ) }
191
204
}
192
205
193
- import MakeModelGenerator< Location , RustDataFlow , RustTaintTracking , ModelGeneratorInput >
206
+ import MakeSummaryModelGenerator< SummaryModelGeneratorInput > as SummaryModels
207
+ import MakeSourceModelGenerator< SourceModelGeneratorInput > as SourceModels
208
+ import MakeSinkModelGenerator< SinkModelGeneratorInput > as SinkModels
0 commit comments