mirror of
https://github.com/github/codeql.git
synced 2026-05-01 03:35:13 +02:00
Merge pull request #10865 from egregius313/egregius313/android-activity-alias
Java: Add library support for activity-alias elements in AndroidManifest.qll
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added support for Android Manifest `<activity-aliases>` elements in data flow sources.
|
||||
@@ -26,7 +26,12 @@ class AndroidComponent extends Class {
|
||||
|
||||
/** The XML element corresponding to this Android component. */
|
||||
AndroidComponentXmlElement getAndroidComponentXmlElement() {
|
||||
result.getResolvedComponentName() = this.getQualifiedName()
|
||||
// Find an element with an identifier matching the qualified name of the component.
|
||||
// Aliases have two identifiers (name and target), so check both identifiers (if present).
|
||||
exists(AndroidIdentifierXmlAttribute identifier |
|
||||
identifier = result.getAnAttribute() and
|
||||
result.getResolvedIdentifier(identifier) = this.getQualifiedName()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this Android component is configured as `exported` in an `AndroidManifest.xml` file. */
|
||||
@@ -52,6 +57,12 @@ class ExportableAndroidComponent extends AndroidComponent {
|
||||
or
|
||||
this.hasIntentFilter() and
|
||||
not this.getAndroidComponentXmlElement().isNotExported()
|
||||
or
|
||||
exists(AndroidActivityAliasXmlElement e |
|
||||
e = this.getAndroidComponentXmlElement() and
|
||||
not e.isNotExported() and
|
||||
e.hasAnIntentFilterElement()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -129,6 +129,42 @@ class AndroidApplicationXmlElement extends XmlElement {
|
||||
*/
|
||||
class AndroidActivityXmlElement extends AndroidComponentXmlElement {
|
||||
AndroidActivityXmlElement() { this.getName() = "activity" }
|
||||
|
||||
/**
|
||||
* Gets an `<activity-alias>` element aliasing the activity.
|
||||
*/
|
||||
AndroidActivityAliasXmlElement getAnAlias() {
|
||||
exists(AndroidActivityAliasXmlElement alias | this = alias.getTarget() | result = alias)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An `<activity-alias>` element in an Android manifest file.
|
||||
*/
|
||||
class AndroidActivityAliasXmlElement extends AndroidComponentXmlElement {
|
||||
AndroidActivityAliasXmlElement() { this.getName() = "activity-alias" }
|
||||
|
||||
/**
|
||||
* Get and resolve the name of the target activity from the `android:targetActivity` attribute.
|
||||
*/
|
||||
string getResolvedTargetActivityName() {
|
||||
exists(AndroidXmlAttribute attr |
|
||||
attr = this.getAnAttribute() and attr.getName() = "targetActivity"
|
||||
|
|
||||
result = this.getResolvedIdentifier(attr)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `<activity>` element referenced by the `android:targetActivity` attribute.
|
||||
*/
|
||||
AndroidActivityXmlElement getTarget() {
|
||||
exists(AndroidActivityXmlElement activity |
|
||||
activity.getResolvedComponentName() = this.getResolvedTargetActivityName()
|
||||
|
|
||||
result = activity
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,6 +248,13 @@ class AndroidPermissionXmlAttribute extends XmlAttribute {
|
||||
predicate isWrite() { this.getName() = "writePermission" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The attribute `android:name` or `android:targetActivity`.
|
||||
*/
|
||||
class AndroidIdentifierXmlAttribute extends AndroidXmlAttribute {
|
||||
AndroidIdentifierXmlAttribute() { this.getName() = ["name", "targetActivity"] }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `<path-permission`> element of a `<provider>` in an Android manifest file.
|
||||
*/
|
||||
@@ -228,7 +271,7 @@ class AndroidPathPermissionXmlElement extends XmlElement {
|
||||
class AndroidComponentXmlElement extends XmlElement {
|
||||
AndroidComponentXmlElement() {
|
||||
this.getParent() instanceof AndroidApplicationXmlElement and
|
||||
this.getName().regexpMatch("(activity|service|receiver|provider)")
|
||||
this.getName().regexpMatch("(activity|activity-alias|service|receiver|provider)")
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,19 +297,30 @@ class AndroidComponentXmlElement extends XmlElement {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of an identifier attribute, and tries to resolve it into a fully qualified identifier.
|
||||
*/
|
||||
string getResolvedIdentifier(AndroidIdentifierXmlAttribute identifier) {
|
||||
exists(string name | name = identifier.getValue() |
|
||||
if name.matches(".%")
|
||||
then
|
||||
result =
|
||||
this.getParent()
|
||||
.(XmlElement)
|
||||
.getParent()
|
||||
.(AndroidManifestXmlElement)
|
||||
.getPackageAttributeValue() + name
|
||||
else result = name
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the resolved value of the `android:name` attribute of this component element.
|
||||
*/
|
||||
string getResolvedComponentName() {
|
||||
if this.getComponentName().matches(".%")
|
||||
then
|
||||
result =
|
||||
this.getParent()
|
||||
.(XmlElement)
|
||||
.getParent()
|
||||
.(AndroidManifestXmlElement)
|
||||
.getPackageAttributeValue() + this.getComponentName()
|
||||
else result = this.getComponentName()
|
||||
exists(AndroidXmlAttribute attr | attr = this.getAnAttribute() and attr.getName() = "name" |
|
||||
result = this.getResolvedIdentifier(attr)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.example.myapplication">
|
||||
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
|
||||
android:theme="@style/Theme.MyApplication"
|
||||
tools:targetApi="31">
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.MyApplication.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".AnotherActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.MyApplication.NoActionBar">
|
||||
</activity>
|
||||
|
||||
|
||||
<activity-alias
|
||||
android:name=".MainAlias"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:targetActivity=".MainActivity"></activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".SecondAlias"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:targetActivity=".MainActivity"></activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".AnotherAlias"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:targetActivity="com.example.myapplication.AnotherActivity"></activity-alias>
|
||||
<activity
|
||||
android:name=".ExampleActivity"
|
||||
android:exported="false"
|
||||
android:label="@string/app_name"
|
||||
></activity>
|
||||
|
||||
<activity-alias
|
||||
android:name=".ExampleAlias"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:targetActivity=".ExampleActivity">
|
||||
</activity-alias>
|
||||
|
||||
<activity
|
||||
android:name=".Example2Activity"
|
||||
android:exported="false"
|
||||
android:label="@string/app_name">
|
||||
</activity>
|
||||
|
||||
<activity-alias
|
||||
android:name=".Example2Alias"
|
||||
android:label="@string/app_name"
|
||||
android:targetActivity=".Example2Activity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"></action>
|
||||
<action android:name="android.intent.category.LAUNCHER"></action>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.example.myapplication;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
public class Example2Activity extends Activity {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.example.myapplication;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
public class ExampleActivity extends Activity {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
| .AnotherAlias | .AnotherActivity |
|
||||
| .Example2Alias | .Example2Activity |
|
||||
| .ExampleAlias | .ExampleActivity |
|
||||
| .MainAlias | .MainActivity |
|
||||
| .SecondAlias | .MainActivity |
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
import semmle.code.xml.AndroidManifest
|
||||
|
||||
from AndroidActivityAliasXmlElement alias
|
||||
select alias.getComponentName(), alias.getTarget().getComponentName()
|
||||
@@ -0,0 +1,4 @@
|
||||
| Example2Activity.java:5:14:5:29 | Example2Activity | AndroidManifest.xml:68:9:72:20 | activity |
|
||||
| Example2Activity.java:5:14:5:29 | Example2Activity | AndroidManifest.xml:74:9:82:26 | activity-alias |
|
||||
| ExampleActivity.java:5:14:5:28 | ExampleActivity | AndroidManifest.xml:55:9:59:25 | activity |
|
||||
| ExampleActivity.java:5:14:5:28 | ExampleActivity | AndroidManifest.xml:61:9:66:26 | activity-alias |
|
||||
@@ -0,0 +1,6 @@
|
||||
import java
|
||||
import semmle.code.java.frameworks.android.Android
|
||||
|
||||
from ExportableAndroidComponent component
|
||||
where component.isExported()
|
||||
select component, component.getAndroidComponentXmlElement()
|
||||
@@ -0,0 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/google-android-9.0.0/
|
||||
Reference in New Issue
Block a user