@@ -3,9 +3,7 @@ private import semmle.code.java.dataflow.DataFlow
3
3
private import semmle.code.java.dataflow.ExternalFlow
4
4
private import semmle.code.java.dataflow.FlowSteps
5
5
6
- /**
7
- * The class `android.content.Intent`.
8
- */
6
+ /** The class `android.content.Intent`. */
9
7
class TypeIntent extends Class {
10
8
TypeIntent ( ) { this .hasQualifiedName ( "android.content" , "Intent" ) }
11
9
}
@@ -15,49 +13,37 @@ class TypeComponentName extends Class {
15
13
TypeComponentName ( ) { this .hasQualifiedName ( "android.content" , "ComponentName" ) }
16
14
}
17
15
18
- /**
19
- * The class `android.app.Activity`.
20
- */
16
+ /** The class `android.app.Activity`. */
21
17
class TypeActivity extends Class {
22
18
TypeActivity ( ) { this .hasQualifiedName ( "android.app" , "Activity" ) }
23
19
}
24
20
25
- /**
26
- * The class `android.app.Service`.
27
- */
21
+ /** The class `android.app.Service`. */
28
22
class TypeService extends Class {
29
23
TypeService ( ) { this .hasQualifiedName ( "android.app" , "Service" ) }
30
24
}
31
25
32
- /**
33
- * The class `android.content.Context`.
34
- */
26
+ /** The class `android.content.Context`. */
35
27
class TypeContext extends RefType {
36
28
// Not inlining this makes it more likely to be used as a sentinel,
37
29
// which is useful when running Android queries on non-Android projects.
38
30
pragma [ noinline]
39
31
TypeContext ( ) { this .hasQualifiedName ( "android.content" , "Context" ) }
40
32
}
41
33
42
- /**
43
- * The class `android.content.BroadcastReceiver`.
44
- */
34
+ /** The class `android.content.BroadcastReceiver`. */
45
35
class TypeBroadcastReceiver extends Class {
46
36
TypeBroadcastReceiver ( ) { this .hasQualifiedName ( "android.content" , "BroadcastReceiver" ) }
47
37
}
48
38
49
- /**
50
- * The method `Activity.getIntent`
51
- */
39
+ /** The method `Activity.getIntent` */
52
40
class AndroidGetIntentMethod extends Method {
53
41
AndroidGetIntentMethod ( ) {
54
42
this .hasName ( "getIntent" ) and this .getDeclaringType ( ) instanceof TypeActivity
55
43
}
56
44
}
57
45
58
- /**
59
- * The method `BroadcastReceiver.onReceive`.
60
- */
46
+ /** The method `BroadcastReceiver.onReceive`. */
61
47
class AndroidReceiveIntentMethod extends Method {
62
48
AndroidReceiveIntentMethod ( ) {
63
49
this .hasName ( "onReceive" ) and this .getDeclaringType ( ) instanceof TypeBroadcastReceiver
@@ -77,25 +63,68 @@ class AndroidServiceIntentMethod extends Method {
77
63
78
64
/**
79
65
* The method `Context.startActivity` or `startActivities`.
66
+ *
67
+ * DEPRECATED: Use `StartActivityMethod` instead.
80
68
*/
81
- class ContextStartActivityMethod extends Method {
69
+ deprecated class ContextStartActivityMethod extends Method {
82
70
ContextStartActivityMethod ( ) {
83
71
( this .hasName ( "startActivity" ) or this .hasName ( "startActivities" ) ) and
84
72
this .getDeclaringType ( ) instanceof TypeContext
85
73
}
86
74
}
87
75
88
76
/**
89
- * Specifies that if an `Intent` is tainted, then so are its synthetic fields.
77
+ * The method `Context.startActivity`, `Context.startActivities`,
78
+ * `Activity.startActivity`,`Activity.startActivities`,
79
+ * `Activity.startActivityForResult`, `Activity.startActivityIfNeeded`,
80
+ * `Activity.startNextMatchingActivity`, `Activity.startActivityFromChild`,
81
+ * or `Activity.startActivityFromFragment`.
90
82
*/
83
+ class StartActivityMethod extends Method {
84
+ StartActivityMethod ( ) {
85
+ this .getName ( ) .matches ( "start%Activit%" ) and
86
+ (
87
+ this .getDeclaringType ( ) instanceof TypeContext or
88
+ this .getDeclaringType ( ) instanceof TypeActivity
89
+ )
90
+ }
91
+ }
92
+
93
+ /**
94
+ * The method `Context.sendBroadcast`, `sendBroadcastAsUser`,
95
+ * `sendOrderedBroadcast`, `sendOrderedBroadcastAsUser`,
96
+ * `sendStickyBroadcast`, `sendStickyBroadcastAsUser`,
97
+ * `sendStickyOrderedBroadcast`, `sendStickyOrderedBroadcastAsUser`,
98
+ * or `sendBroadcastWithMultiplePermissions`.
99
+ */
100
+ class SendBroadcastMethod extends Method {
101
+ SendBroadcastMethod ( ) {
102
+ this .getName ( ) .matches ( "send%Broadcast%" ) and
103
+ this .getDeclaringType ( ) instanceof TypeContext
104
+ }
105
+ }
106
+
107
+ /**
108
+ * The method `Context.startService`, `startForegroundService`,
109
+ * `bindIsolatedService`, `bindService`, or `bindServiceAsUser`.
110
+ */
111
+ class StartServiceMethod extends Method {
112
+ StartServiceMethod ( ) {
113
+ this .hasName ( [
114
+ "startService" , "startForegroundService" , "bindIsolatedService" , "bindService" ,
115
+ "bindServiceAsUser"
116
+ ] ) and
117
+ this .getDeclaringType ( ) instanceof TypeContext
118
+ }
119
+ }
120
+
121
+ /** Specifies that if an `Intent` is tainted, then so are its synthetic fields. */
91
122
private class IntentFieldsInheritTaint extends DataFlow:: SyntheticFieldContent ,
92
123
TaintInheritingContent {
93
124
IntentFieldsInheritTaint ( ) { this .getField ( ) .matches ( "android.content.Intent.%" ) }
94
125
}
95
126
96
- /**
97
- * The method `Intent.getParcelableExtra`.
98
- */
127
+ /** The method `Intent.getParcelableExtra`. */
99
128
class IntentGetParcelableExtraMethod extends Method {
100
129
IntentGetParcelableExtraMethod ( ) {
101
130
this .hasName ( "getParcelableExtra" ) and
@@ -157,9 +186,7 @@ private class BundleExtrasSyntheticField extends SyntheticField {
157
186
override RefType getType ( ) { result instanceof AndroidBundle }
158
187
}
159
188
160
- /**
161
- * Holds if extras may be implicitly read from the Intent `node`.
162
- */
189
+ /** Holds if extras may be implicitly read from the Intent `node`. */
163
190
predicate allowIntentExtrasImplicitRead ( DataFlow:: Node node , DataFlow:: Content c ) {
164
191
node .getType ( ) instanceof TypeIntent and
165
192
(
@@ -194,25 +221,90 @@ class GrantWriteUriPermissionFlag extends GrantUriPermissionFlag {
194
221
GrantWriteUriPermissionFlag ( ) { this .hasName ( "FLAG_GRANT_WRITE_URI_PERMISSION" ) }
195
222
}
196
223
224
+ /** An instantiation of `android.content.Intent`. */
225
+ private class NewIntent extends ClassInstanceExpr {
226
+ NewIntent ( ) { this .getConstructedType ( ) instanceof TypeIntent }
227
+
228
+ /** Gets the `Class<?>` argument of this call. */
229
+ Argument getClassArg ( ) {
230
+ result .getType ( ) instanceof TypeClass and
231
+ result = this .getAnArgument ( )
232
+ }
233
+ }
234
+
235
+ /** A call to a method that starts an Android component. */
236
+ private class StartComponentMethodAccess extends MethodAccess {
237
+ StartComponentMethodAccess ( ) {
238
+ this .getMethod ( ) .overrides * ( any ( StartActivityMethod m ) ) or
239
+ this .getMethod ( ) .overrides * ( any ( StartServiceMethod m ) ) or
240
+ this .getMethod ( ) .overrides * ( any ( SendBroadcastMethod m ) )
241
+ }
242
+
243
+ /** Gets the intent argument of this call. */
244
+ Argument getIntentArg ( ) {
245
+ result .getType ( ) instanceof TypeIntent and
246
+ result = this .getAnArgument ( )
247
+ }
248
+
249
+ /** Holds if this targets a component of type `targetType`. */
250
+ predicate targetsComponentType ( RefType targetType ) {
251
+ exists ( NewIntent newIntent |
252
+ DataFlow:: localExprFlow ( newIntent , this .getIntentArg ( ) ) and
253
+ newIntent .getClassArg ( ) .getType ( ) .( ParameterizedType ) .getATypeArgument ( ) = targetType
254
+ )
255
+ }
256
+ }
257
+
197
258
/**
198
- * A value-preserving step from the Intent argument of a `startActivity` call to
199
- * a `getIntent` call in the Activity the Intent pointed to in its constructor.
259
+ * A value-preserving step from the intent argument of a `startActivity` call to
260
+ * a `getIntent` call in the activity the intent targeted in its constructor.
200
261
*/
201
262
private class StartActivityIntentStep extends AdditionalValueStep {
202
263
override predicate step ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
203
- exists ( MethodAccess startActivity , MethodAccess getIntent , ClassInstanceExpr newIntent |
204
- startActivity .getMethod ( ) .overrides * ( any ( ContextStartActivityMethod m ) ) and
264
+ exists ( StartComponentMethodAccess startActivity , MethodAccess getIntent |
265
+ startActivity .getMethod ( ) .overrides * ( any ( StartActivityMethod m ) ) and
205
266
getIntent .getMethod ( ) .overrides * ( any ( AndroidGetIntentMethod m ) ) and
206
- newIntent .getConstructedType ( ) instanceof TypeIntent and
207
- DataFlow:: localExprFlow ( newIntent , startActivity .getArgument ( 0 ) ) and
208
- newIntent .getArgument ( 1 ) .getType ( ) .( ParameterizedType ) .getATypeArgument ( ) =
209
- getIntent .getReceiverType ( ) and
210
- n1 .asExpr ( ) = startActivity .getArgument ( 0 ) and
267
+ startActivity .targetsComponentType ( getIntent .getReceiverType ( ) ) and
268
+ n1 .asExpr ( ) = startActivity .getIntentArg ( ) and
211
269
n2 .asExpr ( ) = getIntent
212
270
)
213
271
}
214
272
}
215
273
274
+ /**
275
+ * A value-preserving step from the intent argument of a `sendBroadcast` call to
276
+ * the intent parameter in the `onReceive` method of the receiver the
277
+ * intent targeted in its constructor.
278
+ */
279
+ private class SendBroadcastReceiverIntentStep extends AdditionalValueStep {
280
+ override predicate step ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
281
+ exists ( StartComponentMethodAccess sendBroadcast , Method onReceive |
282
+ sendBroadcast .getMethod ( ) .overrides * ( any ( SendBroadcastMethod m ) ) and
283
+ onReceive .overrides * ( any ( AndroidReceiveIntentMethod m ) ) and
284
+ sendBroadcast .targetsComponentType ( onReceive .getDeclaringType ( ) ) and
285
+ n1 .asExpr ( ) = sendBroadcast .getIntentArg ( ) and
286
+ n2 .asParameter ( ) = onReceive .getParameter ( 1 )
287
+ )
288
+ }
289
+ }
290
+
291
+ /**
292
+ * A value-preserving step from the intent argument of a `startService` call to
293
+ * the intent parameter in an `AndroidServiceIntentMethod` of the service the
294
+ * intent targeted in its constructor.
295
+ */
296
+ private class StartServiceIntentStep extends AdditionalValueStep {
297
+ override predicate step ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
298
+ exists ( StartComponentMethodAccess startService , Method serviceIntent |
299
+ startService .getMethod ( ) .overrides * ( any ( StartServiceMethod m ) ) and
300
+ serviceIntent .overrides * ( any ( AndroidServiceIntentMethod m ) ) and
301
+ startService .targetsComponentType ( serviceIntent .getDeclaringType ( ) ) and
302
+ n1 .asExpr ( ) = startService .getIntentArg ( ) and
303
+ n2 .asParameter ( ) = serviceIntent .getParameter ( 0 )
304
+ )
305
+ }
306
+ }
307
+
216
308
private class IntentBundleFlowSteps extends SummaryModelCsv {
217
309
override predicate row ( string row ) {
218
310
row =
0 commit comments