@@ -21,21 +21,97 @@ import AutomodelEndpointTypes as AutomodelEndpointTypes
21
21
22
22
newtype JavaRelatedLocationType = CallContext ( )
23
23
24
+ newtype TApplicationModeEndpoint =
25
+ TExplicitArgument ( Call call , DataFlow:: Node arg ) {
26
+ exists ( Argument argExpr |
27
+ arg .asExpr ( ) = argExpr and call = argExpr .getCall ( ) and not argExpr .isVararg ( )
28
+ )
29
+ } or
30
+ TInstanceArgument ( Call call , DataFlow:: Node arg ) { arg = DataFlow:: getInstanceArgument ( call ) } or
31
+ TImplicitVarargsArray ( Call call , DataFlow:: Node arg , int idx ) {
32
+ exists ( Argument argExpr |
33
+ arg .asExpr ( ) = argExpr and
34
+ call .getArgument ( idx ) = argExpr and
35
+ argExpr .isVararg ( ) and
36
+ not exists ( int i | i < idx and call .getArgument ( i ) .( Argument ) .isVararg ( ) )
37
+ )
38
+ }
39
+
40
+ /**
41
+ * An endpoint is a node that is a candidate for modeling.
42
+ */
43
+ abstract private class ApplicationModeEndpoint extends TApplicationModeEndpoint {
44
+ abstract predicate isArgOf ( Call c , int idx ) ;
45
+
46
+ Call getCall ( ) { this .isArgOf ( result , _) }
47
+
48
+ int getArgIndex ( ) { this .isArgOf ( _, result ) }
49
+
50
+ abstract Top asTop ( ) ;
51
+
52
+ abstract DataFlow:: Node asNode ( ) ;
53
+
54
+ abstract string toString ( ) ;
55
+ }
56
+
24
57
/**
25
58
* A class representing nodes that are arguments to calls.
26
59
*/
27
- private class ArgumentNode extends DataFlow:: Node {
28
- Call c ;
60
+ class ExplicitArgument extends ApplicationModeEndpoint , TExplicitArgument {
61
+ Call call ;
62
+ DataFlow:: Node arg ;
29
63
30
- ArgumentNode ( ) {
31
- exists ( Argument arg | this .asExpr ( ) = arg and not arg .isVararg ( ) and c = arg .getCall ( ) )
32
- or
33
- this .( DataFlow:: ImplicitVarargsArray ) .getCall ( ) = c
34
- or
35
- this = DataFlow:: getInstanceArgument ( c )
64
+ ExplicitArgument ( ) { this = TExplicitArgument ( call , arg ) }
65
+
66
+ override predicate isArgOf ( Call c , int idx ) { c = call and this .asTop ( ) = c .getArgument ( idx ) }
67
+
68
+ override Top asTop ( ) { result = arg .asExpr ( ) }
69
+
70
+ override DataFlow:: Node asNode ( ) { result = arg }
71
+
72
+ override string toString ( ) { result = arg .toString ( ) }
73
+ }
74
+
75
+ class InstanceArgument extends ApplicationModeEndpoint , TInstanceArgument {
76
+ Call call ;
77
+ DataFlow:: Node arg ;
78
+
79
+ InstanceArgument ( ) { this = TInstanceArgument ( call , arg ) }
80
+
81
+ override predicate isArgOf ( Call c , int idx ) {
82
+ c = call and this .asTop ( ) = c .getQualifier ( ) and idx = - 1
36
83
}
37
84
38
- Call getCall ( ) { result = c }
85
+ override Top asTop ( ) { if exists ( arg .asExpr ( ) ) then result = arg .asExpr ( ) else result = call }
86
+
87
+ override DataFlow:: Node asNode ( ) { result = arg }
88
+
89
+ override string toString ( ) { result = arg .toString ( ) }
90
+ }
91
+
92
+ /**
93
+ * An endpoint that represents an implicit varargs array.
94
+ * We choose to represent the varargs array as a single endpoint, rather than as multiple endpoints.
95
+ *
96
+ * This avoids the problem of having to deal with redundant endpoints downstream.
97
+ *
98
+ * In order to be able to distinguish between varargs endpoints and regular endpoints, we export the `isVarargsArray`
99
+ * meta data field in the extraction queries.
100
+ */
101
+ class ImplicitVarargsArray extends ApplicationModeEndpoint , TImplicitVarargsArray {
102
+ Call call ;
103
+ DataFlow:: Node vararg ;
104
+ int idx ;
105
+
106
+ ImplicitVarargsArray ( ) { this = TImplicitVarargsArray ( call , vararg , idx ) }
107
+
108
+ override predicate isArgOf ( Call c , int i ) { c = call and i = idx }
109
+
110
+ override Top asTop ( ) { result = this .getCall ( ) }
111
+
112
+ override DataFlow:: Node asNode ( ) { result = vararg }
113
+
114
+ override string toString ( ) { result = vararg .toString ( ) }
39
115
}
40
116
41
117
/**
@@ -47,7 +123,7 @@ private class ArgumentNode extends DataFlow::Node {
47
123
*/
48
124
module ApplicationCandidatesImpl implements SharedCharacteristics:: CandidateSig {
49
125
// for documentation of the implementations here, see the QLDoc in the CandidateSig signature module.
50
- class Endpoint = ArgumentNode ;
126
+ class Endpoint = ApplicationModeEndpoint ;
51
127
52
128
class EndpointType = AutomodelEndpointTypes:: EndpointType ;
53
129
@@ -61,18 +137,18 @@ module ApplicationCandidatesImpl implements SharedCharacteristics::CandidateSig
61
137
predicate isSanitizer ( Endpoint e , EndpointType t ) {
62
138
exists ( t ) and
63
139
(
64
- e .getType ( ) instanceof BoxedType
140
+ e .asNode ( ) . getType ( ) instanceof BoxedType
65
141
or
66
- e .getType ( ) instanceof PrimitiveType
142
+ e .asNode ( ) . getType ( ) instanceof PrimitiveType
67
143
or
68
- e .getType ( ) instanceof NumberType
144
+ e .asNode ( ) . getType ( ) instanceof NumberType
69
145
)
70
146
or
71
147
t instanceof AutomodelEndpointTypes:: PathInjectionSinkType and
72
- e instanceof PathSanitizer:: PathInjectionSanitizer
148
+ e . asNode ( ) instanceof PathSanitizer:: PathInjectionSanitizer
73
149
}
74
150
75
- RelatedLocation asLocation ( Endpoint e ) { result = e .asExpr ( ) }
151
+ RelatedLocation asLocation ( Endpoint e ) { result = e .asTop ( ) }
76
152
77
153
predicate isKnownKind = AutomodelJavaUtil:: isKnownKind / 2 ;
78
154
@@ -98,16 +174,7 @@ module ApplicationCandidatesImpl implements SharedCharacteristics::CandidateSig
98
174
ApplicationModeGetCallable:: getCallable ( e ) .hasQualifiedName ( package , type , name ) and
99
175
signature = ExternalFlow:: paramsString ( ApplicationModeGetCallable:: getCallable ( e ) ) and
100
176
ext = "" and
101
- (
102
- exists ( Call c , int argIdx |
103
- e .asExpr ( ) = c .getArgument ( argIdx ) and
104
- input = AutomodelJavaUtil:: getArgumentForIndex ( argIdx )
105
- )
106
- or
107
- exists ( Call c |
108
- e .asExpr ( ) = c .getQualifier ( ) and input = AutomodelJavaUtil:: getArgumentForIndex ( - 1 )
109
- )
110
- )
177
+ input = AutomodelJavaUtil:: getArgumentForIndex ( e .getArgIndex ( ) )
111
178
}
112
179
113
180
/**
@@ -118,7 +185,7 @@ module ApplicationCandidatesImpl implements SharedCharacteristics::CandidateSig
118
185
*/
119
186
RelatedLocation getRelatedLocation ( Endpoint e , RelatedLocationType type ) {
120
187
type = CallContext ( ) and
121
- result = any ( Call c | e . asExpr ( ) = [ c . getAnArgument ( ) , c . getQualifier ( ) ] )
188
+ result = e . getCall ( )
122
189
}
123
190
}
124
191
@@ -132,20 +199,15 @@ private module ApplicationModeGetCallable implements AutomodelSharedGetCallable:
132
199
/**
133
200
* Returns the API callable being modeled.
134
201
*/
135
- Callable getCallable ( Endpoint e ) {
136
- exists ( Call c |
137
- e .asExpr ( ) = [ c .getAnArgument ( ) , c .getQualifier ( ) ] and
138
- result = c .getCallee ( )
139
- )
140
- }
202
+ Callable getCallable ( Endpoint e ) { result = e .getCall ( ) .getCallee ( ) }
141
203
}
142
204
143
205
/**
144
206
* Contains endpoints that are defined in QL code rather than as a MaD model. Ideally this predicate
145
207
* should be empty.
146
208
*/
147
209
private predicate isCustomSink ( Endpoint e , string kind ) {
148
- e instanceof QueryInjectionSink and kind = "sql"
210
+ e . asNode ( ) instanceof QueryInjectionSink and kind = "sql"
149
211
}
150
212
151
213
module CharacteristicsImpl =
@@ -167,23 +229,21 @@ class ApplicationModeMetadataExtractor extends string {
167
229
168
230
predicate hasMetadata (
169
231
Endpoint e , string package , string type , string subtypes , string name , string signature ,
170
- string input
232
+ string input , string isVarargsArray
171
233
) {
172
- exists ( Call call , Callable callable , int argIdx |
173
- call .getCallee ( ) = callable and
174
- (
175
- e .asExpr ( ) = call .getArgument ( argIdx )
176
- or
177
- e .asExpr ( ) = call .getQualifier ( ) and argIdx = - 1
178
- ) and
179
- input = AutomodelJavaUtil:: getArgumentForIndex ( argIdx ) and
234
+ exists ( Callable callable |
235
+ e .getCall ( ) .getCallee ( ) = callable and
236
+ input = AutomodelJavaUtil:: getArgumentForIndex ( e .getArgIndex ( ) ) and
180
237
package = callable .getDeclaringType ( ) .getPackage ( ) .getName ( ) and
181
238
// we're using the erased types because the MaD convention is to not specify type parameters.
182
239
// Whether something is or isn't a sink doesn't usually depend on the type parameters.
183
240
type = callable .getDeclaringType ( ) .getErasure ( ) .( RefType ) .nestedName ( ) and
184
241
subtypes = AutomodelJavaUtil:: considerSubtypes ( callable ) .toString ( ) and
185
242
name = callable .getName ( ) and
186
- signature = ExternalFlow:: paramsString ( callable )
243
+ signature = ExternalFlow:: paramsString ( callable ) and
244
+ if e instanceof ImplicitVarargsArray
245
+ then isVarargsArray = "true"
246
+ else isVarargsArray = "false"
187
247
)
188
248
}
189
249
}
@@ -253,28 +313,10 @@ private class IsMaDTaintStepCharacteristic extends CharacteristicsImpl::NotASink
253
313
IsMaDTaintStepCharacteristic ( ) { this = "taint step" }
254
314
255
315
override predicate appliesToEndpoint ( Endpoint e ) {
256
- FlowSummaryImpl:: Private:: Steps:: summaryThroughStepValue ( e , _, _) or
257
- FlowSummaryImpl:: Private:: Steps:: summaryThroughStepTaint ( e , _, _) or
258
- FlowSummaryImpl:: Private:: Steps:: summaryGetterStep ( e , _, _, _) or
259
- FlowSummaryImpl:: Private:: Steps:: summarySetterStep ( e , _, _, _)
260
- }
261
- }
262
-
263
- /**
264
- * A negative characteristic that filters out qualifiers that are classes (i.e. static calls). These
265
- * are unlikely to have any non-trivial flow going into them.
266
- *
267
- * Technically, an accessed type _could_ come from outside of the source code, but there's not
268
- * much likelihood of that being user-controlled.
269
- */
270
- private class ClassQualifierCharacteristic extends CharacteristicsImpl:: NotASinkCharacteristic {
271
- ClassQualifierCharacteristic ( ) { this = "class qualifier" }
272
-
273
- override predicate appliesToEndpoint ( Endpoint e ) {
274
- exists ( Call c |
275
- e .asExpr ( ) = c .getQualifier ( ) and
276
- c .getQualifier ( ) instanceof TypeAccess
277
- )
316
+ FlowSummaryImpl:: Private:: Steps:: summaryThroughStepValue ( e .asNode ( ) , _, _) or
317
+ FlowSummaryImpl:: Private:: Steps:: summaryThroughStepTaint ( e .asNode ( ) , _, _) or
318
+ FlowSummaryImpl:: Private:: Steps:: summaryGetterStep ( e .asNode ( ) , _, _, _) or
319
+ FlowSummaryImpl:: Private:: Steps:: summarySetterStep ( e .asNode ( ) , _, _, _)
278
320
}
279
321
}
280
322
@@ -351,7 +393,7 @@ private class OtherArgumentToModeledMethodCharacteristic extends Characteristics
351
393
private class FunctionValueCharacteristic extends CharacteristicsImpl:: LikelyNotASinkCharacteristic {
352
394
FunctionValueCharacteristic ( ) { this = "function value" }
353
395
354
- override predicate appliesToEndpoint ( Endpoint e ) { e .asExpr ( ) instanceof FunctionalExpr }
396
+ override predicate appliesToEndpoint ( Endpoint e ) { e .asNode ( ) . asExpr ( ) instanceof FunctionalExpr }
355
397
}
356
398
357
399
/**
@@ -371,12 +413,12 @@ private class CannotBeTaintedCharacteristic extends CharacteristicsImpl::LikelyN
371
413
* Holds if the node `n` is known as the predecessor in a modeled flow step.
372
414
*/
373
415
private predicate isKnownOutNodeForStep ( Endpoint e ) {
374
- e .asExpr ( ) instanceof Call or // we just assume flow in that case
375
- TaintTracking:: localTaintStep ( _, e ) or
376
- FlowSummaryImpl:: Private:: Steps:: summaryThroughStepValue ( _, e , _) or
377
- FlowSummaryImpl:: Private:: Steps:: summaryThroughStepTaint ( _, e , _) or
378
- FlowSummaryImpl:: Private:: Steps:: summaryGetterStep ( _, _, e , _) or
379
- FlowSummaryImpl:: Private:: Steps:: summarySetterStep ( _, _, e , _)
416
+ e .asNode ( ) . asExpr ( ) instanceof Call or // we just assume flow in that case
417
+ TaintTracking:: localTaintStep ( _, e . asNode ( ) ) or
418
+ FlowSummaryImpl:: Private:: Steps:: summaryThroughStepValue ( _, e . asNode ( ) , _) or
419
+ FlowSummaryImpl:: Private:: Steps:: summaryThroughStepTaint ( _, e . asNode ( ) , _) or
420
+ FlowSummaryImpl:: Private:: Steps:: summaryGetterStep ( _, _, e . asNode ( ) , _) or
421
+ FlowSummaryImpl:: Private:: Steps:: summarySetterStep ( _, _, e . asNode ( ) , _)
380
422
}
381
423
}
382
424
0 commit comments