mirror of
https://github.com/github/codeql.git
synced 2026-04-28 02:05:14 +02:00
Merge pull request #1436 from yh-semmle/java-android-manifest
Approved by aschackmull
This commit is contained in:
54
java/ql/src/semmle/code/java/frameworks/android/Android.qll
Normal file
54
java/ql/src/semmle/code/java/frameworks/android/Android.qll
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Provides classes and predicates for working with Android components.
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.xml.AndroidManifest
|
||||
|
||||
/**
|
||||
* An Android component. That is, either an activity, a service,
|
||||
* a broadcast receiver, or a content provider.
|
||||
*/
|
||||
class AndroidComponent extends Class {
|
||||
AndroidComponent() {
|
||||
this.getASupertype*().hasQualifiedName("android.app", "Activity") or
|
||||
this.getASupertype*().hasQualifiedName("android.app", "Service") or
|
||||
this.getASupertype*().hasQualifiedName("android.content", "BroadcastReceiver") or
|
||||
this.getASupertype*().hasQualifiedName("android.content", "ContentProvider")
|
||||
}
|
||||
|
||||
/** The XML element corresponding to this Android component. */
|
||||
AndroidComponentXmlElement getAndroidComponentXmlElement() {
|
||||
result.getResolvedComponentName() = this.getQualifiedName()
|
||||
}
|
||||
|
||||
/** Holds if this Android component is configured as `exported` in an `AndroidManifest.xml` file. */
|
||||
predicate isExported() { getAndroidComponentXmlElement().isExported() }
|
||||
|
||||
/** Holds if this Android component has an intent filter configured in an `AndroidManifest.xml` file. */
|
||||
predicate hasIntentFilter() { exists(getAndroidComponentXmlElement().getAnIntentFilterElement()) }
|
||||
}
|
||||
|
||||
/** An Android activity. */
|
||||
class AndroidActivity extends AndroidComponent {
|
||||
AndroidActivity() { this.getASupertype*().hasQualifiedName("android.app", "Activity") }
|
||||
}
|
||||
|
||||
/** An Android service. */
|
||||
class AndroidService extends AndroidComponent {
|
||||
AndroidService() { this.getASupertype*().hasQualifiedName("android.app", "Service") }
|
||||
}
|
||||
|
||||
/** An Android broadcast receiver. */
|
||||
class AndroidBroadcastReceiver extends AndroidComponent {
|
||||
AndroidBroadcastReceiver() {
|
||||
this.getASupertype*().hasQualifiedName("android.content", "BroadcastReceiver")
|
||||
}
|
||||
}
|
||||
|
||||
/** An Android content provider. */
|
||||
class AndroidContentProvider extends AndroidComponent {
|
||||
AndroidContentProvider() {
|
||||
this.getASupertype*().hasQualifiedName("android.content", "ContentProvider")
|
||||
}
|
||||
}
|
||||
178
java/ql/src/semmle/code/xml/AndroidManifest.qll
Normal file
178
java/ql/src/semmle/code/xml/AndroidManifest.qll
Normal file
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* Provides classes and predicates for working with Android manifest files.
|
||||
*/
|
||||
|
||||
import XML
|
||||
|
||||
/**
|
||||
* An Android manifest file, named `AndroidManifest.xml`.
|
||||
*/
|
||||
class AndroidManifestXmlFile extends XMLFile {
|
||||
AndroidManifestXmlFile() {
|
||||
this.getBaseName() = "AndroidManifest.xml" and
|
||||
count(XMLElement e | e = this.getAChild()) = 1 and
|
||||
this.getAChild().getName() = "manifest"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the top-level `<manifest>` element in this Android manifest file.
|
||||
*/
|
||||
AndroidManifestXmlElement getManifestElement() { result = this.getAChild() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `<manifest>` element in an Android manifest file.
|
||||
*/
|
||||
class AndroidManifestXmlElement extends XMLElement {
|
||||
AndroidManifestXmlElement() {
|
||||
this.getParent() instanceof AndroidManifestXmlFile and this.getName() = "manifest"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `<application>` child element of this `<manifest>` element.
|
||||
*/
|
||||
AndroidApplicationXmlElement getApplicationElement() { result = this.getAChild() }
|
||||
|
||||
/**
|
||||
* Gets the value of the `package` attribute of this `<manifest>` element.
|
||||
*/
|
||||
string getPackageAttributeValue() { result = getAttributeValue("package") }
|
||||
}
|
||||
|
||||
/**
|
||||
* An `<application>` element in an Android manifest file.
|
||||
*/
|
||||
class AndroidApplicationXmlElement extends XMLElement {
|
||||
AndroidApplicationXmlElement() {
|
||||
this.getParent() instanceof AndroidManifestXmlElement and this.getName() = "application"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a component child element of this `<application>` element.
|
||||
*/
|
||||
AndroidComponentXmlElement getAComponentElement() { result = this.getAChild() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An `<activity>` element in an Android manifest file.
|
||||
*/
|
||||
class AndroidActivityXmlElement extends AndroidComponentXmlElement {
|
||||
AndroidActivityXmlElement() { this.getName() = "activity" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `<service>` element in an Android manifest file.
|
||||
*/
|
||||
class AndroidServiceXmlElement extends AndroidComponentXmlElement {
|
||||
AndroidServiceXmlElement() { this.getName() = "service" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `<receiver>` element in an Android manifest file.
|
||||
*/
|
||||
class AndroidReceiverXmlElement extends AndroidComponentXmlElement {
|
||||
AndroidReceiverXmlElement() { this.getName() = "receiver" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `<provider>` element in an Android manifest file.
|
||||
*/
|
||||
class AndroidProviderXmlElement extends AndroidComponentXmlElement {
|
||||
AndroidProviderXmlElement() { this.getName() = "provider" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An Android component element in an Android manifest file.
|
||||
*/
|
||||
class AndroidComponentXmlElement extends XMLElement {
|
||||
AndroidComponentXmlElement() {
|
||||
this.getParent() instanceof AndroidApplicationXmlElement and
|
||||
this.getName().regexpMatch("(activity|service|receiver|provider)")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an `<intent-filter>` child element of this component element.
|
||||
*/
|
||||
AndroidIntentFilterXmlElement getAnIntentFilterElement() { result = this.getAChild() }
|
||||
|
||||
/**
|
||||
* Gets the value of the `android:name` attribute of this component element.
|
||||
*/
|
||||
string getComponentName() {
|
||||
exists(XMLAttribute attr |
|
||||
attr = getAnAttribute() and
|
||||
attr.getNamespace().getPrefix() = "android" and
|
||||
attr.getName() = "name"
|
||||
|
|
||||
result = attr.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the resolved value of the `android:name` attribute of this component element.
|
||||
*/
|
||||
string getResolvedComponentName() {
|
||||
if getComponentName().matches(".%")
|
||||
then
|
||||
result = getParent()
|
||||
.(XMLElement)
|
||||
.getParent()
|
||||
.(AndroidManifestXmlElement)
|
||||
.getPackageAttributeValue() + getComponentName()
|
||||
else result = getComponentName()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the `android:exported` attribute of this component element.
|
||||
*/
|
||||
string getExportedAttributeValue() {
|
||||
exists(XMLAttribute attr |
|
||||
attr = getAnAttribute() and
|
||||
attr.getNamespace().getPrefix() = "android" and
|
||||
attr.getName() = "exported"
|
||||
|
|
||||
result = attr.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the `android:exported` attribute of this component element is `true`.
|
||||
*/
|
||||
predicate isExported() { getExportedAttributeValue() = "true" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An `<intent-filter>` element in an Android manifest file.
|
||||
*/
|
||||
class AndroidIntentFilterXmlElement extends XMLElement {
|
||||
AndroidIntentFilterXmlElement() {
|
||||
this.getFile() instanceof AndroidManifestXmlFile and this.getName() = "intent-filter"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an `<action>` child element of this `<intent-filter>` element.
|
||||
*/
|
||||
AndroidActionXmlElement getAnActionElement() { result = this.getAChild() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An `<action>` element in an Android manifest file.
|
||||
*/
|
||||
class AndroidActionXmlElement extends XMLElement {
|
||||
AndroidActionXmlElement() {
|
||||
this.getFile() instanceof AndroidManifestXmlFile and this.getName() = "action"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this action.
|
||||
*/
|
||||
string getActionName() {
|
||||
exists(XMLAttribute attr |
|
||||
attr = getAnAttribute() and
|
||||
attr.getNamespace().getPrefix() = "android" and
|
||||
attr.getName() = "name"
|
||||
|
|
||||
result = attr.getValue()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0"
|
||||
package="com.example.myapp">
|
||||
|
||||
<!-- Beware that these values are overridden by the build.gradle file -->
|
||||
<uses-sdk android:minSdkVersion="15" android:targetSdkVersion="26" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
|
||||
<!-- This name is resolved to com.example.myapp.MainActivity
|
||||
based upon the package attribute -->
|
||||
<activity android:name=".MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".DisplayMessageActivity"
|
||||
android:parentActivityName=".MainActivity" />
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
<!--
|
||||
/*
|
||||
* This file is licensed under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
-->
|
||||
@@ -0,0 +1 @@
|
||||
class Test {}
|
||||
@@ -0,0 +1 @@
|
||||
| com.example.myapp.MainActivity | android.intent.action.MAIN |
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
import semmle.code.xml.AndroidManifest
|
||||
|
||||
from AndroidActivityXmlElement e
|
||||
select e.getResolvedComponentName(), e.getAnIntentFilterElement().getAnActionElement().getActionName()
|
||||
Reference in New Issue
Block a user