@@ -3,9 +3,7 @@ private import semmle.code.java.dataflow.DataFlow
33private import semmle.code.java.dataflow.ExternalFlow
44private import semmle.code.java.dataflow.FlowSteps
55
6- /**
7- * The class `android.content.Intent`.
8- */
6+ /** The class `android.content.Intent`. */
97class TypeIntent extends Class {
108 TypeIntent ( ) { this .hasQualifiedName ( "android.content" , "Intent" ) }
119}
@@ -15,49 +13,37 @@ class TypeComponentName extends Class {
1513 TypeComponentName ( ) { this .hasQualifiedName ( "android.content" , "ComponentName" ) }
1614}
1715
18- /**
19- * The class `android.app.Activity`.
20- */
16+ /** The class `android.app.Activity`. */
2117class TypeActivity extends Class {
2218 TypeActivity ( ) { this .hasQualifiedName ( "android.app" , "Activity" ) }
2319}
2420
25- /**
26- * The class `android.app.Service`.
27- */
21+ /** The class `android.app.Service`. */
2822class TypeService extends Class {
2923 TypeService ( ) { this .hasQualifiedName ( "android.app" , "Service" ) }
3024}
3125
32- /**
33- * The class `android.content.Context`.
34- */
26+ /** The class `android.content.Context`. */
3527class TypeContext extends RefType {
3628 // Not inlining this makes it more likely to be used as a sentinel,
3729 // which is useful when running Android queries on non-Android projects.
3830 pragma [ noinline]
3931 TypeContext ( ) { this .hasQualifiedName ( "android.content" , "Context" ) }
4032}
4133
42- /**
43- * The class `android.content.BroadcastReceiver`.
44- */
34+ /** The class `android.content.BroadcastReceiver`. */
4535class TypeBroadcastReceiver extends Class {
4636 TypeBroadcastReceiver ( ) { this .hasQualifiedName ( "android.content" , "BroadcastReceiver" ) }
4737}
4838
49- /**
50- * The method `Activity.getIntent`
51- */
39+ /** The method `Activity.getIntent` */
5240class AndroidGetIntentMethod extends Method {
5341 AndroidGetIntentMethod ( ) {
5442 this .hasName ( "getIntent" ) and this .getDeclaringType ( ) instanceof TypeActivity
5543 }
5644}
5745
58- /**
59- * The method `BroadcastReceiver.onReceive`.
60- */
46+ /** The method `BroadcastReceiver.onReceive`. */
6147class AndroidReceiveIntentMethod extends Method {
6248 AndroidReceiveIntentMethod ( ) {
6349 this .hasName ( "onReceive" ) and this .getDeclaringType ( ) instanceof TypeBroadcastReceiver
@@ -77,25 +63,68 @@ class AndroidServiceIntentMethod extends Method {
7763
7864/**
7965 * The method `Context.startActivity` or `startActivities`.
66+ *
67+ * DEPRECATED: Use `StartActivityMethod` instead.
8068 */
81- class ContextStartActivityMethod extends Method {
69+ deprecated class ContextStartActivityMethod extends Method {
8270 ContextStartActivityMethod ( ) {
8371 ( this .hasName ( "startActivity" ) or this .hasName ( "startActivities" ) ) and
8472 this .getDeclaringType ( ) instanceof TypeContext
8573 }
8674}
8775
8876/**
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`.
9082 */
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. */
91122private class IntentFieldsInheritTaint extends DataFlow:: SyntheticFieldContent ,
92123 TaintInheritingContent {
93124 IntentFieldsInheritTaint ( ) { this .getField ( ) .matches ( "android.content.Intent.%" ) }
94125}
95126
96- /**
97- * The method `Intent.getParcelableExtra`.
98- */
127+ /** The method `Intent.getParcelableExtra`. */
99128class IntentGetParcelableExtraMethod extends Method {
100129 IntentGetParcelableExtraMethod ( ) {
101130 this .hasName ( "getParcelableExtra" ) and
@@ -157,9 +186,7 @@ private class BundleExtrasSyntheticField extends SyntheticField {
157186 override RefType getType ( ) { result instanceof AndroidBundle }
158187}
159188
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`. */
163190predicate allowIntentExtrasImplicitRead ( DataFlow:: Node node , DataFlow:: Content c ) {
164191 node .getType ( ) instanceof TypeIntent and
165192 (
@@ -194,25 +221,90 @@ class GrantWriteUriPermissionFlag extends GrantUriPermissionFlag {
194221 GrantWriteUriPermissionFlag ( ) { this .hasName ( "FLAG_GRANT_WRITE_URI_PERMISSION" ) }
195222}
196223
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+
197258/**
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.
200261 */
201262private class StartActivityIntentStep extends AdditionalValueStep {
202263 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
205266 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
211269 n2 .asExpr ( ) = getIntent
212270 )
213271 }
214272}
215273
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+
216308private class IntentBundleFlowSteps extends SummaryModelCsv {
217309 override predicate row ( string row ) {
218310 row =
0 commit comments