Skip to content

Commit 1857a5d

Browse files
committed
Refactor Intent flow steps
1 parent 00b0a6b commit 1857a5d

File tree

1 file changed

+59
-56
lines changed
  • java/ql/lib/semmle/code/java/frameworks/android

1 file changed

+59
-56
lines changed

java/ql/lib/semmle/code/java/frameworks/android/Intent.qll

Lines changed: 59 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -249,88 +249,91 @@ class GrantWriteUriPermissionFlag extends GrantUriPermissionFlag {
249249
GrantWriteUriPermissionFlag() { this.hasName("FLAG_GRANT_WRITE_URI_PERMISSION") }
250250
}
251251

252+
/** The instantiation of an `android.content.Intent` instance. */
253+
private class NewIntent extends ClassInstanceExpr {
254+
NewIntent() { this.getConstructedType() instanceof TypeIntent }
255+
256+
/** Gets the `Class<?>` argument of this call. */
257+
Argument getClassArg() {
258+
result.getType() instanceof TypeClass and
259+
result = this.getAnArgument()
260+
}
261+
}
262+
263+
/** A call to a method that starts an Android component */
264+
private class StartComponentMethodAccess extends MethodAccess {
265+
StartComponentMethodAccess() {
266+
this.getMethod().overrides*(any(StartActivityMethod m)) or
267+
this.getMethod().overrides*(any(StartServiceMethod m)) or
268+
this.getMethod().overrides*(any(SendBroadcastMethod m))
269+
}
270+
271+
/** Gets the intent argument of this call. */
272+
Argument getIntentArg() {
273+
result.getType() instanceof TypeIntent and
274+
result = this.getAnArgument()
275+
}
276+
277+
/** Holds if this targets a component of type `targetType`. */
278+
predicate targetsComponentType(RefType targetType) {
279+
exists(NewIntent newIntent |
280+
DataFlow::localExprFlow(newIntent, this.getIntentArg()) and
281+
newIntent.getClassArg().getType().(ParameterizedType).getATypeArgument() = targetType
282+
)
283+
}
284+
}
285+
252286
/**
253-
* Gets the `Class<?>` argument of an `android.content.Intent`constructor.
254-
*
255-
* The `android.content.Intent` class has two constructors with an argument of type
256-
* `Class<?>`. One has the argument at position 1 and the other at position 3.
257-
* https://developer.android.com/reference/android/content/Intent#public-constructors
287+
* Holds if there is a step from the intent argument `n1` of a `startActivity` call
288+
* to a `getIntent` call `n2` in the activity `n1` targets.
258289
*/
259-
private Argument getClassArgOfIntentConstructor(ClassInstanceExpr classInstanceExpr) {
260-
classInstanceExpr.getConstructedType() instanceof TypeIntent and
261-
if classInstanceExpr.getNumArgument() = 2
262-
then result = classInstanceExpr.getArgument(1)
263-
else result = classInstanceExpr.getArgument(3)
290+
private predicate startActivityIntentStep(DataFlow::Node n1, DataFlow::Node n2) {
291+
exists(StartComponentMethodAccess startActivity, MethodAccess getIntent |
292+
startActivity.getMethod().overrides*(any(StartActivityMethod m)) and
293+
getIntent.getMethod().overrides*(any(AndroidGetIntentMethod m)) and
294+
startActivity.targetsComponentType(getIntent.getReceiverType()) and
295+
n1.asExpr() = startActivity.getIntentArg() and
296+
n2.asExpr() = getIntent
297+
)
264298
}
265299

266300
/**
267-
* A value-preserving step from the Intent argument of a `startActivity` call to
268-
* a `getIntent` call in the Activity the Intent pointed to in its constructor.
301+
* A value-preserving step from the intent argument of a `startActivity` call to
302+
* a `getIntent` call in the activity the intent targeted in its constructor.
269303
*/
270304
private class StartActivityIntentStep extends AdditionalValueStep {
271-
/**
272-
* Gets the `Intent` argument of an Android `StartActivityMethod`.
273-
*
274-
* The `startActivityFromChild` and `startActivityFromFragment` methods have
275-
* an argument of type `Intent` at position 1, but the rest of the methods of
276-
* type `StartActivityMethod` have an argument of type `Intent` at position 0.
277-
*/
278-
private Argument getIntentArgOfStartActMethod(MethodAccess methodAccess) {
279-
methodAccess.getMethod().overrides*(any(StartActivityMethod m)) and
280-
if methodAccess.getMethod().hasName(["startActivityFromChild", "startActivityFromFragment"])
281-
then result = methodAccess.getArgument(1)
282-
else result = methodAccess.getArgument(0)
283-
}
284-
285-
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
286-
exists(MethodAccess startActivity, MethodAccess getIntent, ClassInstanceExpr newIntent |
287-
startActivity.getMethod().overrides*(any(StartActivityMethod m)) and
288-
getIntent.getMethod().overrides*(any(AndroidGetIntentMethod m)) and
289-
newIntent.getConstructedType() instanceof TypeIntent and
290-
DataFlow::localExprFlow(newIntent, this.getIntentArgOfStartActMethod(startActivity)) and
291-
getClassArgOfIntentConstructor(newIntent).getType().(ParameterizedType).getATypeArgument() =
292-
getIntent.getReceiverType() and
293-
n1.asExpr() = this.getIntentArgOfStartActMethod(startActivity) and
294-
n2.asExpr() = getIntent
295-
)
296-
}
305+
override predicate step(DataFlow::Node n1, DataFlow::Node n2) { startActivityIntentStep(n1, n2) }
297306
}
298307

299308
/**
300-
* A value-preserving step from the Intent argument of a `sendBroadcast` call to
301-
* the `Intent` parameter in the `onReceive` method of the BroadcastReceiver the
302-
* Intent pointed to in its constructor.
309+
* A value-preserving step from the intent argument of a `sendBroadcast` call to
310+
* the intent parameter in the `onReceive` method of the receiver the
311+
* intent targeted in its constructor.
303312
*/
304313
private class SendBroadcastReceiverIntentStep extends AdditionalValueStep {
305314
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
306-
exists(MethodAccess sendBroadcast, Method onReceive, ClassInstanceExpr newIntent |
315+
exists(StartComponentMethodAccess sendBroadcast, Method onReceive |
307316
sendBroadcast.getMethod().overrides*(any(SendBroadcastMethod m)) and
308317
onReceive.overrides*(any(AndroidReceiveIntentMethod m)) and
309-
newIntent.getConstructedType() instanceof TypeIntent and
310-
DataFlow::localExprFlow(newIntent, sendBroadcast.getArgument(0)) and
311-
getClassArgOfIntentConstructor(newIntent).getType().(ParameterizedType).getATypeArgument() =
312-
onReceive.getDeclaringType() and
313-
n1.asExpr() = sendBroadcast.getArgument(0) and
318+
sendBroadcast.targetsComponentType(onReceive.getDeclaringType()) and
319+
n1.asExpr() = sendBroadcast.getIntentArg() and
314320
n2.asParameter() = onReceive.getParameter(1)
315321
)
316322
}
317323
}
318324

319325
/**
320-
* A value-preserving step from the Intent argument of a `startService` call to
321-
* the `Intent` parameter in an `AndroidServiceIntentMethod` of the Service the
322-
* Intent pointed to in its constructor.
326+
* A value-preserving step from the intent argument of a `startService` call to
327+
* the intent parameter in an `AndroidServiceIntentMethod` of the service the
328+
* intent targeted in its constructor.
323329
*/
324330
private class StartServiceIntentStep extends AdditionalValueStep {
325331
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
326-
exists(MethodAccess startService, Method serviceIntent, ClassInstanceExpr newIntent |
332+
exists(StartComponentMethodAccess startService, Method serviceIntent |
327333
startService.getMethod().overrides*(any(StartServiceMethod m)) and
328334
serviceIntent.overrides*(any(AndroidServiceIntentMethod m)) and
329-
newIntent.getConstructedType() instanceof TypeIntent and
330-
DataFlow::localExprFlow(newIntent, startService.getArgument(0)) and
331-
getClassArgOfIntentConstructor(newIntent).getType().(ParameterizedType).getATypeArgument() =
332-
serviceIntent.getDeclaringType() and
333-
n1.asExpr() = startService.getArgument(0) and
335+
startService.targetsComponentType(serviceIntent.getDeclaringType()) and
336+
n1.asExpr() = startService.getIntentArg() and
334337
n2.asParameter() = serviceIntent.getParameter(0)
335338
)
336339
}

0 commit comments

Comments
 (0)